* [PATCH 2/2] Support "history replay" for git log commands
From: Linus Torvalds @ 2007-11-02 20:35 UTC (permalink / raw)
To: Marco Costalba; +Cc: Paul Mackerras, git
In-Reply-To: <alpine.LFD.0.999.0711021301200.3342@woody.linux-foundation.org>
This notices if we aren't in topological order, and replays the history.
Thus avoiding the need to sort history up front.
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
---
See the code and the more complete explanations in [PATCH 0/2]. In
particular, see the last section there about the downsides of this: the
50x expansion of output on the kernel is unacceptable, but if somebody can
make a graphical viewer that can react correctly to the "Replay" thing,
I'm sure I can make the replays themselves happen much more rarely.
builtin-blame.c | 2 +-
builtin-log.c | 35 +++++++++++++++++++++++++++++++++++
log-tree.c | 10 +++++++---
revision.c | 29 ++++++++++++++++++++++-------
revision.h | 6 +++++-
5 files changed, 70 insertions(+), 12 deletions(-)
diff --git a/builtin-blame.c b/builtin-blame.c
index 8432b82..7b6af8c 100644
--- a/builtin-blame.c
+++ b/builtin-blame.c
@@ -1502,7 +1502,7 @@ static void assign_blame(struct scoreboard *sb, struct rev_info *revs, int opt)
else {
commit->object.flags |= UNINTERESTING;
if (commit->object.parsed)
- mark_parents_uninteresting(commit);
+ mark_parents_uninteresting(revs, commit);
}
/* treat root commit as boundary */
if (!commit->parents && !show_root)
diff --git a/builtin-log.c b/builtin-log.c
index e8b982d..10e0821 100644
--- a/builtin-log.c
+++ b/builtin-log.c
@@ -77,6 +77,35 @@ static void cmd_log_init(int argc, const char **argv, const char *prefix,
}
}
+static void replay_history(struct rev_info *revs)
+{
+ struct commit_list *entry;
+
+ revs->trigger_replay = 0;
+ while ((entry = revs->shown) != NULL) {
+ struct commit *commit = entry->item;
+ unsigned flags = commit->object.flags;
+
+ /* Undo the SHOWN and FORCE_REPLAY bits */
+ commit->object.flags = flags & ~(SHOWN | FORCE_REPLAY);
+ commit->indegree = 0;
+
+ /* Remove it from the shown list, put it on the commit list */
+ revs->shown = entry->next;
+ entry->next = revs->commits;
+ revs->commits = entry;
+
+ printf("Replay %s\n", sha1_to_hex(commit->object.sha1));
+
+ /* Was this the one that caused us to replay? */
+ if (flags & FORCE_REPLAY)
+ break;
+ }
+
+ /* Ok, sort the list to be replayed properly now.. */
+ sort_in_topological_order(&revs->commits, revs->lifo);
+}
+
static int cmd_log_walk(struct rev_info *rev)
{
struct commit *commit;
@@ -84,6 +113,12 @@ static int cmd_log_walk(struct rev_info *rev)
prepare_revision_walk(rev);
while ((commit = get_revision(rev)) != NULL) {
log_tree_commit(rev, commit);
+
+ if (rev->replay_history) {
+ if (rev->trigger_replay)
+ replay_history(rev);
+ continue;
+ }
if (!rev->reflog_info) {
/* we allow cycles in reflog ancestry */
free(commit->buffer);
diff --git a/log-tree.c b/log-tree.c
index 3763ce9..ce9b887 100644
--- a/log-tree.c
+++ b/log-tree.c
@@ -6,12 +6,16 @@
struct decoration name_decoration = { "object names" };
-static void show_parents(struct commit *commit, int abbrev)
+static void show_parents(struct rev_info *opt, struct commit *commit, int abbrev)
{
struct commit_list *p;
for (p = commit->parents; p ; p = p->next) {
struct commit *parent = p->item;
printf(" %s", diff_unique_abbrev(parent->object.sha1, abbrev));
+ if (parent->object.flags & SHOWN) {
+ opt->trigger_replay = 1;
+ parent->object.flags |= FORCE_REPLAY;
+ }
}
}
@@ -147,7 +151,7 @@ void show_log(struct rev_info *opt, const char *sep)
}
fputs(diff_unique_abbrev(commit->object.sha1, abbrev_commit), stdout);
if (opt->parents)
- show_parents(commit, abbrev_commit);
+ show_parents(opt, commit, abbrev_commit);
show_decorations(commit);
putchar(opt->diffopt.line_termination);
return;
@@ -248,7 +252,7 @@ void show_log(struct rev_info *opt, const char *sep)
fputs(diff_unique_abbrev(commit->object.sha1, abbrev_commit),
stdout);
if (opt->parents)
- show_parents(commit, abbrev_commit);
+ show_parents(opt, commit, abbrev_commit);
if (parent)
printf(" (from %s)",
diff_unique_abbrev(parent->object.sha1,
diff --git a/revision.c b/revision.c
index e85b4af..e40bc1c 100644
--- a/revision.c
+++ b/revision.c
@@ -79,7 +79,7 @@ void mark_tree_uninteresting(struct tree *tree)
tree->buffer = NULL;
}
-void mark_parents_uninteresting(struct commit *commit)
+void mark_parents_uninteresting(struct rev_info *revs, struct commit *commit)
{
struct commit_list *parents = commit->parents;
@@ -87,6 +87,10 @@ void mark_parents_uninteresting(struct commit *commit)
struct commit *commit = parents->item;
if (!(commit->object.flags & UNINTERESTING)) {
commit->object.flags |= UNINTERESTING;
+ if (commit->object.flags & SHOWN) {
+ revs->trigger_replay = 1;
+ commit->object.flags |= FORCE_REPLAY;
+ }
/*
* Normally we haven't parsed the parent
@@ -97,7 +101,7 @@ void mark_parents_uninteresting(struct commit *commit)
* to mark its parents recursively too..
*/
if (commit->parents)
- mark_parents_uninteresting(commit);
+ mark_parents_uninteresting(revs, commit);
}
/*
@@ -167,8 +171,9 @@ static struct commit *handle_commit(struct rev_info *revs, struct object *object
die("unable to parse commit %s", name);
if (flags & UNINTERESTING) {
commit->object.flags |= UNINTERESTING;
- mark_parents_uninteresting(commit);
- revs->limited = 1;
+ mark_parents_uninteresting(revs, commit);
+ if (!revs->replay_history)
+ revs->limited = 1;
}
return commit;
}
@@ -399,7 +404,7 @@ static int add_parents_to_list(struct rev_info *revs, struct commit *commit, str
return -1;
p->object.flags |= UNINTERESTING;
if (p->parents)
- mark_parents_uninteresting(p);
+ mark_parents_uninteresting(revs, p);
if (p->object.flags & SEEN)
continue;
p->object.flags |= SEEN;
@@ -542,7 +547,7 @@ static int limit_list(struct rev_info *revs)
if (add_parents_to_list(revs, commit, &list) < 0)
return -1;
if (obj->flags & UNINTERESTING) {
- mark_parents_uninteresting(commit);
+ mark_parents_uninteresting(revs, commit);
if (everybody_uninteresting(list))
break;
continue;
@@ -995,6 +1000,10 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch
revs->parents = 1;
continue;
}
+ if (!strcmp(arg, "--replay")) {
+ revs->replay_history = 1;
+ continue;
+ }
if (!strcmp(arg, "--dense")) {
revs->dense = 1;
continue;
@@ -1386,7 +1395,13 @@ static struct commit *get_revision_1(struct rev_info *revs)
struct commit *commit = entry->item;
revs->commits = entry->next;
- free(entry);
+
+ /* Are we going to potentially replay? */
+ if (revs->replay_history) {
+ entry->next = revs->shown;
+ revs->shown = entry;
+ } else
+ free(entry);
if (revs->reflog_info)
fake_reflog_parent(revs->reflog_info, commit);
diff --git a/revision.h b/revision.h
index 1f64576..75b320d 100644
--- a/revision.h
+++ b/revision.h
@@ -11,6 +11,7 @@
#define ADDED (1u<<7) /* Parents already parsed and added? */
#define SYMMETRIC_LEFT (1u<<8)
#define TOPOSORT (1u<<9) /* In the active toposort list.. */
+#define FORCE_REPLAY (1u<<10) /* This commit was wrong somehow */
struct rev_info;
struct log_info;
@@ -20,6 +21,7 @@ typedef void (prune_fn_t)(struct rev_info *revs, struct commit *commit);
struct rev_info {
/* Starting list */
struct commit_list *commits;
+ struct commit_list *shown;
struct object_array pending;
/* Parents of shown commits */
@@ -36,6 +38,8 @@ struct rev_info {
no_walk:1,
remove_empty_trees:1,
simplify_history:1,
+ replay_history:1,
+ trigger_replay:1,
lifo:1,
topo_order:1,
tag_objects:1,
@@ -113,7 +117,7 @@ extern int handle_revision_arg(const char *arg, struct rev_info *revs,int flags,
extern int prepare_revision_walk(struct rev_info *revs);
extern struct commit *get_revision(struct rev_info *revs);
-extern void mark_parents_uninteresting(struct commit *commit);
+extern void mark_parents_uninteresting(struct rev_info *revs, struct commit *commit);
extern void mark_tree_uninteresting(struct tree *tree);
struct name_path {
^ permalink raw reply related
* Re: [PATCH] git-rev-list.txt: rev stands for revision, not reverse.
From: Junio C Hamano @ 2007-11-02 20:46 UTC (permalink / raw)
To: Ralf Wildenhues; +Cc: git
In-Reply-To: <7vprys1k5m.fsf@gitster.siamese.dyndns.org>
Junio C Hamano <gitster@pobox.com> writes:
> Ralf Wildenhues <Ralf.Wildenhues@gmx.de> writes:
>
>> Is the reverse chronological order the primary sorting key at all?
>
> It is mostly chrono but there is a topo element as well. You
> would never see a parent none of whose child is shown.
To be precise...
Internally, it mainly works on topology with an additional logic
to tiebreak with commit timestamps.
- We always have one or more "output candidates".
- Initially, the set of output candidates are primed from the
positive refs (e.g. "foo", foo in "bar..foo", foo and bar in
"bar...foo") you give to rev-list and/or log family of
commands, after reachability analysis with negative refs
(e.g. "^foo", bar in "bar..foo", merge-base of foo and bar in
"bar...foo") if present.
- We output the latest one among output candidates. The
parents of the commit we output go through the reachability
analysis and the ones that are reachable from any of the
negative refs are removed. The ones that survive this
reachability analysis are added to the output candidates.
And the process starts over. The algorithm terminates when
there is none.
In practice, because child commits tend to get later commit
timestamps than all of their parent commits, the output looks
mostly reverse chronological.
^ permalink raw reply
* Re: [PATCH 2/2] Support "history replay" for git log commands
From: Junio C Hamano @ 2007-11-02 21:05 UTC (permalink / raw)
To: Linus Torvalds; +Cc: Marco Costalba, Paul Mackerras, git
In-Reply-To: <alpine.LFD.0.999.0711021333050.3342@woody.linux-foundation.org>
Linus Torvalds <torvalds@linux-foundation.org> writes:
> This notices if we aren't in topological order, and replays the history.
> Thus avoiding the need to sort history up front.
>
> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
> ---
>
> See the code and the more complete explanations in [PATCH 0/2]. In
> particular, see the last section there about the downsides of this: the
> 50x expansion of output on the kernel is unacceptable, but if somebody can
> make a graphical viewer that can react correctly to the "Replay" thing,
> I'm sure I can make the replays themselves happen much more rarely.
>
> builtin-blame.c | 2 +-
> builtin-log.c | 35 +++++++++++++++++++++++++++++++++++
> log-tree.c | 10 +++++++---
> revision.c | 29 ++++++++++++++++++++++-------
> revision.h | 6 +++++-
> 5 files changed, 70 insertions(+), 12 deletions(-)
>
> diff --git a/builtin-blame.c b/builtin-blame.c
> index 8432b82..7b6af8c 100644
> --- a/builtin-blame.c
> +++ b/builtin-blame.c
> @@ -1502,7 +1502,7 @@ static void assign_blame(struct scoreboard *sb, struct rev_info *revs, int opt)
> else {
> commit->object.flags |= UNINTERESTING;
> if (commit->object.parsed)
> - mark_parents_uninteresting(commit);
> + mark_parents_uninteresting(revs, commit);
> }
> /* treat root commit as boundary */
> if (!commit->parents && !show_root)
> diff --git a/builtin-log.c b/builtin-log.c
> index e8b982d..10e0821 100644
> --- a/builtin-log.c
> +++ b/builtin-log.c
> @@ -77,6 +77,35 @@ static void cmd_log_init(int argc, const char **argv, const char *prefix,
> }
> }
>
> +static void replay_history(struct rev_info *revs)
> +{
> + struct commit_list *entry;
> +
> + revs->trigger_replay = 0;
> + while ((entry = revs->shown) != NULL) {
> + struct commit *commit = entry->item;
> + unsigned flags = commit->object.flags;
> +
> + /* Undo the SHOWN and FORCE_REPLAY bits */
> + commit->object.flags = flags & ~(SHOWN | FORCE_REPLAY);
> + commit->indegree = 0;
> +
> + /* Remove it from the shown list, put it on the commit list */
> + revs->shown = entry->next;
> + entry->next = revs->commits;
> + revs->commits = entry;
> +
> + printf("Replay %s\n", sha1_to_hex(commit->object.sha1));
> +
> + /* Was this the one that caused us to replay? */
> + if (flags & FORCE_REPLAY)
> + break;
Can one iteration of loop in log_tree_commit() smudge more
than one commits with FORCE_REPLAY? Maybe make the
trigger_replay a counter and count down in this loop until we
find that many commits that have the FORCE_REPLAY flag?
^ permalink raw reply
* Re: [PATCH 1/4] Add testcase for ammending and fixing author in git commit.
From: Kristian Høgsberg @ 2007-11-02 21:13 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <7vy7dg1kdg.fsf@gitster.siamese.dyndns.org>
On Fri, 2007-11-02 at 13:07 -0700, Junio C Hamano wrote:
> Kristian Høgsberg <krh@redhat.com> writes:
>
> > Signed-off-by: Kristian Høgsberg <krh@redhat.com>
> > ---
> > t/t7501-commit.sh | 10 ++++++++++
> > 1 files changed, 10 insertions(+), 0 deletions(-)
> >
> > diff --git a/t/t7501-commit.sh b/t/t7501-commit.sh
> > index b151b51..3f2112a 100644
> > --- a/t/t7501-commit.sh
> > +++ b/t/t7501-commit.sh
> > @@ -163,4 +163,14 @@ test_expect_success 'partial commit that involves removal (3)' '
> >
> > '
> >
> > +author="The Real Author <someguy@his.email.org>"
> > +test_expect_success 'amend commit to fix author' '
> > +
> > + git reset --hard
> > + git cat-file -p HEAD | sed -e "s/author.*>/author $author/" > expected &&
> > + git commit --amend --author="$author" &&
> > + git cat-file -p HEAD > current &&
> > + diff expected current
> > +
> > +'
> > test_done
>
> This can't be right. How are you ignoring the differences in
> committer dates?
t/test-lib.sh fixes GIT_COMMITTER_DATE so all commits have the date
committer C O Mitter <committer@example.com> 1112911993 -0700
unless you use test_tick.
> By the way, I _think_ git-commit.sh allows fixing author name/email
> without molesting the author timestamp (i.e. takes it from the
> amended commit). That should probably be checked with the test
> as well.
You're right, I need to pick GIT_AUTHOR_DATE from the ammended commit.
Ok, I'll need to rewrite determine_author_info() a little bit. I might
get an update patch out this weekend.
cheers,
Kristian
^ permalink raw reply
* Re: [PATCH 2/2] Support "history replay" for git log commands
From: Linus Torvalds @ 2007-11-02 21:17 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Marco Costalba, Paul Mackerras, git
In-Reply-To: <7v4pg41hq0.fsf@gitster.siamese.dyndns.org>
On Fri, 2 Nov 2007, Junio C Hamano wrote:
>
> Can one iteration of loop in log_tree_commit() smudge more
> than one commits with FORCE_REPLAY? Maybe make the
> trigger_replay a counter and count down in this loop until we
> find that many commits that have the FORCE_REPLAY flag?
Good point, and yes, that sounds like the right thing to do.
Linus
^ permalink raw reply
* Re: [PATCH] Make git-clone obey "--" (end argument parsing)
From: Junio C Hamano @ 2007-11-02 21:32 UTC (permalink / raw)
To: Heikki Orsila; +Cc: git
In-Reply-To: <20071102142150.GD9632@jolt.modeemi.cs.tut.fi>
Heikki Orsila <shd@modeemi.fi> writes:
> Junio C Hamano wrote:
>> I do not think this breaks anything, but does it _help_
>> anything in practice?
>>
>> What kind of breakage does this patch fix?
>
> It doesn't fix anything, but it is a good usability standard to obey --.
> I was creating a script that would _automatically_ clone repositories of
> other users. As a little bit pedantic shell script writer I added "--"
> and noticed that git clone doesn't handle that,...
The first real parameter will always be the remote repo
URL^Wlocator, and sane people won't have anything that begin
with a hyphen for that, will they?
So the change is only for consistency's sake.
I am not saying that is a bad thing. I just wanted to
understand if there was a real breakage there.
Thanks. Will apply.
^ permalink raw reply
* Re: git rm --cached
From: Jing Xue @ 2007-11-02 21:41 UTC (permalink / raw)
To: Remi Vanicat; +Cc: git
In-Reply-To: <87mytwiq1f.dlv@vanicat.homelinux.org>
Quoting Remi Vanicat <vanicat@debian.org>:
> Jing Xue <jingxue@digizenstudio.com> writes:
>
>> In the following scenario, why do I have to run 'git reset' following
>> 'git rm --cached 1.txt' to revert to exactly where I was before 'git add
>> 1.txt'? Shouldn't 'git rm --cached' have done that already?
>
> Observed behavior are exactly what I expected: 'git rm --cached' mark
> the file in the index as been deleted without deleting it in the
> working directories, it did not but the index it was before the
> 'git add 1.txt'.
I was confused by two things I guess:
1. I looked at the "index" as a staging area for _changes_ not files
themselves. So where 'man git-rm' says '--caches ... remove[s] the
paths only from the index, leaving working tree files.' I took it to
mean that it removes the changes on those paths, rather than staging a
new "path deletion" action for a later commit.
2. The FAQ entry "Why 'git rm' is not inverse of 'git add'" says "a
natural inverse of 'add' is 'un-add', and that operation is called 'rm
--cached',..." Now I realize that only applies to adding a new file,
but not changes on an existing file.
> You probably want to use git reset HEAD -- 1.txt to unstage
> modification on 1.txt
Sure.
Thanks.
--
Jing Xue
^ permalink raw reply
* Git-windows and git-svn?
From: Abdelrazak Younes @ 2007-11-02 21:55 UTC (permalink / raw)
To: git
Hello,
I would like to try git on Windows together with git-svn, I downloaded
Git-1.5.3-preview20071027.exe and tried:
yns@xxx /d/devel/lyx/git/trunk
$ git-svn init svn://svn.lyx.org/lyx/lyx-devel/trunk
Useless use of a constant in void context at /bin/git-svn line 848.
Can't locate Digest/MD5.pm in @INC (@INC contains: /lib
/usr/lib/perl5/5.6.1/msy
s /usr/lib/perl5/5.6.1 /usr/lib/perl5/site_perl/5.6.1/msys
/usr/lib/perl5/site_p
erl/5.6.1 /usr/lib/perl5/site_perl .) at /bin/git-svn line 2420.
BEGIN failed--compilation aborted at /bin/git-svn line 2420.
Is there something I am doing wrong?
Thanks in advance for any help,
Abdel.
^ permalink raw reply
* Re: [PATCH] Mention that git-branch -M can cause problems for tracking branches
From: Jonas Fonseca @ 2007-11-02 22:04 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <7vlk9g1k1q.fsf@gitster.siamese.dyndns.org>
Junio C Hamano <gitster@pobox.com> wrote Fri, Nov 02, 2007:
> Jonas Fonseca <fonseca@diku.dk> writes:
>
> > Signed-off-by: Jonas Fonseca <fonseca@diku.dk>
> > ---
> > Documentation/git-branch.txt | 5 +++++
> > 1 files changed, 5 insertions(+), 0 deletions(-)
> >
> > I made a patch to discard the overwritten branch's configuration
> > section, which Spearce felt was too lossy a behaviour. However, since
> > it confused me, I think it should at least be mentioned in the manpage.
> > Maybe the warning message from git should also be added to improve its
> > "googlability".
> >
> > diff --git a/Documentation/git-branch.txt b/Documentation/git-branch.txt
> > index 5e81aa4..def4e85 100644
> > --- a/Documentation/git-branch.txt
> > +++ b/Documentation/git-branch.txt
> > @@ -165,6 +165,11 @@ If you are creating a branch that you want to immediately checkout, it's
> > easier to use the git checkout command with its `-b` option to create
> > a branch and check it out with a single command.
> >
> > +When a branch is renamed so that it overwrites an existing branch unintended
> > +problems can arise. This is because git refuses to discard the configuration
> > +section of the overwritten branch. As a result git can become confused if, for
> > +example, the branches involved were used for tracking two different remote
> > +branches. The only way to fix this is to edit the configuration file manually.
>
> I do not understand this bit about "refuse".
>
> - To "refuse to discard", somebody has to ask to discard ---
> who asks so and when?
IMO, the user asks when using git-branch -M. And in case it is not clear
the problem arises for the command sequence:
$ git branch --track o-next origin/next
$ git branch --track m-next madcoder/next
$ git branch -M o-next m-next
$ git remote
Warning: more than one branch.m-next.remote
...
> - Is there a reason to "refuse" when such a removal request is
> made? If so, what is it? If not, why refusal?
Personally, I don't see why we need to refuse, since git-branch -M is
somewhat similar to saying -m (rename) plus adding a "force" flag
meaning: "yes, I know that this will potentially throw away settings for
an already existing branch".
The main reason to "refuse" the removal is that for the general case,
e.g. when using `git-config --rename-section`, this can potentially lead
to loss of valuable config settings. This was pointed out by Shawn in
his reply to my patch[0]. I agreed to this in my follow-up and asked if
it would be acceptable to add an additional flag to so that git-branch
can switch on this request for removal.
[0] http://thread.gmane.org/gmane.comp.version-control.git/61291
--
Jonas Fonseca
^ permalink raw reply
* Re: Git-windows and git-svn?
From: Johannes Schindelin @ 2007-11-02 22:07 UTC (permalink / raw)
To: Abdelrazak Younes; +Cc: git
In-Reply-To: <fgg6cd$3ep$1@ger.gmane.org>
Hi,
On Fri, 2 Nov 2007, Abdelrazak Younes wrote:
> I would like to try git on Windows together with git-svn, I downloaded
> Git-1.5.3-preview20071027.exe and tried:
>
> yns@xxx /d/devel/lyx/git/trunk
> $ git-svn init svn://svn.lyx.org/lyx/lyx-devel/trunk
> Useless use of a constant in void context at /bin/git-svn line 848.
> Can't locate Digest/MD5.pm in @INC (@INC contains: /lib
> /usr/lib/perl5/5.6.1/msy
> s /usr/lib/perl5/5.6.1 /usr/lib/perl5/site_perl/5.6.1/msys
> /usr/lib/perl5/site_p
> erl/5.6.1 /usr/lib/perl5/site_perl .) at /bin/git-svn line 2420.
> BEGIN failed--compilation aborted at /bin/git-svn line 2420.
>
> Is there something I am doing wrong?
The proper mailinglist for this is msysgit@googlegroups.com. And right
next to the "Downloads" tab you clicked on to download the installer,
there is an "Issues" tab. There you'll find that we're working on it.
Hth,
Dscho
^ permalink raw reply
* Re: Git-windows and git-svn?
From: Abdelrazak Younes @ 2007-11-02 22:26 UTC (permalink / raw)
To: git
In-Reply-To: <Pine.LNX.4.64.0711022206190.4362@racer.site>
Johannes Schindelin wrote:
>> Is there something I am doing wrong?
>
> The proper mailinglist for this is msysgit@googlegroups.com.
Sorry, I'll move to that. Any chance you create a gmane news interface?
> And right
> next to the "Downloads" tab you clicked on to download the installer,
> there is an "Issues" tab. There you'll find that we're working on it.
Oups, sorry again, haven't see this tab.
Thanks and sorry for the noise,
Abdel.
^ permalink raw reply
* [PATCH v3] Add to gitk an --argscmd flag to get the list of refs to draw at refresh time.
From: Yann Dirson @ 2007-11-02 22:24 UTC (permalink / raw)
To: Paul Mackerras; +Cc: git
This allows to display a set of refs, when the refs in the set may
themselves change between two refresh operations (eg. the set of
patches in a patch stack), and is expected to be called from other
porcelain suites.
The command is expected to generate a list of commits, which will be
appended to the commits litterally passed on the command-line. That
command is handled similarly to the litteral refs, and has its own
field in the saved view, and an edit field in the view editor.
Signed-off-by: Yann Dirson <ydirson@altern.org>
---
This version is the same as v2, just rebased on current git master. Just let me know
if there are any issues left - notably with the concept of allowing both plain args and
argcmds.
Documentation/gitk.txt | 7 +++++
gitk | 67 ++++++++++++++++++++++++++++++++++++++----------
2 files changed, 60 insertions(+), 14 deletions(-)
diff --git a/Documentation/gitk.txt b/Documentation/gitk.txt
index 8dbfb0d..c3a98d4 100644
--- a/Documentation/gitk.txt
+++ b/Documentation/gitk.txt
@@ -41,6 +41,13 @@ frequently used options.
Show all branches.
+--argscmd=<command>::
+ Command to be run each time gitk has to determine the list of
+ <revs> to show. The command is expected to print on its
+ standard output a list of additional revs to be shown. Use
+ this instead of explicitely specifying <revs> if the set of
+ commits to show may vary between refreshs.
+
<revs>::
Limit the revisions to show. This can be either a single revision
diff --git a/gitk b/gitk
index 1da0b0a..5e6af40 100755
--- a/gitk
+++ b/gitk
@@ -82,7 +82,7 @@ proc dorunq {} {
proc start_rev_list {view} {
global startmsecs
global commfd leftover tclencoding datemode
- global viewargs viewfiles commitidx viewcomplete vnextroot
+ global viewargs viewargscmd viewfiles commitidx viewcomplete vnextroot
global showlocalchanges commitinterest mainheadid
global progressdirn progresscoords proglastnc curview
@@ -90,13 +90,24 @@ proc start_rev_list {view} {
set commitidx($view) 0
set viewcomplete($view) 0
set vnextroot($view) 0
+ set args $viewargs($view)
+ if {$viewargscmd($view) ne "None"} {
+ if {[catch {
+ set fd [open [concat | $viewargscmd($view)] r]
+ } err]} {
+ puts stderr "Error executing --argscmd command: $err"
+ exit 1
+ }
+ set args [concat $args [read $fd 500000]]
+ close $fd
+ }
set order "--topo-order"
if {$datemode} {
set order "--date-order"
}
if {[catch {
set fd [open [concat | git log --no-color -z --pretty=raw $order --parents \
- --boundary $viewargs($view) "--" $viewfiles($view)] r]
+ --boundary $args "--" $viewfiles($view)] r]
} err]} {
error_popup "Error executing git rev-list: $err"
exit 1
@@ -1154,7 +1165,7 @@ proc savestuff {w} {
global canv canv2 canv3 mainfont textfont uifont tabstop
global stuffsaved findmergefiles maxgraphpct
global maxwidth showneartags showlocalchanges
- global viewname viewfiles viewargs viewperm nextviewnum
+ global viewname viewfiles viewargs viewargscmd viewperm nextviewnum
global cmitmode wrapcomment datetimeformat limitdiffs
global colors bgcolor fgcolor diffcolors diffcontext selectbgcolor
@@ -1193,7 +1204,7 @@ proc savestuff {w} {
puts -nonewline $f "set permviews {"
for {set v 0} {$v < $nextviewnum} {incr v} {
if {$viewperm($v)} {
- puts $f "{[list $viewname($v) $viewfiles($v) $viewargs($v)]}"
+ puts $f "{[list $viewname($v) $viewfiles($v) $viewargs($v) $viewargscmd($v)]}"
}
}
puts $f "}"
@@ -1849,7 +1860,7 @@ proc shellsplit {str} {
proc newview {ishighlight} {
global nextviewnum newviewname newviewperm uifont newishighlight
- global newviewargs revtreeargs
+ global newviewargs revtreeargs viewargscmd newviewargscmd curview
set newishighlight $ishighlight
set top .gitkview
@@ -1860,13 +1871,14 @@ proc newview {ishighlight} {
set newviewname($nextviewnum) "View $nextviewnum"
set newviewperm($nextviewnum) 0
set newviewargs($nextviewnum) [shellarglist $revtreeargs]
+ set newviewargscmd($nextviewnum) [shellarglist $viewargscmd($curview)]
vieweditor $top $nextviewnum "Gitk view definition"
}
proc editview {} {
global curview
global viewname viewperm newviewname newviewperm
- global viewargs newviewargs
+ global viewargs newviewargs viewargscmd newviewargscmd
set top .gitkvedit-$curview
if {[winfo exists $top]} {
@@ -1876,6 +1888,7 @@ proc editview {} {
set newviewname($curview) $viewname($curview)
set newviewperm($curview) $viewperm($curview)
set newviewargs($curview) [shellarglist $viewargs($curview)]
+ set newviewargscmd($curview) [shellarglist $viewargscmd($curview)]
vieweditor $top $curview "Gitk: edit view $viewname($curview)"
}
@@ -1896,7 +1909,15 @@ proc vieweditor {top n title} {
grid $top.al - -sticky w -pady 5
entry $top.args -width 50 -textvariable newviewargs($n) \
-background white -font uifont
+
grid $top.args - -sticky ew -padx 5
+ message $top.ac -aspect 1000 -font uifont \
+ -text "Command to generate more commits to include:"
+ grid $top.ac - -sticky w -pady 5
+ entry $top.argscmd -width 50 -textvariable newviewargscmd($n) \
+ -background white -font uifont
+
+ grid $top.argscmd - -sticky ew -padx 5
message $top.l -aspect 1000 -font uifont \
-text "Enter files and directories to include, one per line:"
grid $top.l - -sticky w
@@ -1942,7 +1963,7 @@ proc allviewmenus {n op args} {
proc newviewok {top n} {
global nextviewnum newviewperm newviewname newishighlight
global viewname viewfiles viewperm selectedview curview
- global viewargs newviewargs viewhlmenu
+ global viewargs newviewargs viewargscmd newviewargscmd viewhlmenu
if {[catch {
set newargs [shellsplit $newviewargs($n)]
@@ -1952,6 +1973,14 @@ proc newviewok {top n} {
focus $top
return
}
+ if {[catch {
+ set newargscmd [shellsplit $newviewargscmd($n)]
+ } err]} {
+ error_popup "Error in commit selection command: $err"
+ wm raise $top
+ focus $top
+ return
+ }
set files {}
foreach f [split [$top.t get 0.0 end] "\n"] {
set ft [string trim $f]
@@ -1966,6 +1995,7 @@ proc newviewok {top n} {
set viewperm($n) $newviewperm($n)
set viewfiles($n) $files
set viewargs($n) $newargs
+ set viewargscmd($n) $newargscmd
addviewmenu $n
if {!$newishighlight} {
run showview $n
@@ -1982,9 +2012,11 @@ proc newviewok {top n} {
# doviewmenu $viewhlmenu 1 [list addvhighlight $n] \
# entryconf [list -label $viewname($n) -value $viewname($n)]
}
- if {$files ne $viewfiles($n) || $newargs ne $viewargs($n)} {
+ if {$files ne $viewfiles($n) || $newargs ne $viewargs($n) || \
+ $newargscmd ne $viewargscmd($n)} {
set viewfiles($n) $files
set viewargs($n) $newargs
+ set viewargscmd($n) $newargscmd
if {$curview == $n} {
run updatecommits
}
@@ -8505,18 +8537,22 @@ set mergeonly 0
set revtreeargs {}
set cmdline_files {}
set i 0
+set revtreeargscmd None
foreach arg $argv {
- switch -- $arg {
- "" { }
- "-d" { set datemode 1 }
- "--merge" {
+ switch -regexp -- $arg {
+ "^$" { }
+ "^-d$" { set datemode 1 }
+ "^--merge$" {
set mergeonly 1
lappend revtreeargs $arg
}
- "--" {
+ "^--$" {
set cmdline_files [lrange $argv [expr {$i + 1}] end]
break
}
+ "^--argscmd=" {
+ regexp {^--argscmd=(.*)} $arg match revtreeargscmd
+ }
default {
lappend revtreeargs $arg
}
@@ -8618,6 +8654,7 @@ set highlight_files {}
set viewfiles(0) {}
set viewperm(0) 0
set viewargs(0) {}
+set viewargscmd(0) None
set cmdlineok 0
set stopped 0
@@ -8633,7 +8670,7 @@ tkwait visibility .
wm title . "[file tail $argv0]: [file tail [pwd]]"
readrefs
-if {$cmdline_files ne {} || $revtreeargs ne {}} {
+if {$cmdline_files ne {} || $revtreeargs ne {} || $revtreeargscmd ne {}} {
# create a view for the files/dirs specified on the command line
set curview 1
set selectedview 1
@@ -8641,6 +8678,7 @@ if {$cmdline_files ne {} || $revtreeargs ne {}} {
set viewname(1) "Command line"
set viewfiles(1) $cmdline_files
set viewargs(1) $revtreeargs
+ set viewargscmd(1) $revtreeargscmd
set viewperm(1) 0
addviewmenu 1
.bar.view entryconf Edit* -state normal
@@ -8654,6 +8692,7 @@ if {[info exists permviews]} {
set viewname($n) [lindex $v 0]
set viewfiles($n) [lindex $v 1]
set viewargs($n) [lindex $v 2]
+ set viewargscmd($n) [lindex $v 3]
set viewperm($n) 1
addviewmenu $n
}
^ permalink raw reply related
* Re: [PATCH] Mention that git-branch -M can cause problems for tracking branches
From: Junio C Hamano @ 2007-11-02 22:30 UTC (permalink / raw)
To: Jonas Fonseca; +Cc: git, spearce
In-Reply-To: <20071102220411.GA13666@diku.dk>
Jonas Fonseca <fonseca@diku.dk> writes:
> The main reason to "refuse" the removal is that for the general case,
> e.g. when using `git-config --rename-section`, this can potentially lead
> to loss of valuable config settings. This was pointed out by Shawn in
> his reply to my patch[0]. I agreed to this in my follow-up and asked if
> it would be acceptable to add an additional flag to so that git-branch
> can switch on this request for removal.
So when you rename branch.foo section to branch.bar, instead of
replacing the whole existing branch.bar with what used to be in
branch.foo, you _append_ that to branch.bar?
That sounds insane.
What good does it do to keep what used to be branch.bar? The
old contents in the section are by no means "valuable". They
were about 'bar' and do not even have anything to do with the
branch being renamed, which used to be called 'foo'.
Shawn's example of modifying multi-valued variable is
irrelevant. Over there, we have options to replace everything
or append to it, don't we?
If the option is --rename-section, that is "rename section", not
"merge section". If for some reason a merge section operation
is needed, that should be supplied in a separate patch, but for
the branch renaming I really do not see the need for it.
^ permalink raw reply
* Re: [PATCH 1/4] Add testcase for ammending and fixing author in git commit.
From: Junio C Hamano @ 2007-11-02 22:33 UTC (permalink / raw)
To: Kristian Høgsberg; +Cc: git
In-Reply-To: <1194038030.25288.20.camel@hinata.boston.redhat.com>
Kristian Høgsberg <krh@redhat.com> writes:
>> This can't be right. How are you ignoring the differences in
>> committer dates?
>
> t/test-lib.sh fixes GIT_COMMITTER_DATE so all commits have the date
>
> committer C O Mitter <committer@example.com> 1112911993 -0700
>
> unless you use test_tick.
Heh, that was actually what I was getting at. By not doing
test_tick, you are not making sure that the commit gets the
timestamp of the time --amend is run.
>> By the way, I _think_ git-commit.sh allows fixing author name/email
>> without molesting the author timestamp (i.e. takes it from the
>> amended commit). That should probably be checked with the test
>> as well.
>
> You're right, I need to pick GIT_AUTHOR_DATE from the ammended commit.
> Ok, I'll need to rewrite determine_author_info() a little bit. I might
> get an update patch out this weekend.
^ permalink raw reply
* [PATCH 2/5] Update git-sh-setup(1) to allow transparent use of git-rev-parse --parseopt
From: Pierre Habouzit @ 2007-11-02 22:39 UTC (permalink / raw)
To: gitster, torvalds, Junio C Hamano; +Cc: git, Pierre Habouzit
In-Reply-To: <1194043193-29601-2-git-send-email-madcoder@debian.org>
If you set OPTIONS_SPEC, git-sh-setups uses git-rev-parse --parseopt
automatically.
It also diverts usage to re-exec $0 with the -h option as parse-options.c
will catch that.
PARSEOPT_OPTS can also be used to pass options git git-rev-parse --parseopt
mode (like --keep-dashdash).
Signed-off-by: Pierre Habouzit <madcoder@debian.org>
---
git-sh-setup.sh | 44 ++++++++++++++++++++++++++------------------
1 files changed, 26 insertions(+), 18 deletions(-)
diff --git a/git-sh-setup.sh b/git-sh-setup.sh
index 86d7d4c..330b78e 100755
--- a/git-sh-setup.sh
+++ b/git-sh-setup.sh
@@ -16,9 +16,32 @@ die() {
exit 1
}
-usage() {
- die "Usage: $0 $USAGE"
-}
+if test -n "$OPTIONS_SPEC"; then
+ usage() {
+ exec "$0" -h
+ }
+
+ eval `echo "$OPTIONS_SPEC" | git rev-parse --parseopt $PARSEOPT_OPTS -- "$@" || echo exit $?`
+else
+ usage() {
+ die "Usage: $0 $USAGE"
+ }
+
+ if [ -z "$LONG_USAGE" ]
+ then
+ LONG_USAGE="Usage: $0 $USAGE"
+ else
+ LONG_USAGE="Usage: $0 $USAGE
+
+$LONG_USAGE"
+ fi
+
+ case "$1" in
+ -h|--h|--he|--hel|--help)
+ echo "$LONG_USAGE"
+ exit
+ esac
+fi
set_reflog_action() {
if [ -z "${GIT_REFLOG_ACTION:+set}" ]
@@ -91,21 +114,6 @@ get_author_ident_from_commit () {
LANG=C LC_ALL=C sed -ne "$pick_author_script"
}
-if [ -z "$LONG_USAGE" ]
-then
- LONG_USAGE="Usage: $0 $USAGE"
-else
- LONG_USAGE="Usage: $0 $USAGE
-
-$LONG_USAGE"
-fi
-
-case "$1" in
- -h|--h|--he|--hel|--help)
- echo "$LONG_USAGE"
- exit
-esac
-
# Make sure we are in a valid repository of a vintage we understand.
if [ -z "$SUBDIRECTORY_OK" ]
then
--
1.5.3.5.1460.gdb47
^ permalink raw reply related
* [PATCH 3/5] Migrate git-clean.sh to use git-rev-parse --parseopt.
From: Pierre Habouzit @ 2007-11-02 22:39 UTC (permalink / raw)
To: gitster, torvalds, Junio C Hamano; +Cc: git, Pierre Habouzit
In-Reply-To: <1194043193-29601-3-git-send-email-madcoder@debian.org>
Also minor consistency tweaks in how errors are caught.
Signed-off-by: Pierre Habouzit <madcoder@debian.org>
---
git-clean.sh | 38 ++++++++++++++++++++------------------
1 files changed, 20 insertions(+), 18 deletions(-)
diff --git a/git-clean.sh b/git-clean.sh
index 4491738..6959433 100755
--- a/git-clean.sh
+++ b/git-clean.sh
@@ -3,16 +3,21 @@
# Copyright (c) 2005-2006 Pavel Roskin
#
-USAGE="[-d] [-f] [-n] [-q] [-x | -X] [--] <paths>..."
-LONG_USAGE='Clean untracked files from the working directory
- -d remove directories as well
- -f override clean.requireForce and clean anyway
- -n don'\''t remove anything, just show what would be done
- -q be quiet, only report errors
- -x remove ignored files as well
- -X remove only ignored files
+OPTIONS_SPEC="\
+git-clean [options] <paths>...
+
+Clean untracked files from the working directory
+
When optional <paths>... arguments are given, the paths
-affected are further limited to those that match them.'
+affected are further limited to those that match them.
+--
+d remove directories as well
+f override clean.requireForce and clean anyway
+n don't remove anything, just show what would be done
+q be quiet, only report errors
+x remove ignored files as well
+X remove only ignored files"
+
SUBDIRECTORY_OK=Yes
. git-sh-setup
require_work_tree
@@ -55,23 +60,20 @@ do
shift
break
;;
- -*)
- usage
- ;;
*)
- break
+ usage # should not happen
+ ;;
esac
shift
done
if [ "$disabled" = true ]; then
- echo "clean.requireForce set and -n or -f not given; refusing to clean"
- exit 1
+ die "clean.requireForce set and -n or -f not given; refusing to clean"
fi
-case "$ignored,$ignoredonly" in
- 1,1) usage;;
-esac
+if [ "$ignored,$ignoredonly" = "1,1" ]; then
+ die "-x and -X cannot be set together"
+fi
if [ -z "$ignored" ]; then
excl="--exclude-per-directory=.gitignore"
--
1.5.3.5.1460.gdb47
^ permalink raw reply related
* [PATCH 4/5] Migrate git-clone to use git-rev-parse --parseopt
From: Pierre Habouzit @ 2007-11-02 22:39 UTC (permalink / raw)
To: gitster, torvalds, Junio C Hamano; +Cc: git, Pierre Habouzit
In-Reply-To: <1194043193-29601-4-git-send-email-madcoder@debian.org>
Signed-off-by: Pierre Habouzit <madcoder@debian.org>
---
git-clone.sh | 102 +++++++++++++++++++++++++++++++++-------------------------
1 files changed, 58 insertions(+), 44 deletions(-)
diff --git a/git-clone.sh b/git-clone.sh
index 0ea3c24..8680a7c 100755
--- a/git-clone.sh
+++ b/git-clone.sh
@@ -8,15 +8,36 @@
# See git-sh-setup why.
unset CDPATH
+OPTIONS_SPEC="\
+git-clone [options] <repo> [<dir>]
+--
+n,no-checkout don't create a checkout
+bare create a bare repository
+naked create a bare repository
+l,local to clone from a local repository
+no-hardlinks don't use local hardlinks, always copy
+s,shared setup as a shared repository
+template= path to the template directory
+q,quiet be quiet
+reference= reference repository
+o,origin= use <name> instead of 'origin' to track upstream
+u,upload-pack= path to git-upload-pack on the remote
+depth= create a shallow clone of that depth
+
+use-separate-remote compatibility, do not use
+no-separate-remote compatibility, do not use"
+
die() {
echo >&2 "$@"
exit 1
}
usage() {
- die "Usage: $0 [--template=<template_directory>] [--reference <reference-repo>] [--bare] [-l [-s]] [-q] [-u <upload-pack>] [--origin <name>] [--depth <n>] [-n] <repo> [<dir>]"
+ exec "$0" -h
}
+eval `echo "$OPTIONS_SPEC" | git rev-parse --parseopt $PARSEOPT_OPTS -- "$@" || echo exit $?`
+
get_repo_base() {
(
cd "`/bin/pwd`" &&
@@ -106,64 +127,57 @@ depth=
no_progress=
local_explicitly_asked_for=
test -t 1 || no_progress=--no-progress
-while
- case "$#,$1" in
- 0,*) break ;;
- *,-n|*,--no|*,--no-|*,--no-c|*,--no-ch|*,--no-che|*,--no-chec|\
- *,--no-check|*,--no-checko|*,--no-checkou|*,--no-checkout)
- no_checkout=yes ;;
- *,--na|*,--nak|*,--nake|*,--naked|\
- *,-b|*,--b|*,--ba|*,--bar|*,--bare) bare=yes ;;
- *,-l|*,--l|*,--lo|*,--loc|*,--loca|*,--local)
- local_explicitly_asked_for=yes
- use_local_hardlink=yes ;;
- *,--no-h|*,--no-ha|*,--no-har|*,--no-hard|*,--no-hardl|\
- *,--no-hardli|*,--no-hardlin|*,--no-hardlink|*,--no-hardlinks)
- use_local_hardlink=no ;;
- *,-s|*,--s|*,--sh|*,--sha|*,--shar|*,--share|*,--shared)
- local_shared=yes; ;;
- 1,--template) usage ;;
- *,--template)
+
+while test $# != 0
+do
+ case "$1" in
+ -n|--no-checkout)
+ no_checkout=yes ;;
+ --naked|--bare)
+ bare=yes ;;
+ -l|--local)
+ local_explicitly_asked_for=yes
+ use_local_hardlink=yes
+ ;;
+ --no-hardlinks)
+ use_local_hardlink=no ;;
+ -s|--shared)
+ local_shared=yes ;;
+ --template)
shift; template="--template=$1" ;;
- *,--template=*)
- template="$1" ;;
- *,-q|*,--quiet) quiet=-q ;;
- *,--use-separate-remote) ;;
- *,--no-separate-remote)
+ -q|--quiet)
+ quiet=-q ;;
+ --use-separate-remote|--no-separate-remote)
die "clones are always made with separate-remote layout" ;;
- 1,--reference) usage ;;
- *,--reference)
+ --reference)
shift; reference="$1" ;;
- *,--reference=*)
- reference=`expr "z$1" : 'z--reference=\(.*\)'` ;;
- *,-o|*,--or|*,--ori|*,--orig|*,--origi|*,--origin)
- case "$2" in
+ -o,--origin)
+ shift;
+ case "$1" in
'')
usage ;;
*/*)
- die "'$2' is not suitable for an origin name"
+ die "'$1' is not suitable for an origin name"
esac
- git check-ref-format "heads/$2" ||
- die "'$2' is not suitable for a branch name"
+ git check-ref-format "heads/$1" ||
+ die "'$1' is not suitable for a branch name"
test -z "$origin_override" ||
die "Do not give more than one --origin options."
origin_override=yes
- origin="$2"; shift
+ origin="$1"
;;
- 1,-u|1,--upload-pack) usage ;;
- *,-u|*,--upload-pack)
+ -u|--upload-pack)
shift
upload_pack="--upload-pack=$1" ;;
- *,--upload-pack=*)
- upload_pack=--upload-pack=$(expr "z$1" : 'z-[^=]*=\(.*\)') ;;
- 1,--depth) usage;;
- *,--depth)
+ --depth)
+ shift
+ depth="--depth=$1" ;;
+ --)
shift
- depth="--depth=$1";;
- *,-*) usage ;;
- *) break ;;
+ break ;;
+ *)
+ usage ;;
esac
-do
shift
done
--
1.5.3.5.1460.gdb47
^ permalink raw reply related
* [PATCH 1/5] Add a parseopt mode to git-rev-parse to bring parse-options to shell scripts.
From: Pierre Habouzit @ 2007-11-02 22:39 UTC (permalink / raw)
To: gitster, torvalds, Junio C Hamano; +Cc: git, Pierre Habouzit
In-Reply-To: <1194043193-29601-1-git-send-email-madcoder@debian.org>
Signed-off-by: Pierre Habouzit <madcoder@debian.org>
---
Documentation/git-rev-parse.txt | 75 ++++++++++++++++++++++-
builtin-rev-parse.c | 126 +++++++++++++++++++++++++++++++++++++++
2 files changed, 199 insertions(+), 2 deletions(-)
diff --git a/Documentation/git-rev-parse.txt b/Documentation/git-rev-parse.txt
index 4758c33..6811656 100644
--- a/Documentation/git-rev-parse.txt
+++ b/Documentation/git-rev-parse.txt
@@ -23,6 +23,13 @@ distinguish between them.
OPTIONS
-------
+--parseopt::
+ Use `git-rev-parse` in option parsing mode (see PARSEOPT section below).
+
+--keep-dash-dash::
+ Only meaningful in `--parseopt` mode. Tells the option parser to echo
+ out the first `--` met instead of skipping it.
+
--revs-only::
Do not output flags and parameters not meant for
`git-rev-list` command.
@@ -288,10 +295,74 @@ Here are a handful examples:
C^@ I J F
F^! D G H D F
+PARSEOPT
+--------
+
+In `--parseopt` mode, `git-rev-parse` helps massaging options to bring to shell
+scripts the same facilities C builtins have. It works as an option normalizer
+(e.g. splits single switches aggregate values), a bit like `getopt(1)` does.
+
+It takes on the standard input the specification of the options to parse and
+understand, and echoes on the standard ouput a line suitable for `sh(1)` `eval`
+to replace the arguments with normalized ones. In case of error, it ouputs
+usage on the standard error stream, and exits with code 129.
+
+Input Format
+~~~~~~~~~~~~
+
+`git-ref-parse --parseopt` input format is fully text based. It has two parts,
+separated by a line that contains only `--`. The lines before (should be more
+than one) are used for the usage. The lines after describe the options.
+
+Each line of options has this format:
+
+------------
+<opt_spec><arg_spec>? SP+ help LF
+------------
+
+`<opt_spec>`::
+ its format is the short option character, then the long option name
+ separated by a comma. Both parts are not required, though at least one
+ is necessary. `h,help`, `dry-run` and `f` are all three correct
+ `<opt_spec>`.
+
+`<arg_spec>`::
+ an `<arg_spec>` tells the option parser if the option has an argument
+ (`=`), an optionnal one (`?` though its use is discouraged) or none
+ (no `<arg_spec>` in that case).
+
+The rest of the line after as many spaces up to the ending line feed is used
+as the help associated to the option.
+
+Blank lines are ignored, and lines that don't match this specification are used
+as option group headers (start the line with a space to purposely create such
+lines).
+
+Example
+~~~~~~~
+
+------------
+OPTS_SPEC="\
+some-command [options] <args>...
+
+some-command does foo and bar !
+--
+h,help show the help
+
+foo some nifty option --foo
+bar= some cool option --bar with an argument
+
+ An option group Header
+C? option C with an optionnal argument"
+
+eval `echo "$OPTS_SPEC" | git-rev-parse --parseopt -- "$@" || echo exit $?`
+------------
+
+
Author
------
-Written by Linus Torvalds <torvalds@osdl.org> and
-Junio C Hamano <junkio@cox.net>
+Written by Linus Torvalds <torvalds@osdl.org> .
+Junio C Hamano <junkio@cox.net> and Pierre Habouzit <madcoder@debian.org>
Documentation
--------------
diff --git a/builtin-rev-parse.c b/builtin-rev-parse.c
index 8d78b69..054519b 100644
--- a/builtin-rev-parse.c
+++ b/builtin-rev-parse.c
@@ -8,6 +8,7 @@
#include "refs.h"
#include "quote.h"
#include "builtin.h"
+#include "parse-options.h"
#define DO_REVS 1
#define DO_NOREV 2
@@ -209,6 +210,128 @@ static int try_difference(const char *arg)
return 0;
}
+static int parseopt_dump(const struct option *o, const char *arg, int unset)
+{
+ struct strbuf *parsed = o->value;
+ if (unset)
+ strbuf_addf(parsed, " --no-%s", o->long_name);
+ else if (o->short_name)
+ strbuf_addf(parsed, " -%c", o->short_name);
+ else
+ strbuf_addf(parsed, " --%s", o->long_name);
+ if (arg) {
+ strbuf_addch(parsed, ' ');
+ sq_quote_buf(parsed, arg);
+ }
+ return 0;
+}
+
+static const char *skipspaces(const char *s)
+{
+ while (isspace(*s))
+ s++;
+ return s;
+}
+
+static int cmd_parseopt(int argc, const char **argv, const char *prefix)
+{
+ static int keep_dashdash = 0;
+ static char const * const parseopt_usage[] = {
+ "git-rev-parse --parseopt [options] -- [<args>...]",
+ NULL
+ };
+ static struct option parseopt_opts[] = {
+ OPT_BOOLEAN(0, "keep-dashdash", &keep_dashdash,
+ "keep the `--` passed as an arg"),
+ OPT_END(),
+ };
+
+ struct strbuf sb, parsed;
+ const char **usage = NULL;
+ struct option *opts = NULL;
+ int onb = 0, osz = 0, unb = 0, usz = 0;
+
+ strbuf_init(&parsed, 0);
+ strbuf_addstr(&parsed, "set --");
+ argc = parse_options(argc, argv, parseopt_opts, parseopt_usage,
+ PARSE_OPT_KEEP_DASHDASH);
+ if (argc < 1 || strcmp(argv[0], "--"))
+ usage_with_options(parseopt_usage, parseopt_opts);
+
+ strbuf_init(&sb, 0);
+ /* get the usage up to the first line with a -- on it */
+ for (;;) {
+ if (strbuf_getline(&sb, stdin, '\n') == EOF)
+ die("premature end of input");
+ ALLOC_GROW(usage, unb + 1, usz);
+ if (!strcmp("--", sb.buf)) {
+ if (unb < 1)
+ die("no usage string given before the `--' separator");
+ usage[unb] = NULL;
+ break;
+ }
+ usage[unb++] = strbuf_detach(&sb, NULL);
+ }
+
+ /* parse: (<short>|<short>,<long>|<long>)[=?]? SP+ <help> */
+ while (strbuf_getline(&sb, stdin, '\n') != EOF) {
+ const char *s;
+ struct option *o;
+
+ if (!sb.len)
+ continue;
+
+ ALLOC_GROW(opts, onb + 1, osz);
+ memset(opts + onb, 0, sizeof(opts[onb]));
+
+ o = &opts[onb++];
+ s = strchr(sb.buf, ' ');
+ if (!s || *sb.buf == ' ') {
+ o->type = OPTION_GROUP;
+ o->help = xstrdup(skipspaces(s));
+ continue;
+ }
+
+ o->type = OPTION_CALLBACK;
+ o->help = xstrdup(skipspaces(s));
+ o->value = &parsed;
+ o->callback = &parseopt_dump;
+ switch (s[-1]) {
+ case '=':
+ s--;
+ break;
+ case '?':
+ o->flags = PARSE_OPT_OPTARG;
+ s--;
+ break;
+ default:
+ o->flags = PARSE_OPT_NOARG;
+ break;
+ }
+
+ if (s - sb.buf == 1) /* short option only */
+ o->short_name = *sb.buf;
+ else if (sb.buf[1] != ',') /* long option only */
+ o->long_name = xmemdupz(sb.buf, s - sb.buf);
+ else {
+ o->short_name = *sb.buf;
+ o->long_name = xmemdupz(sb.buf + 2, s - sb.buf - 2);
+ }
+ }
+ strbuf_release(&sb);
+
+ /* put an OPT_END() */
+ ALLOC_GROW(opts, onb + 1, osz);
+ memset(opts + onb, 0, sizeof(opts[onb]));
+ argc = parse_options(argc, argv, opts, usage,
+ keep_dashdash ? PARSE_OPT_KEEP_DASHDASH : 0);
+
+ strbuf_addf(&parsed, " --");
+ sq_quote_argv(&parsed, argv, argc, 0);
+ puts(parsed.buf);
+ return 0;
+}
+
int cmd_rev_parse(int argc, const char **argv, const char *prefix)
{
int i, as_is = 0, verify = 0;
@@ -216,6 +339,9 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
git_config(git_default_config);
+ if (argc > 1 && !strcmp("--parseopt", argv[1]))
+ return cmd_parseopt(argc - 1, argv + 1, prefix);
+
for (i = 1; i < argc; i++) {
const char *arg = argv[i];
--
1.5.3.5.1460.gdb47
^ permalink raw reply related
* [PATCH 5/5] Migrate git-am.sh to use git-rev-parse --parseopt
From: Pierre Habouzit @ 2007-11-02 22:39 UTC (permalink / raw)
To: gitster, torvalds, Junio C Hamano; +Cc: git, Pierre Habouzit
In-Reply-To: <1194043193-29601-5-git-send-email-madcoder@debian.org>
Signed-off-by: Pierre Habouzit <madcoder@debian.org>
---
git-am.sh | 97 +++++++++++++++++++++++++++++++-----------------------------
1 files changed, 50 insertions(+), 47 deletions(-)
diff --git a/git-am.sh b/git-am.sh
index 2514d07..e5ed6a7 100755
--- a/git-am.sh
+++ b/git-am.sh
@@ -2,11 +2,25 @@
#
# Copyright (c) 2005, 2006 Junio C Hamano
-USAGE='[--signoff] [--dotest=<dir>] [--keep] [--utf8 | --no-utf8]
- [--3way] [--interactive] [--binary]
- [--whitespace=<option>] [-C<n>] [-p<n>]
- <mbox>|<Maildir>...
- or, when resuming [--skip | --resolved]'
+OPTIONS_SPEC="\
+git-am [options] <mbox>|<Maildir>...
+git-am [options] --resolved
+git-am [options] --skip
+--
+d,dotest= use <dir> and not .dotest
+i,interactive= run interactively
+b,binary pass --allo-binary-replacement to git-apply
+3,3way allow fall back on 3way merging if needed
+s,signoff add a Signed-off-by line to the commit message
+u,utf8 recode into utf8 (default)
+k,keep pass -k flagg to git-mailinfo
+whitespace= pass it through git-apply
+C= pass it through git-apply
+p= pass it through git-apply
+resolvemsg= override error message when patch failure occurs
+r,resolved to be used after a patch failure
+skip skip the current patch"
+
. git-sh-setup
set_reflog_action am
require_work_tree
@@ -110,49 +124,38 @@ git_apply_opt=
while test $# != 0
do
case "$1" in
- -d=*|--d=*|--do=*|--dot=*|--dote=*|--dotes=*|--dotest=*)
- dotest=`expr "z$1" : 'z-[^=]*=\(.*\)'`; shift ;;
- -d|--d|--do|--dot|--dote|--dotes|--dotest)
- case "$#" in 1) usage ;; esac; shift
- dotest="$1"; shift;;
-
- -i|--i|--in|--int|--inte|--inter|--intera|--interac|--interact|\
- --interacti|--interactiv|--interactive)
- interactive=t; shift ;;
-
- -b|--b|--bi|--bin|--bina|--binar|--binary)
- binary=t; shift ;;
-
- -3|--3|--3w|--3wa|--3way)
- threeway=t; shift ;;
- -s|--s|--si|--sig|--sign|--signo|--signof|--signoff)
- sign=t; shift ;;
- -u|--u|--ut|--utf|--utf8)
- utf8=t; shift ;; # this is now default
- --no-u|--no-ut|--no-utf|--no-utf8)
- utf8=; shift ;;
- -k|--k|--ke|--kee|--keep)
- keep=t; shift ;;
-
- -r|--r|--re|--res|--reso|--resol|--resolv|--resolve|--resolved)
- resolved=t; shift ;;
-
- --sk|--ski|--skip)
- skip=t; shift ;;
-
- --whitespace=*|-C*|-p*)
- git_apply_opt="$git_apply_opt $1"; shift ;;
-
- --resolvemsg=*)
- resolvemsg=${1#--resolvemsg=}; shift ;;
-
- --)
- shift; break ;;
- -*)
- usage ;;
- *)
- break ;;
+ -i|--interactive)
+ interactive=t ;;
+ -b|--binary)
+ binary=t ;;
+ -3|--3way)
+ threeway=t ;;
+ -s--signoff)
+ sign=t ;;
+ -u|--utf8)
+ utf8=t ;; # this is now default
+ --no-utf8)
+ utf8= ;;
+ -k|--keep)
+ keep=t ;;
+ -r|--resolved)
+ resolved=t ;;
+ --skip)
+ skip=t ;;
+ -d|--dotest)
+ shift; dotest=$1;;
+ --resolvemsg)
+ shift; resolvemsg=$1 ;;
+ --whitespace)
+ git_apply_opt="$git_apply_opt $1=$2"; shift ;;
+ -C|-p)
+ git_apply_opt="$git_apply_opt $1$2"; shift ;;
+ --)
+ shift; break ;;
+ *)
+ usage ;;
esac
+ shift
done
# If the dotest directory exists, but we have finished applying all the
--
1.5.3.5.1460.gdb47
^ permalink raw reply related
* let's retry this based on git-rev-parse --parseopt
From: Pierre Habouzit @ 2007-11-02 22:39 UTC (permalink / raw)
To: gitster, torvalds; +Cc: git
So as it seems git-rev-parse is the place to do that, here is a new
proposal, with a few more commands migrated. Of course it doesn't means
we should not rewrite some (if not all) of the shell scripts as
builtins, but it will take some pain from the user, and provide nice
option parsers from day 1 for new porcelains.
I believe that the git-am.sh migration is a perfect example of why this
option parser helps.
Note that in the patch 1, the documentation _needs_ to be reviewed by a
native speaker.
^ permalink raw reply
* Re: Git-windows and git-svn?
From: Pascal Obry @ 2007-11-02 23:00 UTC (permalink / raw)
To: Abdelrazak Younes; +Cc: git
In-Reply-To: <fgg6cd$3ep$1@ger.gmane.org>
Abdelrazak,
> I would like to try git on Windows together with git-svn, I downloaded
> Git-1.5.3-preview20071027.exe and tried:
The best Git port on Windows is the Cygwin one. I'm using git-svn
without trouble.
Pascal.
--
--|------------------------------------------------------
--| Pascal Obry Team-Ada Member
--| 45, rue Gabriel Peri - 78114 Magny Les Hameaux FRANCE
--|------------------------------------------------------
--| http://www.obry.net
--| "The best way to travel is by means of imagination"
--|
--| gpg --keyserver wwwkeys.pgp.net --recv-key C1082595
^ permalink raw reply
* [PATCH 1/3] gitweb: Add tests for overriding gitweb config with repo config
From: Jakub Narebski @ 2007-11-02 23:41 UTC (permalink / raw)
To: git; +Cc: Jakub Narebski
In-Reply-To: <1194046880-29941-1-git-send-email-jnareb@gmail.com>
Make blame view and snapshot support overridable by repository
config. Test tree view with both features disabled, and with both
features enabled.
Test with features enabled also tests multiple formats snapshot
support (in tree view).
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
---
If I remember correctly it was when creating this test that there were
probles with CGI::Carp::set_programname() in t9500 test. And it took
me some time to discover where the bug was.
t/t9500-gitweb-standalone-no-errors.sh | 23 +++++++++++++++++++++++
1 files changed, 23 insertions(+), 0 deletions(-)
diff --git a/t/t9500-gitweb-standalone-no-errors.sh b/t/t9500-gitweb-standalone-no-errors.sh
index 1bf0988..35fff3d 100755
--- a/t/t9500-gitweb-standalone-no-errors.sh
+++ b/t/t9500-gitweb-standalone-no-errors.sh
@@ -557,4 +557,27 @@ test_expect_success \
'gitweb_run "p=.git;a=tree;opt=--no-merges"'
test_debug 'cat gitweb.log'
+# ----------------------------------------------------------------------
+# gitweb config and repo config
+
+cat >>gitweb_config.perl <<EOF
+
+\$feature{'blame'}{'override'} = 1;
+\$feature{'snapshot'}{'override'} = 1;
+EOF
+
+test_expect_success \
+ 'config override: tree view, features disabled in repo config' \
+ 'git config gitweb.blame no &&
+ git config gitweb.snapshot none &&
+ gitweb_run "p=.git;a=tree"'
+test_debug 'cat gitweb.log'
+
+test_expect_success \
+ 'config override: tree view, features enabled in repo config' \
+ 'git config gitweb.blame yes &&
+ git config gitweb.snapshot "zip,tgz, tbz2" &&
+ gitweb_run "p=.git;a=tree"'
+test_debug 'cat gitweb.log'
+
test_done
--
1.5.3.5
^ permalink raw reply related
* [PATCH 3/3] gitweb: Use config file for repository description and URLs
From: Jakub Narebski @ 2007-11-02 23:41 UTC (permalink / raw)
To: git; +Cc: Jakub Narebski
In-Reply-To: <1194046880-29941-1-git-send-email-jnareb@gmail.com>
Allow to use configuration variable gitweb.description for repository
description if there is no $GIT_DIR/description file, and multivalued
configuration variable gitweb.url for URLs of a project (to clone or
fetch from) if there is no $GIT_DIR/cloneurl file.
While repository description is shown in the projects list page, so it
is better to use file and not config variable for performance, it is I
think better to use gitweb.url for URLs (as it is shown only on
project summary page).
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
---
gitweb/gitweb.perl | 10 ++++++++--
1 files changed, 8 insertions(+), 2 deletions(-)
diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl
index f54455b..7cac629 100755
--- a/gitweb/gitweb.perl
+++ b/gitweb/gitweb.perl
@@ -1606,7 +1606,9 @@ sub git_get_path_by_hash {
sub git_get_project_description {
my $path = shift;
- open my $fd, "$projectroot/$path/description" or return undef;
+ $git_dir = "$projectroot/$path";
+ open my $fd, "$projectroot/$path/description"
+ or return git_get_project_config('description');
my $descr = <$fd>;
close $fd;
if (defined $descr) {
@@ -1618,7 +1620,11 @@ sub git_get_project_description {
sub git_get_project_url_list {
my $path = shift;
- open my $fd, "$projectroot/$path/cloneurl" or return;
+ $git_dir = "$projectroot/$path";
+ open my $fd, "$projectroot/$path/cloneurl"
+ or return wantarray ?
+ @{ config_to_multi(git_get_project_config('url')) } :
+ config_to_multi(git_get_project_config('url'));
my @git_project_url_list = map { chomp; $_ } <$fd>;
close $fd;
--
1.5.3.5
^ permalink raw reply related
* [PATCH 2/3] gitweb: Read repo config using 'git config -z -l'
From: Jakub Narebski @ 2007-11-02 23:41 UTC (permalink / raw)
To: git; +Cc: Jakub Narebski
In-Reply-To: <1194046880-29941-1-git-send-email-jnareb@gmail.com>
Change git_get_project_config to run git-config only once per
repository, without changing its signature (its calling convention).
This means for example that it returns 'true' or 'false' when called
with second argument '--bool', and not true or false value.
Instead of calling 'git config [<type>] --get gitweb.<key>' once for
each config variable, call 'git config -z -l' only once, parsing and
saving its output to %config variable. This makes possible to add new
per repository configuration without paying cost of forking once per
variable checked. We can now allow repository description and
repository URLs to be stored in config file without badly affecting
gitweb performance.
For now only configuration variables for 'gitweb' section are stored.
Multiple values for single configuration variable are stored as
anonymous array reference; configuration variable with no value is
stored as undef.
Converting configuration variable values to boolean or integer value
are done in Perl. Results differ from git-config in the fact that no
conversion error is ever raised. For boolean values no value, 'true'
(any case) and 'false' (any case) are considered true, numbers are
true if not zero; all other values (even invalid for bool) are
considered false. For integer values value suffix of 'k', 'm', or 'g'
following decimal number will cause the value to be multiplied by
1024, 1048576, or 1073741824; other values are returned as-is, only
whitespace stripped.
Signed-off-by: Jakub Narebski <jnareb@gmail.com>
---
This makes use of commit 2275d502114c71045af991697048191fed88aac4
"config: Add --null/-z option for null-delimted output"
by Frank Lichtenheld. The --null/-z option to git-config was created
among others with gitweb in mind, if I remember correctly.
In the future we would most probably want to move this to Git.pm, and
use Git.pm in gitweb.
gitweb/gitweb.perl | 115 ++++++++++++++++++++++++++++++++++++++++++++++++---
1 files changed, 108 insertions(+), 7 deletions(-)
diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl
index 827f977..f54455b 100755
--- a/gitweb/gitweb.perl
+++ b/gitweb/gitweb.perl
@@ -1432,20 +1432,121 @@ sub git_get_type {
return $type;
}
+# repository configuration
+our $config_file = '';
+our %config;
+
+# store multiple values for single key as anonymous array reference
+# single values stored directly in the hash, not as [ <value> ]
+sub hash_set_multi {
+ my ($hash, $key, $value) = @_;
+
+ if (!exists $hash->{$key}) {
+ $hash->{$key} = $value;
+ } elsif (!ref $hash->{$key}) {
+ $hash->{$key} = [ $hash->{$key}, $value ];
+ } else {
+ push @{$hash->{$key}}, $value;
+ }
+}
+
+# return hash of git project configuration
+# optionally limited to some section, e.g. 'gitweb'
+sub git_parse_project_config {
+ my $section_regexp = shift;
+ my %config;
+
+ local $/ = "\0";
+
+ open my $fh, "-|", git_cmd(), "config", '-z', '-l',
+ or return;
+
+ while (my $keyval = <$fh>) {
+ chomp $keyval;
+ my ($key, $value) = split(/\n/, $keyval, 2);
+
+ hash_set_multi(\%config, $key, $value)
+ if (!defined $section_regexp || $key =~ /^(?:$section_regexp)\./o);
+ }
+ close $fh;
+
+ return %config;
+}
+
+# convert config value to boolean, 'true' or 'false'
+# no value, number > 0, 'true' and 'yes' values are true
+# rest of values are treated as false (never as error)
+sub config_to_bool {
+ my $val = shift;
+
+ # strip leading and trailing whitespace
+ $val =~ s/^\s+//;
+ $val =~ s/\s+$//;
+
+ return (!defined $val || # section.key
+ ($val =~ /^\d+$/ && $val) || # section.key = 1
+ ($val =~ /^(?:true|yes)$/i)); # section.key = true
+}
+
+# convert config value to simple decimal number
+# an optional value suffix of 'k', 'm', or 'g' will cause the value
+# to be multiplied by 1024, 1048576, or 1073741824
+sub config_to_int {
+ my $val = shift;
+
+ # strip leading and trailing whitespace
+ $val =~ s/^\s+//;
+ $val =~ s/\s+$//;
+
+ if (my ($num, $unit) = ($val =~ /^([0-9]*)([kmg])$/i)) {
+ $unit = lc($unit);
+ # unknown unit is treated as 1
+ return $num * ($unit eq 'g' ? 1073741824 :
+ $unit eq 'm' ? 1048576 :
+ $unit eq 'k' ? 1024 : 1);
+ }
+ return $val;
+}
+
+# convert config value to array reference, if needed
+sub config_to_multi {
+ my $val = shift;
+
+ return ref($val) ? $val : [ $val ];
+}
+
sub git_get_project_config {
my ($key, $type) = @_;
+ # key sanity check
return unless ($key);
$key =~ s/^gitweb\.//;
return if ($key =~ m/\W/);
- my @x = (git_cmd(), 'config');
- if (defined $type) { push @x, $type; }
- push @x, "--get";
- push @x, "gitweb.$key";
- my $val = qx(@x);
- chomp $val;
- return ($val);
+ # type sanity check
+ if (defined $type) {
+ $type =~ s/^--//;
+ $type = undef
+ unless ($type eq 'bool' || $type eq 'int');
+ }
+
+ # get config
+ if (!defined $config_file ||
+ $config_file ne "$git_dir/config") {
+ %config = git_parse_project_config('gitweb');
+ $config_file = "$git_dir/config";
+ }
+
+ # ensure given type
+ if (!defined $type) {
+ return $config{"gitweb.$key"};
+ } elsif ($type eq 'bool') {
+ # backward compatibility: 'git config --bool' returns true/false
+ return config_to_bool($config{"gitweb.$key"}) ? 'true' : 'false';
+ } elsif ($type eq 'int') {
+ return config_to_int($config{"gitweb.$key"});
+ }
+ return $config{"gitweb.$key"};
}
# get hash of given path at given ref
--
1.5.3.5
^ permalink raw reply related
* [PATCH 0/3] gitweb: Improve reading of repo config
From: Jakub Narebski @ 2007-11-02 23:41 UTC (permalink / raw)
To: git; +Cc: Jakub Narebski
This series of patches introduces single-call reading of
gitweb-related part of repository configuration in gitweb. Instead of
calling git-config once for each config variable we check, read all
variables at once for first request of repo config variable.
First patch adds test to check if our changes do not break gitweb too
badly, second one introduces mentioned above "eager" repo config
reading, and third makes use of the fact that adding new configuration
variables to check is not that costly now.
Table of contents:
==================
[PATCH 1/3] gitweb: Add tests for overriding gitweb config with repo config
[PATCH 2/3] gitweb: Read repo config using 'git config -z -l'
[PATCH 3/3] gitweb: Use config file for repository description and URLs
Diffstat:
=========
gitweb/gitweb.perl | 82 +++++++++++++++++++++----------------------------
1 files changed, 33 insertions(+), 47 deletions(-)
--
Jakub Narebski, Poland
git version 1.5.3.5
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox