Merge branch 'jc/pickaxe' into next

* jc/pickaxe:
  Introduce a new revision set operator <rev>^!
  git-pickaxe: cache one already found path per commit.
This commit is contained in:
Junio C Hamano
2006-11-01 13:22:16 -08:00
4 changed files with 75 additions and 7 deletions

View File

@@ -111,6 +111,44 @@ The contents of the actual line is output after the above
header, prefixed by a TAB. This is to allow adding more
header elements later.
SPECIFIYING RANGES
------------------
Unlike `git-blame` and `git-annotate` in older git, the extent
of annotation can be limited to both line ranges and revision
ranges. When you are interested in finding the origin for
ll. 40-60 for file `foo`, you can use `-L` option like this:
git pickaxe -L 40,60 foo
When you are not interested in changes older than the version
v2.6.18, or changes older than 3 weeks, you can use revision
range specifiers similar to `git-rev-list`:
git pickaxe v2.6.18.. -- foo
git pickaxe --since=3.weeks -- foo
When revision range specifiers are used to limit the annotation,
lines that have not changed since the range boundary (either the
commit v2.6.18 or the most recent commit that is more than 3
weeks old in the above example) are blamed for that range
boundary commit.
A particularly useful way is to see if an added file have lines
created by copy-and-paste from existing files. Sometimes this
indicates that the developer was being sloppy and did not
refactor the code properly. You can first find the commit that
introduced the file with:
git log --diff-filter=A --pretty=short -- foo
and then annotate the change between the commit and its
parents, using `commit{caret}!` notation:
git pickaxe -C -C -f $commit^! -- foo
SEE ALSO
--------
gitlink:git-blame[1]

View File

@@ -239,14 +239,21 @@ of `r1` and `r2` and is defined as
It it the set of commits that are reachable from either one of
`r1` or `r2` but not from both.
Here are a few examples:
Two other shorthands for naming a set that is formed by a commit
and its parent commits exists. `r1{caret}@` notation means all
parents of `r1`. `r1{caret}!` includes commit `r1` but excludes
its all parents.
Here are a handful examples:
D A B D
D F A B C D F
^A G B D
^A G B D
^A F B C F
G...I C D F G I
^B G I C D F G I
^B G I C D F G I
F^@ A B C
F^! H D F H
Author
------

View File

@@ -141,6 +141,8 @@ static int cmp_suspect(struct origin *a, struct origin *b)
return strcmp(a->path, b->path);
}
#define cmp_suspect(a, b) ( ((a)==(b)) ? 0 : cmp_suspect(a,b) )
static void sanity_check_refcnt(struct scoreboard *);
static void coalesce(struct scoreboard *sb)
@@ -213,6 +215,12 @@ static struct origin *find_origin(struct scoreboard *sb,
struct diff_options diff_opts;
const char *paths[2];
if (parent->util) {
struct origin *cached = parent->util;
if (!strcmp(cached->path, origin->path))
return origin_incref(cached);
}
/* See if the origin->path is different between parent
* and origin first. Most of the time they are the
* same and diff-tree is fairly efficient about this.
@@ -259,6 +267,12 @@ static struct origin *find_origin(struct scoreboard *sb,
}
}
diff_flush(&diff_opts);
if (porigin) {
origin_incref(porigin);
if (parent->util)
origin_decref(parent->util);
parent->util = porigin;
}
return porigin;
}
@@ -905,7 +919,7 @@ static void pass_blame(struct scoreboard *sb, struct origin *origin, int opt)
continue;
if (parse_commit(p))
continue;
porigin = find(sb, parent->item, origin);
porigin = find(sb, p, origin);
if (!porigin)
continue;
if (!hashcmp(porigin->blob_sha1, origin->blob_sha1)) {
@@ -1371,8 +1385,10 @@ static void sanity_check_refcnt(struct scoreboard *sb)
ent->suspect->refcnt = -ent->suspect->refcnt;
}
for (ent = sb->ent; ent; ent = ent->next) {
/* then pick each and see if they have the the
* correct refcnt
/* then pick each and see if they have the the correct
* refcnt; note that ->util caching means origin's refcnt
* may well be greater than the number of blame entries
* that use it.
*/
int found;
struct blame_entry *e;
@@ -1386,7 +1402,7 @@ static void sanity_check_refcnt(struct scoreboard *sb)
continue;
found++;
}
if (suspect->refcnt != found)
if (suspect->refcnt < found)
baa = 1;
}
if (baa) {

View File

@@ -657,6 +657,13 @@ int handle_revision_arg(const char *arg, struct rev_info *revs,
return 0;
*dotdot = '^';
}
dotdot = strstr(arg, "^!");
if (dotdot && !dotdot[2]) {
*dotdot = 0;
if (!add_parents_only(revs, arg, flags ^ UNINTERESTING))
*dotdot = '^';
}
local_flags = 0;
if (*arg == '^') {
local_flags = UNINTERESTING;