From 365527adbfa8a16dfc05ab71818602f55ada55ba Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Mon, 12 Sep 2005 19:47:07 -0700 Subject: [PATCH 01/13] Fix CDPATH problem. CDPATH has two problems: * It takes scripts to unexpected places (somebody had CDPATH=..:../..:$HOME and the "cd" in git-clone.sh:get_repo_base took him to $HOME/.git when he said "clone foo bar" to clone a repository in "foo" which had "foo/.git"). CDPATH mechanism does not implicitly give "." at the beginning of CDPATH, which is the most irritating part. * The extra echo when it does its thing confuses scripts further. Most of our scripts that use "cd" includes git-sh-setup so the problem is primarily fixed there. git-clone starts without a repository, and it needs its own fix. Signed-off-by: Junio C Hamano --- git-clone.sh | 3 +++ git-sh-setup.sh | 6 ++++++ 2 files changed, 9 insertions(+) diff --git a/git-clone.sh b/git-clone.sh index c07629227..a21f13af2 100755 --- a/git-clone.sh +++ b/git-clone.sh @@ -5,6 +5,9 @@ # # Clone a repository into a different directory that does not yet exist. +# See git-sh-setup why. +unset CDPATH + usage() { echo >&2 "* git clone [-l [-s]] [-q] [-u ] " exit 1 diff --git a/git-sh-setup.sh b/git-sh-setup.sh index 06d8299ce..d5bfa62de 100755 --- a/git-sh-setup.sh +++ b/git-sh-setup.sh @@ -6,6 +6,12 @@ : ${GIT_DIR=.git} : ${GIT_OBJECT_DIRECTORY="$GIT_DIR/objects"} +# Having this variable in your environment would break scripts because +# you would cause "cd" to be be taken to unexpected places. If you +# like CDPATH, define it for your interactive shell sessions without +# exporting it. +unset CDPATH + die() { echo "$@" >&2 exit 1 From 22c67ca88ec65c4f278e8c82b2d98f3bd025238b Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Mon, 12 Sep 2005 22:20:02 -0700 Subject: [PATCH 02/13] Propagate errors from fetch-pack correctly to git-fetch. When git-fetch-pack fails, the command does not notice the failure and instead pretended nothing was fetched and there was nothing wrong. Signed-off-by: Junio C Hamano --- git-fetch.sh | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/git-fetch.sh b/git-fetch.sh index 673a18417..227394403 100755 --- a/git-fetch.sh +++ b/git-fetch.sh @@ -205,9 +205,16 @@ case "$remote" in http://* | https://* | rsync://* ) ;; # we are already done. *) - git-fetch-pack "$remote" $rref | + ( + git-fetch-pack "$remote" $rref || echo failed "$remote" + ) | while read sha1 remote_name do + case "$sha1" in + failed) + echo >&2 "Fetch failure: $remote" + exit 1 ;; + esac found= single_force= for ref in $refs @@ -225,7 +232,7 @@ http://* | https://* | rsync://* ) local_name=$(expr "$found" : '[^:]*:\(.*\)') append_fetch_head "$sha1" "$remote" "$remote_name" "$remote_nick" "$local_name" - done + done || exit ;; esac From f88ed172e7a391bd907798ad2a3347a83cd24317 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Mon, 12 Sep 2005 22:20:42 -0700 Subject: [PATCH 03/13] Fix off-by-one error in git-merge 'git-merge -s' without a strategy name does not fail and does not give usage as it should. Signed-off-by: Junio C Hamano --- git-merge.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/git-merge.sh b/git-merge.sh index a784e0f2c..e51e73499 100755 --- a/git-merge.sh +++ b/git-merge.sh @@ -43,7 +43,7 @@ do case "$#,$1" in *,*=*) strategy=`expr "$1" : '-[^=]*=\(.*\)'` ;; - 0,*) + 1,*) usage ;; *) strategy="$2" From e4cf17ce0db2dab7c9525a732f86c5e3df3b4ed0 Mon Sep 17 00:00:00 2001 From: Fredrik Kuivinen Date: Tue, 13 Sep 2005 08:22:26 +0200 Subject: [PATCH 04/13] [PATCH] Rename the 'fredrik' merge strategy to 'recursive'. Otherwise we would regret when Fredrik comes up with another merge algorithm with different pros-and-cons with the current one. Signed-off-by: Fredrik Kuivinen Signed-off-by: Junio C Hamano --- .gitignore | 2 +- Makefile | 2 +- git-merge-fredrik.py => git-merge-recursive.py | 0 git-merge.sh | 4 ++-- 4 files changed, 4 insertions(+), 4 deletions(-) rename git-merge-fredrik.py => git-merge-recursive.py (100%) diff --git a/.gitignore b/.gitignore index cc2b29ebf..31c03f468 100644 --- a/.gitignore +++ b/.gitignore @@ -44,10 +44,10 @@ git-mailinfo git-mailsplit git-merge git-merge-base -git-merge-fredrik git-merge-index git-merge-octopus git-merge-one-file +git-merge-recursive git-merge-resolve git-merge-stupid git-mktag diff --git a/Makefile b/Makefile index 9c2bdd642..a851f5646 100644 --- a/Makefile +++ b/Makefile @@ -83,7 +83,7 @@ SCRIPT_PERL = \ git-rename.perl git-shortlog.perl SCRIPT_PYTHON = \ - git-merge-fredrik.py + git-merge-recursive.py # The ones that do not have to link with lcrypto nor lz. SIMPLE_PROGRAMS = \ diff --git a/git-merge-fredrik.py b/git-merge-recursive.py similarity index 100% rename from git-merge-fredrik.py rename to git-merge-recursive.py diff --git a/git-merge.sh b/git-merge.sh index e51e73499..818e6b772 100755 --- a/git-merge.sh +++ b/git-merge.sh @@ -12,9 +12,9 @@ usage () { die "git-merge [-n] [-s ]... +" } -# all_strategies='resolve fredrik stupid octopus' +# all_strategies='resolve recursive stupid octopus' -all_strategies='fredrik octopus resolve stupid' +all_strategies='recursive octopus resolve stupid' default_strategies='resolve octopus' use_strategies= From a5cd85e084458bf573d0d29fa79c4e1ad7973ed7 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Tue, 13 Sep 2005 13:16:45 -0700 Subject: [PATCH 05/13] Detect ls-remote failure properly. The part that can fail is before the pipe, so we need to propagate the error properly to the main process. Signed-off-by: Junio C Hamano --- git-ls-remote.sh | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/git-ls-remote.sh b/git-ls-remote.sh index 604c5f5bb..bfbd5a4d5 100755 --- a/git-ls-remote.sh +++ b/git-ls-remote.sh @@ -42,12 +42,16 @@ http://* | https://* ) if [ -n "$GIT_SSL_NO_VERIFY" ]; then curl_extra_args="-k" fi - curl -nsf $curl_extra_args "$peek_repo/info/refs" || exit 1 + curl -nsf $curl_extra_args "$peek_repo/info/refs" || + echo "failed slurping" ;; rsync://* ) mkdir $tmpdir - rsync -rq "$peek_repo/refs" $tmpdir || exit 1 + rsync -rq "$peek_repo/refs" $tmpdir || { + echo "failed slurping" + exit + } (cd $tmpdir && find refs -type f) | while read path do @@ -58,12 +62,17 @@ rsync://* ) ;; * ) - git-peek-remote "$peek_repo" + git-peek-remote "$peek_repo" || + echo "failed slurping" ;; esac | sort -t ' ' -k 2 | while read sha1 path do + case "$sha1" in + failed) + die "Failed to find remote refs" + esac case "$path" in refs/heads/*) group=heads ;; From ccfd3e99621f489db4ea37a03be7674adbd03f6e Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Tue, 13 Sep 2005 00:05:22 -0700 Subject: [PATCH 06/13] [PATCH] Define relative .git/objects/info/alternates semantics. An entry in the alternates file can name a directory relative to the object store it describes. A typical linux-2.6 maintainer repository would have "../../../torvalds/linux-2.6.git/objects" there, because the subsystem maintainer object store would live in /pub/scm/linux/kernel/git/$u/$system.git/objects/ and the object store of Linus tree is in /pub/scm/linux/kernel/git/torvalds/linux-2.6.git/objects/ This unfortunately is different from GIT_ALTERNATE_OBJECT_DIRECTORIES which is relative to the cwd of the running process, but there is no way to make it consistent with the behaviour of the environment variable. The process typically is run in $system.git/ directory for a naked repository, or one level up for a repository with a working tree, so we just define it to be relative to the objects/ directory to be different from either ;-). Later, the dumb transport could be updated to read from info/alternates and make requests for the repository the repository borrows from. Signed-off-by: Junio C Hamano --- sha1_file.c | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/sha1_file.c b/sha1_file.c index f4c742eed..663820278 100644 --- a/sha1_file.c +++ b/sha1_file.c @@ -240,10 +240,12 @@ static struct alternate_object_database **alt_odb_tail; * SHA1, an extra slash for the first level indirection, and the * terminating NUL. */ -static void link_alt_odb_entries(const char *alt, const char *ep, int sep) +static void link_alt_odb_entries(const char *alt, const char *ep, int sep, + const char *relative_base) { const char *cp, *last; struct alternate_object_database *ent; + int base_len = -1; last = alt; while (last < ep) { @@ -261,12 +263,25 @@ static void link_alt_odb_entries(const char *alt, const char *ep, int sep) int pfxlen = cp - last; int entlen = pfxlen + 43; + if (*last != '/' && relative_base) { + /* Relative alt-odb */ + if (base_len < 0) + base_len = strlen(relative_base) + 1; + entlen += base_len; + pfxlen += base_len; + } ent = xmalloc(sizeof(*ent) + entlen); *alt_odb_tail = ent; alt_odb_tail = &(ent->next); ent->next = NULL; - - memcpy(ent->base, last, pfxlen); + if (*last != '/' && relative_base) { + memcpy(ent->base, relative_base, base_len - 1); + ent->base[base_len - 1] = '/'; + memcpy(ent->base + base_len, + last, cp - last); + } + else + memcpy(ent->base, last, pfxlen); ent->name = ent->base + pfxlen + 1; ent->base[pfxlen] = ent->base[pfxlen + 3] = '/'; ent->base[entlen-1] = 0; @@ -288,12 +303,12 @@ void prepare_alt_odb(void) alt = getenv(ALTERNATE_DB_ENVIRONMENT); if (!alt) alt = ""; - sprintf(path, "%s/info/alternates", get_object_directory()); if (alt_odb_tail) return; alt_odb_tail = &alt_odb_list; - link_alt_odb_entries(alt, alt + strlen(alt), ':'); + link_alt_odb_entries(alt, alt + strlen(alt), ':', NULL); + sprintf(path, "%s/info/alternates", get_object_directory()); fd = open(path, O_RDONLY); if (fd < 0) return; @@ -306,7 +321,8 @@ void prepare_alt_odb(void) if (map == MAP_FAILED) return; - link_alt_odb_entries(map, map + st.st_size, '\n'); + link_alt_odb_entries(map, map + st.st_size, '\n', + get_object_directory()); munmap(map, st.st_size); } From d9a23fa6f7124befe7803f5f3a8c53999578caa4 Mon Sep 17 00:00:00 2001 From: Fredrik Kuivinen Date: Tue, 13 Sep 2005 23:39:34 +0200 Subject: [PATCH 07/13] [PATCH] Be more like the 'resolve' strategy. If there are non-mergeable changes leave the head contents in the cache and update the working directory with the output from merge(1). In the add/add and delete/modify conflict cases leave unmerged cache entries in the index. Signed-off-by: Fredrik Kuivinen Signed-off-by: Junio C Hamano --- git-merge-recursive.py | 68 ++++++++++++++++++++---------------------- 1 file changed, 33 insertions(+), 35 deletions(-) diff --git a/git-merge-recursive.py b/git-merge-recursive.py index 27b84867b..145a5cf0d 100755 --- a/git-merge-recursive.py +++ b/git-merge-recursive.py @@ -7,8 +7,6 @@ sys.path.append('@@GIT_PYTHON_PATH@@') from gitMergeCommon import * -alwaysWriteTree = False - # The actual merge code # --------------------- @@ -46,19 +44,14 @@ def infoMsg(*args): runProgram(['git-update-cache', '-q', '--refresh']) # Use the original index if we only have one common ancestor - updateWd = True - if alwaysWriteTree: - cleanCache = True - else: - cleanCache = False + cleanCache = False else: runProgram(['git-read-tree', h1.tree()]) - updateWd = False cleanCache = True [shaRes, clean] = mergeTrees(h1.tree(), h2.tree(), Ms.tree(), branch1Name, branch2Name, - cleanCache, updateWd) + cleanCache) if clean or cleanCache: res = Commit(None, [h1, h2], tree=shaRes) @@ -125,7 +118,7 @@ def unmergedCacheEntries(): return res def mergeTrees(head, merge, common, branch1Name, branch2Name, - cleanCache, updateWd): + cleanCache): '''Merge the trees 'head' and 'merge' with the common ancestor 'common'. The name of the head branch is 'branch1Name' and the name of the merge branch is 'branch2Name'. Return a tuple (tree, cleanMerge) @@ -138,10 +131,11 @@ def mergeTrees(head, merge, common, branch1Name, branch2Name, print 'Already uptodate!' return [head, True] - if updateWd: - updateArg = '-u' - else: + if cleanCache: updateArg = '-i' + else: + updateArg = '-u' + runProgram(['git-read-tree', updateArg, '-m', common, head, merge]) cleanMerge = True @@ -157,7 +151,7 @@ def mergeTrees(head, merge, common, branch1Name, branch2Name, entries = unmergedCacheEntries() for name in entries: if not processEntry(entries[name], branch1Name, branch2Name, - files, dirs, cleanCache, updateWd): + files, dirs, cleanCache): cleanMerge = False if cleanMerge or cleanCache: @@ -169,29 +163,25 @@ def mergeTrees(head, merge, common, branch1Name, branch2Name, return [tree, cleanMerge] -def processEntry(entry, branch1Name, branch2Name, files, dirs, - cleanCache, updateWd): +def processEntry(entry, branch1Name, branch2Name, files, dirs, cleanCache): '''Merge one cache entry. 'files' is a Set with the files in both of the heads that we are going to merge. 'dirs' contains the corresponding data for directories. If 'cleanCache' is True no non-zero stages will be left in the cache for the path corresponding to the entry 'entry'.''' -# cleanCache == True => Don't leave any non-stage 0 entries in the cache. -# False => Leave unmerged entries - -# updateWd == True => Update the working directory to correspond to the cache -# False => Leave the working directory unchanged +# cleanCache == True => Don't leave any non-stage 0 entries in the cache and +# don't update the working directory +# False => Leave unmerged entries and update the working directory # clean == True => non-conflict case # False => conflict case # If cleanCache == False then the cache shouldn't be updated if clean == False - def updateFile(clean, sha, mode, path): - if cleanCache or (not cleanCache and clean): - runProgram(['git-update-cache', '--add', '--cacheinfo', - '0%o' % mode, sha, path]) + def updateFile(clean, sha, mode, path, onlyWd=False): + updateCache = not onlyWd and (cleanCache or (not cleanCache and clean)) + updateWd = onlyWd or (not cleanCache and clean) if updateWd: prog = ['git-cat-file', 'blob', sha] @@ -213,13 +203,18 @@ def updateFile(clean, sha, mode, path): os.symlink(linkTarget, path) else: assert(False) - runProgram(['git-update-cache', '--', path]) + + if updateWd and updateCache: + runProgram(['git-update-cache', '--add', '--', path]) + elif updateCache: + runProgram(['git-update-cache', '--add', '--cacheinfo', + '0%o' % mode, sha, path]) def removeFile(clean, path): if cleanCache or (not cleanCache and clean): runProgram(['git-update-cache', '--force-remove', '--', path]) - if updateWd: + if not cleanCache and clean: try: os.unlink(path) except OSError, e: @@ -235,8 +230,7 @@ def uniquePath(path, branch): files.add(newPath) return newPath - debug('processing', entry.path, 'clean cache:', cleanCache, - 'wd:', updateWd) + debug('processing', entry.path, 'clean cache:', cleanCache) cleanMerge = True @@ -327,9 +321,9 @@ def uniquePath(path, branch): if aMode != bMode: cleanMerge = False print 'CONFLICT: File "' + path + \ - '" added identically in both branches,' - print 'CONFLICT: but permissions conflict', '0%o' % aMode, \ - '->', '0%o' % bMode + '" added identically in both branches,', \ + 'but permissions conflict', '0%o' % aMode, '->', \ + '0%o' % bMode print 'CONFLICT: adding with permission:', '0%o' % aMode updateFile(False, aSha, aMode, path) @@ -341,8 +335,7 @@ def uniquePath(path, branch): newPath1 = uniquePath(path, branch1Name) newPath2 = uniquePath(path, branch2Name) print 'CONFLICT (add/add): File "' + path + \ - '" added non-identically in both branches.', \ - 'Adding "' + newPath1 + '" and "' + newPath2 + '" instead.' + '" added non-identically in both branches.' removeFile(False, path) updateFile(False, aSha, aMode, newPath1) updateFile(False, bSha, bMode, newPath2) @@ -372,7 +365,12 @@ def uniquePath(path, branch): if ret != 0: cleanMerge = False print 'CONFLICT (content): Merge conflict in "' + path + '".' - updateFile(False, sha, mode, path) + + if cleanCache: + updateFile(False, sha, mode, path) + else: + updateFile(True, aSha, aMode, path) + updateFile(False, sha, mode, path, True) else: updateFile(True, sha, mode, path) From 0d214b6619bf14a6409a2a1ba079f3530d40ee41 Mon Sep 17 00:00:00 2001 From: Fredrik Kuivinen Date: Tue, 13 Sep 2005 23:40:23 +0200 Subject: [PATCH 08/13] [PATCH] Don't output 'Automatic merge failed, ...' git-merge.sh does this for us. Signed-off-by: Fredrik Kuivinen Signed-off-by: Junio C Hamano --- git-merge-recursive.py | 1 - 1 file changed, 1 deletion(-) diff --git a/git-merge-recursive.py b/git-merge-recursive.py index 145a5cf0d..eeb3d24da 100755 --- a/git-merge-recursive.py +++ b/git-merge-recursive.py @@ -423,5 +423,4 @@ def usage(): if clean: sys.exit(0) else: - print 'Automatic merge failed, fix up by hand' sys.exit(1) From 87a71b65acc10c4879b13d2030185e5640a087cd Mon Sep 17 00:00:00 2001 From: Fredrik Kuivinen Date: Tue, 13 Sep 2005 23:40:47 +0200 Subject: [PATCH 09/13] [PATCH] Adjust git-merge-recursive.py for the new tool names. Signed-off-by: Fredrik Kuivinen Signed-off-by: Junio C Hamano --- git-merge-recursive.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/git-merge-recursive.py b/git-merge-recursive.py index eeb3d24da..ea7f994a4 100755 --- a/git-merge-recursive.py +++ b/git-merge-recursive.py @@ -41,7 +41,7 @@ def infoMsg(*args): if callDepth == 0: if len(ca) > 1: runProgram(['git-read-tree', h1.tree()]) - runProgram(['git-update-cache', '-q', '--refresh']) + runProgram(['git-update-index', '-q', '--refresh']) # Use the original index if we only have one common ancestor cleanCache = False @@ -205,14 +205,14 @@ def updateFile(clean, sha, mode, path, onlyWd=False): assert(False) if updateWd and updateCache: - runProgram(['git-update-cache', '--add', '--', path]) + runProgram(['git-update-index', '--add', '--', path]) elif updateCache: - runProgram(['git-update-cache', '--add', '--cacheinfo', + runProgram(['git-update-index', '--add', '--cacheinfo', '0%o' % mode, sha, path]) def removeFile(clean, path): if cleanCache or (not cleanCache and clean): - runProgram(['git-update-cache', '--force-remove', '--', path]) + runProgram(['git-update-index', '--force-remove', '--', path]) if not cleanCache and clean: try: From 6511cce24b932eba33d8e13b54664673121a8b7e Mon Sep 17 00:00:00 2001 From: Fredrik Kuivinen Date: Tue, 13 Sep 2005 23:41:16 +0200 Subject: [PATCH 10/13] [PATCH] Use a temporary index file when we merge the common ancestors. With this change we can get rid of a call to 'git-update-index --refresh'. Signed-off-by: Fredrik Kuivinen Signed-off-by: Junio C Hamano --- git-merge-recursive.py | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/git-merge-recursive.py b/git-merge-recursive.py index ea7f994a4..66165b01c 100755 --- a/git-merge-recursive.py +++ b/git-merge-recursive.py @@ -10,6 +10,22 @@ # The actual merge code # --------------------- +originalIndexFile = os.environ.get('GIT_INDEX_FILE', + os.environ.get('GIT_DIR', '.git') + '/index') +temporaryIndexFile = os.environ.get('GIT_DIR', '.git') + \ + '/merge-recursive-tmp-index' +def setupIndex(temporary): + try: + os.unlink(temporaryIndexFile) + except OSError: + pass + if temporary: + newIndex = temporaryIndexFile + os.environ + else: + newIndex = originalIndexFile + os.environ['GIT_INDEX_FILE'] = newIndex + def merge(h1, h2, branch1Name, branch2Name, graph, callDepth=0): '''Merge the commits h1 and h2, return the resulting virtual commit object and a flag indicating the cleaness of the merge.''' @@ -39,13 +55,10 @@ def infoMsg(*args): assert(isinstance(Ms, Commit)) if callDepth == 0: - if len(ca) > 1: - runProgram(['git-read-tree', h1.tree()]) - runProgram(['git-update-index', '-q', '--refresh']) - # Use the original index if we only have one common ancestor - + setupIndex(False) cleanCache = False else: + setupIndex(True) runProgram(['git-read-tree', h1.tree()]) cleanCache = True From daae66994967ba503f5e868eddf6962a2c1d7871 Mon Sep 17 00:00:00 2001 From: Fredrik Kuivinen Date: Tue, 13 Sep 2005 23:41:39 +0200 Subject: [PATCH 11/13] [PATCH] Use the 'die' function where it is appropriate. Signed-off-by: Fredrik Kuivinen Signed-off-by: Junio C Hamano --- gitMergeCommon.py | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/gitMergeCommon.py b/gitMergeCommon.py index ce9694b15..3af4fbd15 100644 --- a/gitMergeCommon.py +++ b/gitMergeCommon.py @@ -1,19 +1,24 @@ import sys, re, os, traceback from sets import Set +def die(*args): + printList(args, sys.stderr) + sys.exit(2) + +def printList(list, file=sys.stdout): + for x in list: + file.write(str(x)) + file.write(' ') + file.write('\n') + if sys.version_info[0] < 2 or \ (sys.version_info[0] == 2 and sys.version_info[1] < 4): - print 'Python version 2.4 required, found', \ - str(sys.version_info[0])+'.'+str(sys.version_info[1])+'.'+ \ - str(sys.version_info[2]) - sys.exit(1) + die('Python version 2.4 required, found', \ + str(sys.version_info[0])+'.'+str(sys.version_info[1])+'.'+ \ + str(sys.version_info[2])) import subprocess -def die(*args): - printList(args, sys.stderr) - sys.exit(2) - # Debugging machinery # ------------------- @@ -32,12 +37,6 @@ def debug(*args): if funcName in functionsToDebug: printList(args) -def printList(list, file=sys.stdout): - for x in list: - file.write(str(x)) - file.write(' ') - file.write('\n') - # Program execution # ----------------- From 74376a686425c6304eafff9f26d8d5fb0d083bc0 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Tue, 13 Sep 2005 21:09:03 -0700 Subject: [PATCH 12/13] git-merge-recursive: Trivial RE fixes. Signed-off-by: Junio C Hamano --- git-merge-recursive.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/git-merge-recursive.py b/git-merge-recursive.py index 66165b01c..60e8b21b3 100755 --- a/git-merge-recursive.py +++ b/git-merge-recursive.py @@ -74,7 +74,7 @@ def infoMsg(*args): return [res, clean] -getFilesRE = re.compile('([0-9]+) ([a-z0-9]+) ([0-9a-f]{40})\t(.*)') +getFilesRE = re.compile(r'^([0-7]+) (\S+) ([0-9a-f]{40})\t(.*)$', re.S) def getFilesAndDirs(tree): files = Set() dirs = Set() @@ -99,7 +99,7 @@ def __init__(self): self.stages = [Stage(), Stage(), Stage()] self.path = path -unmergedRE = re.compile('^([0-9]+) ([0-9a-f]{40}) ([1-3])\t(.*)$') +unmergedRE = re.compile(r'^([0-7]+) ([0-9a-f]{40}) ([1-3])\t(.*)$', re.S) def unmergedCacheEntries(): '''Create a dictionary mapping file names to CacheEntry objects. The dictionary contains one entry for every path with a From 2ba6c47be1762726ad0c1d5779064c489150d789 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Tue, 13 Sep 2005 22:27:42 -0700 Subject: [PATCH 13/13] read-tree: fix bogus debugging statement. We wanted to detect case #16 which should be rare, but botched the case when some paths are missing, causing a segfault. My fault. Signed-off-by: Junio C Hamano --- read-tree.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/read-tree.c b/read-tree.c index 4db154db2..6a5c08c4c 100644 --- a/read-tree.c +++ b/read-tree.c @@ -362,12 +362,15 @@ static int keep_entry(struct cache_entry *ce) static void show_stage_entry(FILE *o, const char *label, const struct cache_entry *ce) { - fprintf(stderr, "%s%06o %s %d\t%s\n", - label, - ntohl(ce->ce_mode), - sha1_to_hex(ce->sha1), - ce_stage(ce), - ce->name); + if (!ce) + fprintf(o, "%s (missing)\n", label); + else + fprintf(o, "%s%06o %s %d\t%s\n", + label, + ntohl(ce->ce_mode), + sha1_to_hex(ce->sha1), + ce_stage(ce), + ce->name); } #endif