From: Junio C Hamano Date: Sun, 26 Mar 2006 08:22:53 +0000 (-0800) Subject: Merge branches 'jc/clone' and 'jc/name' X-Git-Tag: v1.3.0-rc1~4^2~1 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/be1295d16a2593dcf468fef7d9e811d057d9039f?ds=inline;hp=-c Merge branches 'jc/clone' and 'jc/name' * jc/clone: git-clone: typofix. clone: record the remote primary branch with remotes/$origin/HEAD revamp git-clone (take #2). revamp git-clone. fetch,parse-remote,fmt-merge-msg: refs/remotes/* support * jc/name: sha1_name: make core.warnambiguousrefs the default. sha1_name: warning ambiguous refs. get_sha1_basic(): try refs/... and finally refs/remotes/$foo/HEAD core.warnambiguousrefs: warns when "name" is used and both "name" branch and tag exists. --- be1295d16a2593dcf468fef7d9e811d057d9039f diff --combined blame.c index 7e88833a37,90338af31c,270ca52c3a..396defccc7 --- a/blame.c +++ b/blame.c @@@@ -14,7 -14,6 -14,7 +14,7 @@@@ #include "tree.h" #include "blob.h" #include "diff.h" + #include "diffcore.h" #include "revision.h" #define DEBUG 0 @@@@ -35,9 -34,7 -35,9 +35,9 @@@@ struct util_info char *buf; unsigned long size; int num_lines; - // const char* path; + const char* pathname; + + void* topo_data; }; struct chunk { @@@@ -180,13 -177,11 -180,13 +180,13 @@@@ static int get_blob_sha1_internal(unsig unsigned mode, int stage); static unsigned char blob_sha1[20]; + static const char* blame_file; static int get_blob_sha1(struct tree *t, const char *pathname, unsigned char *sha1) { int i; const char *pathspec[2]; + blame_file = pathname; pathspec[0] = pathname; pathspec[1] = NULL; memset(blob_sha1, 0, sizeof(blob_sha1)); @@@@ -211,10 -206,6 -211,10 +211,10 @@@@ static int get_blob_sha1_internal(unsig if (S_ISDIR(mode)) return READ_TREE_RECURSIVE; + if (strncmp(blame_file, base, baselen) || + strcmp(blame_file + baselen, pathname)) + return -1; + memcpy(blob_sha1, sha1, 20); return -1; } @@@@ -351,34 -342,25 -351,34 +351,34 @@@@ static int map_line(struct commit *comm return info->line_map[line]; } - static int fill_util_info(struct commit *commit, const char *path) + static struct util_info* get_util(struct commit *commit) { - struct util_info *util; - if (commit->object.util) - return 0; + struct util_info *util = commit->object.util; + + if (util) + return util; util = xmalloc(sizeof(struct util_info)); + util->buf = NULL; + util->size = 0; + util->line_map = NULL; + util->num_lines = -1; + util->pathname = NULL; + commit->object.util = util; + return util; + } + + static int fill_util_info(struct commit *commit) + { + struct util_info *util = commit->object.util; + + assert(util); + assert(util->pathname); - if (get_blob_sha1(commit->tree, path, util->sha1)) { - free(util); + if (get_blob_sha1(commit->tree, util->pathname, util->sha1)) return 1; - } else { - util->buf = NULL; - util->size = 0; - util->line_map = NULL; - util->num_lines = -1; - commit->object.util = util; + else return 0; - } } static void alloc_line_map(struct commit *commit) @@@@ -407,11 -389,10 -407,11 +407,11 @@@@ static void init_first_commit(struct commit* commit, const char* filename) { - struct util_info* util; + struct util_info* util = commit->object.util; int i; - if (fill_util_info(commit, filename)) + util->pathname = filename; + if (fill_util_info(commit)) die("fill_util_info failed"); alloc_line_map(commit); @@@@ -472,7 -453,7 -472,7 +472,7 @@@@ static void process_commits(struct rev_ if(num_parents == 0) *initial = commit; - if(fill_util_info(commit, path)) + if (fill_util_info(commit)) continue; alloc_line_map(commit); @@@@ -490,7 -471,7 -490,7 +490,7 @@@@ printf("parent: %s\n", sha1_to_hex(parent->object.sha1)); - if(fill_util_info(parent, path)) { + if (fill_util_info(parent)) { num_parents--; continue; } @@@@ -530,135 -511,6 -530,135 +530,135 @@@@ } while ((commit = get_revision(rev)) != NULL); } + + static int compare_tree_path(struct rev_info* revs, + struct commit* c1, struct commit* c2) + { + const char* paths[2]; + struct util_info* util = c2->object.util; + paths[0] = util->pathname; + paths[1] = NULL; + + diff_tree_setup_paths(get_pathspec(revs->prefix, paths)); + return rev_compare_tree(c1->tree, c2->tree); + } + + + static int same_tree_as_empty_path(struct rev_info *revs, struct tree* t1, + const char* path) + { + const char* paths[2]; + paths[0] = path; + paths[1] = NULL; + + diff_tree_setup_paths(get_pathspec(revs->prefix, paths)); + return rev_same_tree_as_empty(t1); + } + + static const char* find_rename(struct commit* commit, struct commit* parent) + { + struct util_info* cutil = commit->object.util; + struct diff_options diff_opts; + const char *paths[1]; + int i; + + if (DEBUG) { + printf("find_rename commit: %s ", + sha1_to_hex(commit->object.sha1)); + puts(sha1_to_hex(parent->object.sha1)); + } + + diff_setup(&diff_opts); + diff_opts.recursive = 1; + diff_opts.detect_rename = DIFF_DETECT_RENAME; + paths[0] = NULL; + diff_tree_setup_paths(paths); + if (diff_setup_done(&diff_opts) < 0) + die("diff_setup_done failed"); + + diff_tree_sha1(commit->tree->object.sha1, parent->tree->object.sha1, + "", &diff_opts); + diffcore_std(&diff_opts); + + for (i = 0; i < diff_queued_diff.nr; i++) { + struct diff_filepair *p = diff_queued_diff.queue[i]; + + if (p->status == 'R' && !strcmp(p->one->path, cutil->pathname)) { + if (DEBUG) + printf("rename %s -> %s\n", p->one->path, p->two->path); + return p->two->path; + } + } + + return 0; + } + + static void simplify_commit(struct rev_info *revs, struct commit *commit) + { + struct commit_list **pp, *parent; + + if (!commit->tree) + return; + + if (!commit->parents) { + struct util_info* util = commit->object.util; + if (!same_tree_as_empty_path(revs, commit->tree, + util->pathname)) + commit->object.flags |= TREECHANGE; + return; + } + + pp = &commit->parents; + while ((parent = *pp) != NULL) { + struct commit *p = parent->item; + + if (p->object.flags & UNINTERESTING) { + pp = &parent->next; + continue; + } + + parse_commit(p); + switch (compare_tree_path(revs, p, commit)) { + case REV_TREE_SAME: + parent->next = NULL; + commit->parents = parent; + get_util(p)->pathname = get_util(commit)->pathname; + return; + + case REV_TREE_NEW: + { + + struct util_info* util = commit->object.util; + if (revs->remove_empty_trees && + same_tree_as_empty_path(revs, p->tree, + util->pathname)) { + const char* new_name = find_rename(commit, p); + if (new_name) { + struct util_info* putil = get_util(p); + if (!putil->pathname) + putil->pathname = strdup(new_name); + } else { + *pp = parent->next; + continue; + } + } + } + + /* fallthrough */ + case REV_TREE_DIFFERENT: + pp = &parent->next; + if (!get_util(p)->pathname) + get_util(p)->pathname = + get_util(commit)->pathname; + continue; + } + die("bad tree compare for commit %s", + sha1_to_hex(commit->object.sha1)); + } + commit->object.flags |= TREECHANGE; + } + + struct commit_info { char* author; @@@@ -717,18 -569,6 -717,18 +717,18 @@@@ static const char* format_time(unsigne return time_buf; } + static void topo_setter(struct commit* c, void* data) + { + struct util_info* util = c->object.util; + util->topo_data = data; + } + + static void* topo_getter(struct commit* c) + { + struct util_info* util = c->object.util; + return util->topo_data; + } + int main(int argc, const char **argv) { int i; @@@@ -740,18 -580,16 -740,19 +740,19 @@@@ int sha1_len = 8; int compability = 0; int options = 1; + struct commit* start_commit; - int num_args; const char* args[10]; struct rev_info rev; struct commit_info ci; const char *buf; int max_digits; - size_t longest_file, longest_author; ++ int longest_file, longest_author; + int found_rename; const char* prefix = setup_git_directory(); ++ git_config(git_default_config); for(i = 1; i < argc; i++) { if(options) { @@@@ -796,29 -634,28 -797,29 +797,29 @@@@ strcpy(filename_buf, filename); filename = filename_buf; - { - struct commit* c; - if (get_sha1(commit, sha1)) - die("get_sha1 failed, commit '%s' not found", commit); - c = lookup_commit_reference(sha1); - - if (fill_util_info(c, filename)) { - printf("%s not found in %s\n", filename, commit); - return 1; - } + if (get_sha1(commit, sha1)) + die("get_sha1 failed, commit '%s' not found", commit); + start_commit = lookup_commit_reference(sha1); + get_util(start_commit)->pathname = filename; + if (fill_util_info(start_commit)) { + printf("%s not found in %s\n", filename, commit); + return 1; } - num_args = 0; - args[num_args++] = NULL; - args[num_args++] = "--topo-order"; - args[num_args++] = "--remove-empty"; - args[num_args++] = commit; - args[num_args++] = "--"; - args[num_args++] = filename; - args[num_args] = NULL; - setup_revisions(num_args, args, &rev, "HEAD"); + init_revisions(&rev); + rev.remove_empty_trees = 1; + rev.topo_order = 1; + rev.prune_fn = simplify_commit; + rev.topo_setter = topo_setter; + rev.topo_getter = topo_getter; + rev.limited = 1; + + commit_list_insert(start_commit, &rev.commits); + + args[0] = filename; + args[1] = NULL; + diff_tree_setup_paths(args); prepare_revision_walk(&rev); process_commits(&rev, filename, &initial); @@@@ -826,47 -663,20 -827,47 +827,47 @@@@ for (max_digits = 1, i = 10; i <= num_blame_lines + 1; max_digits++) i *= 10; + longest_file = 0; + longest_author = 0; + found_rename = 0; for (i = 0; i < num_blame_lines; i++) { struct commit *c = blame_lines[i]; + struct util_info* u; if (!c) c = initial; + u = c->object.util; + if (!found_rename && strcmp(filename, u->pathname)) + found_rename = 1; + if (longest_file < strlen(u->pathname)) + longest_file = strlen(u->pathname); + get_commit_info(c, &ci); + if (longest_author < strlen(ci.author)) + longest_author = strlen(ci.author); + } + + for (i = 0; i < num_blame_lines; i++) { + struct commit *c = blame_lines[i]; + struct util_info* u; + + if (!c) + c = initial; + + u = c->object.util; get_commit_info(c, &ci); fwrite(sha1_to_hex(c->object.sha1), sha1_len, 1, stdout); - if(compability) + if(compability) { printf("\t(%10s\t%10s\t%d)", ci.author, format_time(ci.author_time, ci.author_tz), i+1); - else - printf(" (%-15.15s %10s %*d) ", ci.author, + } else { + if (found_rename) + printf(" %-*.*s", longest_file, longest_file, + u->pathname); + printf(" (%-*.*s %10s %*d) ", + longest_author, longest_author, ci.author, format_time(ci.author_time, ci.author_tz), max_digits, i+1); + } if(i == num_blame_lines - 1) { fwrite(buf, blame_len - (buf - blame_contents), diff --combined git-fetch.sh index 68356343a6,c0eb96752e,0346d4a45c..954901ddce --- a/git-fetch.sh +++ b/git-fetch.sh @@@@ -94,6 -94,9 -94,6 +94,9 @@@@ append_fetch_head () # remote-nick is the URL given on the command line (or a shorthand) # remote-name is the $GIT_DIR relative refs/ path we computed # for this refspec. + + + + # the $note_ variable will be fed to git-fmt-merge-msg for further + + # processing. case "$remote_name_" in HEAD) note_= ;; @@@@ -103,6 -106,9 -103,6 +106,9 @@@@ refs/tags/*) note_="$(expr "$remote_name_" : 'refs/tags/\(.*\)')" note_="tag '$note_' of " ;; + + refs/remotes/*) + + note_="$(expr "$remote_name_" : 'refs/remotes/\(.*\)')" + + note_="remote branch '$note_' of " ;; *) note_="$remote_name of " ;; esac @@@@ -147,10 -153,10 -147,10 +153,10 @@@@ fast_forward_local () else echo >&2 "* $1: storing $3" fi - - git-update-ref "$1" "$2" + + git-update-ref "$1" "$2" ;; - - refs/heads/*) + + refs/heads/* | refs/remotes/*) # $1 is the ref being updated. # $2 is the new value for the ref. local=$(git-rev-parse --verify "$1^0" 2>/dev/null) @@@@ -179,7 -185,6 -179,6 +185,7 @@@@ ;; *) echo >&2 " not updating." ++ exit 1 ;; esac }