From 790fa0e297b41b9e8c98a77b58004c58408e5f7a Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sat, 16 Dec 2006 16:23:02 -0800 Subject: [PATCH 01/10] update-index: make D/F conflict error a bit more verbose. When you remove a directory D that has a tracked file D/F out of the way to create a file D and try to "git update-index --add D", it used to say "cannot add" which was not very helpful. This issues an extra error message to explain the situation before the final "fatal" message. Since D/F conflicts are relatively rare event, extra verbosity would not make things too noisy. Signed-off-by: Junio C Hamano --- read-cache.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/read-cache.c b/read-cache.c index eae4745d28..a602010a69 100644 --- a/read-cache.c +++ b/read-cache.c @@ -609,7 +609,7 @@ int add_cache_entry(struct cache_entry *ce, int option) if (!skip_df_check && check_file_directory_conflict(ce, pos, ok_to_replace)) { if (!ok_to_replace) - return -1; + return error("'%s' appears as both a file and as a directory", ce->name); pos = cache_name_pos(ce->name, ntohs(ce->ce_flags)); pos = -pos-1; } From c33ab0dd100d91d417b5ed3378acbf3310c07cec Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sun, 17 Dec 2006 01:09:41 -0800 Subject: [PATCH 02/10] git-add: remove conflicting entry when adding. When replacing an existing file A with a directory A that has a file A/B in it in the index, 'git add' did not succeed because it forgot to pass the allow-replace flag to add_cache_entry(). It might be safer to leave this as an error and require the user to explicitly remove the existing A first before adding A/B since it is an unusual case, but doing that automatically is much easier to use. Signed-off-by: Junio C Hamano --- read-cache.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/read-cache.c b/read-cache.c index a602010a69..983e68b892 100644 --- a/read-cache.c +++ b/read-cache.c @@ -358,7 +358,7 @@ int add_file_to_index(const char *path, int verbose) if (index_path(ce->sha1, path, &st, 1)) die("unable to index file %s", path); - if (add_cache_entry(ce, ADD_CACHE_OK_TO_ADD)) + if (add_cache_entry(ce, ADD_CACHE_OK_TO_ADD|ADD_CACHE_OK_TO_REPLACE)) die("unable to add %s to index",path); if (verbose) printf("add '%s'\n", path); From 81a361be3b12f393d402c5da63191c11c18ea6a9 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sat, 16 Dec 2006 17:39:06 -0800 Subject: [PATCH 03/10] Fix check_file_directory_conflict(). When replacing an existing file A with a directory A that has a file A/B in it in the index, 'update-index --replace --add A/B' did not properly remove the file to make room for the new directory. There was a trivial logic error, most likely a cut & paste one, dating back to quite early days of git. Signed-off-by: Junio C Hamano --- read-cache.c | 2 +- t/t0000-basic.sh | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/read-cache.c b/read-cache.c index 983e68b892..b8d83ccd9f 100644 --- a/read-cache.c +++ b/read-cache.c @@ -517,7 +517,7 @@ static int has_dir_name(const struct cache_entry *ce, int pos, int ok_to_replace pos = cache_name_pos(name, ntohs(create_ce_flags(len, stage))); if (pos >= 0) { retval = -1; - if (ok_to_replace) + if (!ok_to_replace) break; remove_cache_entry_at(pos); continue; diff --git a/t/t0000-basic.sh b/t/t0000-basic.sh index 3260d1d7a7..0cd1c41866 100755 --- a/t/t0000-basic.sh +++ b/t/t0000-basic.sh @@ -272,4 +272,13 @@ test_expect_success \ wc -l) && test $numparent = 1' +test_expect_success 'update-index D/F conflict' ' + mv path0 tmp && + mv path2 path0 && + mv tmp path2 && + git update-index --add --replace path2 path0/file2 && + numpath0=$(git ls-files path0 | wc -l) && + test $numpath0 = 1 +' + test_done From a7f196a74650e45ce240754e2caa483752651063 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Sun, 17 Dec 2006 03:15:14 -0500 Subject: [PATCH 04/10] Default GIT_COMMITTER_NAME to login name in recieve-pack. If GIT_COMMITTER_NAME is not available in receive-pack but reflogs are enabled we would normally die out with an error message asking the user to correct their environment settings. Now that reflogs are enabled by default in (what we guessed to be) non-bare Git repositories this may cause problems for some users who don't have their full name in the gecos field and who don't have access to the remote system to correct the problem. So rather than die()'ing out in receive-pack when we try to log a ref change and have no committer name we default to the username, as obtained from the host's password database. Signed-off-by: Shawn O. Pearce Signed-off-by: Junio C Hamano --- cache.h | 1 + ident.c | 15 +++++++++++++++ receive-pack.c | 2 ++ 3 files changed, 18 insertions(+) diff --git a/cache.h b/cache.h index 2d3df98dc4..b540292d66 100644 --- a/cache.h +++ b/cache.h @@ -309,6 +309,7 @@ void datestamp(char *buf, int bufsize); unsigned long approxidate(const char *); extern int setup_ident(void); +extern void ignore_missing_committer_name(); extern const char *git_author_info(int); extern const char *git_committer_info(int); diff --git a/ident.c b/ident.c index e415fd3588..d7faba6a70 100644 --- a/ident.c +++ b/ident.c @@ -221,3 +221,18 @@ const char *git_committer_info(int error_on_no_name) getenv("GIT_COMMITTER_DATE"), error_on_no_name); } + +void ignore_missing_committer_name() +{ + /* If we did not get a name from the user's gecos entry then + * git_default_name is empty; so instead load the username + * into it as a 'good enough for now' approximation of who + * this user is. + */ + if (!*git_default_name) { + struct passwd *pw = getpwuid(getuid()); + if (!pw) + die("You don't exist. Go away!"); + strlcpy(git_default_name, pw->pw_name, sizeof(git_default_name)); + } +} diff --git a/receive-pack.c b/receive-pack.c index e76d9aea31..5e5510bc3d 100644 --- a/receive-pack.c +++ b/receive-pack.c @@ -420,6 +420,8 @@ int main(int argc, char **argv) die("'%s': unable to chdir or not a git archive", dir); setup_ident(); + /* don't die if gecos is empty */ + ignore_missing_committer_name(); git_config(receive_pack_config); write_head_info(); From 38477d9e6055e3572b465ec3f8e716164111683d Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sun, 17 Dec 2006 00:46:35 -0800 Subject: [PATCH 05/10] Fix mis-mark-up in git-merge-file.txt documentation Signed-off-by: Junio C Hamano --- Documentation/git-merge-file.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/git-merge-file.txt b/Documentation/git-merge-file.txt index 0b41d66a70..29d3faa556 100644 --- a/Documentation/git-merge-file.txt +++ b/Documentation/git-merge-file.txt @@ -1,9 +1,9 @@ git-merge-file(1) -============ +================= NAME ---- -git-merge-file - threeway file merge +git-merge-file - three-way file merge SYNOPSIS From c0e9232e43446d3bfa7844d36e64e087b8709090 Mon Sep 17 00:00:00 2001 From: Quy Tonthat Date: Mon, 18 Dec 2006 01:50:12 +1100 Subject: [PATCH 06/10] Documentation: new option -P for git-svnimport Documentation: new option -P for git-svnimport. Signed-off-by: Quy Tonthat Signed-off-by: Junio C Hamano --- Documentation/git-svnimport.txt | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Documentation/git-svnimport.txt b/Documentation/git-svnimport.txt index b1b87c2fcd..df604e15ec 100644 --- a/Documentation/git-svnimport.txt +++ b/Documentation/git-svnimport.txt @@ -15,6 +15,7 @@ SYNOPSIS [ -b branch_subdir ] [ -T trunk_subdir ] [ -t tag_subdir ] [ -s start_chg ] [ -m ] [ -r ] [ -M regex ] [ -I ] [ -A ] + [ -P ] [ ] @@ -107,6 +108,14 @@ repository without -A. Formerly, this option controlled how many revisions to pull, due to SVN memory leaks. (These have been worked around.) +-P :: + Partial import of the SVN tree. + + By default, the whole tree on the SVN trunk (/trunk) is imported. + '-P my/proj' will import starting only from '/trunk/my/proj'. + This option is useful when you want to import one project from a + svn repo which hosts multiple projects under the same trunk. + -v:: Verbosity: let 'svnimport' report what it is doing. From ee6002aa429272871733b8fbc99a9e6df3e150f5 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sun, 17 Dec 2006 10:33:24 -0800 Subject: [PATCH 07/10] markup fix in svnimport documentation. Signed-off-by: Junio C Hamano --- Documentation/git-svnimport.txt | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Documentation/git-svnimport.txt b/Documentation/git-svnimport.txt index df604e15ec..2c7c7dad54 100644 --- a/Documentation/git-svnimport.txt +++ b/Documentation/git-svnimport.txt @@ -104,17 +104,17 @@ repository without -A. -l :: Specify a maximum revision number to pull. - - Formerly, this option controlled how many revisions to pull, - due to SVN memory leaks. (These have been worked around.) ++ +Formerly, this option controlled how many revisions to pull, +due to SVN memory leaks. (These have been worked around.) -P :: Partial import of the SVN tree. - - By default, the whole tree on the SVN trunk (/trunk) is imported. - '-P my/proj' will import starting only from '/trunk/my/proj'. - This option is useful when you want to import one project from a - svn repo which hosts multiple projects under the same trunk. ++ +By default, the whole tree on the SVN trunk (/trunk) is imported. +'-P my/proj' will import starting only from '/trunk/my/proj'. +This option is useful when you want to import one project from a +svn repo which hosts multiple projects under the same trunk. -v:: Verbosity: let 'svnimport' report what it is doing. From 577ed5c20b4ca374626c104f90c88550cf415067 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sun, 22 Oct 2006 17:32:47 -0700 Subject: [PATCH 08/10] rev-list --left-right The output from "symmetric diff", i.e. A...B, does not distinguish between commits that are reachable from A and the ones that are reachable from B. In this picture, such a symmetric diff includes commits marked with a and b. x---b---b branch B / \ / / . / / \ o---x---a---a branch A However, you cannot tell which ones are 'a' and which ones are 'b' from the output. Sometimes this is frustrating. This adds an output option, --left-right, to rev-list. rev-list --left-right A...B would show ones reachable from A prefixed with '<' and the ones reachable from B prefixed with '>'. When combined with --boundary, boundary commits (the ones marked with 'x' in the above picture) are shown with prefix '-', so you would see list that looks like this: git rev-list --left-right --boundary --pretty=oneline A...B >bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 3rd on b >bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb 2nd on b --- builtin-rev-list.c | 11 +++++++++++ commit.c | 10 +++++----- revision.c | 5 ++++- revision.h | 1 + 4 files changed, 21 insertions(+), 6 deletions(-) diff --git a/builtin-rev-list.c b/builtin-rev-list.c index fb7fc92145..4364035e15 100644 --- a/builtin-rev-list.c +++ b/builtin-rev-list.c @@ -45,6 +45,7 @@ static int bisect_list; static int show_timestamp; static int hdr_termination; static const char *header_prefix; +static int show_left_right; static void show_commit(struct commit *commit) { @@ -54,6 +55,12 @@ static void show_commit(struct commit *commit) fputs(header_prefix, stdout); if (commit->object.flags & BOUNDARY) putchar('-'); + else if (show_left_right) { + if (commit->object.flags & SYMMETRIC_LEFT) + putchar('<'); + else + putchar('>'); + } if (revs.abbrev_commit && revs.abbrev) fputs(find_unique_abbrev(commit->object.sha1, revs.abbrev), stdout); @@ -240,6 +247,10 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix) bisect_list = 1; continue; } + if (!strcmp(arg, "--left-right")) { + show_left_right = 1; + continue; + } if (!strcmp(arg, "--stdin")) { if (read_from_stdin++) die("--stdin given twice?"); diff --git a/commit.c b/commit.c index a6d543eee7..289ef65eb1 100644 --- a/commit.c +++ b/commit.c @@ -868,11 +868,11 @@ void sort_in_topological_order_fn(struct commit_list ** list, int lifo, /* merge-rebase stuff */ -/* bits #0..7 in revision.h */ -#define PARENT1 (1u<< 8) -#define PARENT2 (1u<< 9) -#define STALE (1u<<10) -#define RESULT (1u<<11) +/* bits #0..15 in revision.h */ +#define PARENT1 (1u<<16) +#define PARENT2 (1u<<17) +#define STALE (1u<<18) +#define RESULT (1u<<19) static struct commit *interesting(struct commit_list *list) { diff --git a/revision.c b/revision.c index 993bb668a2..3d989c3edf 100644 --- a/revision.c +++ b/revision.c @@ -344,6 +344,7 @@ static void try_to_simplify_commit(struct rev_info *revs, struct commit *commit) static void add_parents_to_list(struct rev_info *revs, struct commit *commit, struct commit_list **list) { struct commit_list *parent = commit->parents; + unsigned left_flag; if (commit->object.flags & ADDED) return; @@ -388,6 +389,7 @@ static void add_parents_to_list(struct rev_info *revs, struct commit *commit, st if (revs->no_walk) return; + left_flag = (commit->object.flags & SYMMETRIC_LEFT); parent = commit->parents; while (parent) { struct commit *p = parent->item; @@ -395,6 +397,7 @@ static void add_parents_to_list(struct rev_info *revs, struct commit *commit, st parent = parent->next; parse_commit(p); + p->object.flags |= left_flag; if (p->object.flags & SEEN) continue; p->object.flags |= SEEN; @@ -640,7 +643,7 @@ int handle_revision_arg(const char *arg, struct rev_info *revs, add_pending_commit_list(revs, exclude, flags_exclude); free_commit_list(exclude); - a->object.flags |= flags; + a->object.flags |= flags | SYMMETRIC_LEFT; } else a->object.flags |= flags_exclude; b->object.flags |= flags; diff --git a/revision.h b/revision.h index 3adab9590a..f92a4d4375 100644 --- a/revision.h +++ b/revision.h @@ -9,6 +9,7 @@ #define BOUNDARY (1u<<5) #define BOUNDARY_SHOW (1u<<6) #define ADDED (1u<<7) /* Parents already parsed and added? */ +#define SYMMETRIC_LEFT (1u<<8) struct rev_info; struct log_info; From 74bd9029732db28b2fff50de0a190229c6033e02 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sat, 16 Dec 2006 15:31:25 -0800 Subject: [PATCH 09/10] Teach all of log family --left-right output. This makes reviewing git log --left-right --merge --no-merges -p a lot more pleasant. Signed-off-by: Junio C Hamano --- builtin-rev-list.c | 7 +------ log-tree.c | 26 ++++++++++++++++++++++---- revision.c | 4 ++++ revision.h | 1 + 4 files changed, 28 insertions(+), 10 deletions(-) diff --git a/builtin-rev-list.c b/builtin-rev-list.c index 4364035e15..1bb3a06680 100644 --- a/builtin-rev-list.c +++ b/builtin-rev-list.c @@ -45,7 +45,6 @@ static int bisect_list; static int show_timestamp; static int hdr_termination; static const char *header_prefix; -static int show_left_right; static void show_commit(struct commit *commit) { @@ -55,7 +54,7 @@ static void show_commit(struct commit *commit) fputs(header_prefix, stdout); if (commit->object.flags & BOUNDARY) putchar('-'); - else if (show_left_right) { + else if (revs.left_right) { if (commit->object.flags & SYMMETRIC_LEFT) putchar('<'); else @@ -247,10 +246,6 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix) bisect_list = 1; continue; } - if (!strcmp(arg, "--left-right")) { - show_left_right = 1; - continue; - } if (!strcmp(arg, "--stdin")) { if (read_from_stdin++) die("--stdin given twice?"); diff --git a/log-tree.c b/log-tree.c index 8787df5cc6..35be33aaf7 100644 --- a/log-tree.c +++ b/log-tree.c @@ -114,6 +114,14 @@ void show_log(struct rev_info *opt, const char *sep) opt->loginfo = NULL; if (!opt->verbose_header) { + if (opt->left_right) { + if (commit->object.flags & BOUNDARY) + putchar('-'); + else if (commit->object.flags & SYMMETRIC_LEFT) + putchar('<'); + else + putchar('>'); + } fputs(diff_unique_abbrev(commit->object.sha1, abbrev_commit), stdout); if (opt->parents) show_parents(commit, abbrev_commit); @@ -192,10 +200,20 @@ void show_log(struct rev_info *opt, const char *sep) opt->diffopt.stat_sep = buffer; } } else { - printf("%s%s%s", - diff_get_color(opt->diffopt.color_diff, DIFF_COMMIT), - opt->commit_format == CMIT_FMT_ONELINE ? "" : "commit ", - diff_unique_abbrev(commit->object.sha1, abbrev_commit)); + fputs(diff_get_color(opt->diffopt.color_diff, DIFF_COMMIT), + stdout); + if (opt->commit_format != CMIT_FMT_ONELINE) + fputs("commit ", stdout); + if (opt->left_right) { + if (commit->object.flags & BOUNDARY) + putchar('-'); + else if (commit->object.flags & SYMMETRIC_LEFT) + putchar('<'); + else + putchar('>'); + } + fputs(diff_unique_abbrev(commit->object.sha1, abbrev_commit), + stdout); if (opt->parents) show_parents(commit, abbrev_commit); if (parent) diff --git a/revision.c b/revision.c index 3d989c3edf..d84f46e5a6 100644 --- a/revision.c +++ b/revision.c @@ -853,6 +853,10 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch revs->boundary = 1; continue; } + if (!strcmp(arg, "--left-right")) { + revs->left_right = 1; + continue; + } if (!strcmp(arg, "--objects")) { revs->tag_objects = 1; revs->tree_objects = 1; diff --git a/revision.h b/revision.h index f92a4d4375..4585463a44 100644 --- a/revision.h +++ b/revision.h @@ -41,6 +41,7 @@ struct rev_info { limited:1, unpacked:1, /* see also ignore_packed below */ boundary:1, + left_right:1, parents:1; /* Diff flags */ From 5761231975ceffa531d86d9bab0f9a9a370674f6 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sat, 16 Dec 2006 16:07:20 -0800 Subject: [PATCH 10/10] Make left-right automatic. When using symmetric differences, I think the user almost always would want to know which side of the symmetry each commit came from. So this removes --left-right option from the command line, and turns it on automatically when a symmetric difference is used ("git log --merge" counts as a symmetric difference between HEAD and MERGE_HEAD). Just in case, a new option --no-left-right is provided to defeat this, but I do not know if it would be useful. Signed-off-by: Junio C Hamano --- revision.c | 13 ++++++++++--- revision.h | 1 + 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/revision.c b/revision.c index d84f46e5a6..56819f8220 100644 --- a/revision.c +++ b/revision.c @@ -853,8 +853,8 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch revs->boundary = 1; continue; } - if (!strcmp(arg, "--left-right")) { - revs->left_right = 1; + if (!strcmp(arg, "--no-left-right")) { + revs->no_left_right = 1; continue; } if (!strcmp(arg, "--objects")) { @@ -1055,13 +1055,18 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch void prepare_revision_walk(struct rev_info *revs) { int nr = revs->pending.nr; + int has_symmetric = 0; struct object_array_entry *list = revs->pending.objects; revs->pending.nr = 0; revs->pending.alloc = 0; revs->pending.objects = NULL; while (--nr >= 0) { - struct commit *commit = handle_commit(revs, list->item, list->name); + struct commit *commit; + + if (list->item->flags & SYMMETRIC_LEFT) + has_symmetric = 1; + commit = handle_commit(revs, list->item, list->name); if (commit) { if (!(commit->object.flags & SEEN)) { commit->object.flags |= SEEN; @@ -1073,6 +1078,8 @@ void prepare_revision_walk(struct rev_info *revs) if (revs->no_walk) return; + if (!revs->no_left_right && has_symmetric) + revs->left_right = 1; if (revs->limited) limit_list(revs); if (revs->topo_order) diff --git a/revision.h b/revision.h index 4585463a44..b2ab81488c 100644 --- a/revision.h +++ b/revision.h @@ -41,6 +41,7 @@ struct rev_info { limited:1, unpacked:1, /* see also ignore_packed below */ boundary:1, + no_left_right:1, left_right:1, parents:1;