* Re: git-svn and renames
From: Eric Wong @ 2007-07-11 8:20 UTC (permalink / raw)
To: Rogan Dawes; +Cc: Git Mailing List
In-Reply-To: <46938594.2010607@dawes.za.net>
Rogan Dawes <lists@dawes.za.net> wrote:
> Hi folks,
>
> I am trying to push my local changes to an imported SVN project back to
> the SVN repo. For anyone who cares, this is the WebGoat repository which
> you can find at http://dawes.za.net/rogan/webgoat/webgoat.git/
>
> I am trying to push it back to the primary GoogleCode repo. I have
> successfully managed to push 20 or so commits, but I am now running up
> against a problem with a renamed/moved file.
>
> I moved a file from a directory to a subdirectory, and made minimal
> changes to this file so that it remained a valid Java class. i.e. I
> changed the package, and a few other minor things. As can be seen at
> <http://dawes.za.net/gitweb.cgi?p=rogan/webgoat/webgoat.git;a=commitdiff;h=486416188a3e49d60e1510166ac197e5e66cc4d2>,
> git detects the rename with 93% similarity.
>
> However, when I try to push this change to the Google repo, git-svn dies
> with the following error:
>
> $ git svn dcommit
> RA layer request failed: PROPFIND request failed on '/svn/trunk/
> webgoat/main/project/JavaSource/org/owasp/webgoat/lessons/DefaultLessonAction.java':
> PROPFIND of '/svn/trunk/
> webgoat/main/project/JavaSource/org/owasp/webgoat/lessons/DefaultLessonAction.java':
> 400 Bad Request (https://webgoat.googlecode.com) at
> /home/rdawes/bin/git-svn line 400
>
> [Yes, those paths have a space in them, however this does not seem to
> have prevented me from committing the previous 20 or so changes.]
>
> I noted the following in the git-svn documentation, with regards to
> handling renames. However, I am not renaming a directory, only a couple
> of files.
I've personally noted a rename issue with committing funky characters
"#{}" in filenames (I was renaming to get rid of those funky characters of
course). Haven't had proper time to look into it.
Did any previous successful commits have renames in them? You may want
to set similarity to 100% to disable rename detection.
--
Eric Wong
^ permalink raw reply
* Re: [PATCH] Work around a bad interaction between Tcl and cmd.exe with "^{tree}"
From: Shawn O. Pearce @ 2007-07-11 8:03 UTC (permalink / raw)
To: Johannes Sixt; +Cc: git
In-Reply-To: <4693AF6C.99DB933@eudaptics.com>
Johannes Sixt <J.Sixt@eudaptics.com> wrote:
> It seems that MSYS's wish does some quoting for Bourne shells, in
> particular, escape the first '{' of the "^{tree}" suffix, but then it uses
> cmd.exe to run "git rev-parse". However, cmd.exe does not remove the
> backslash, so that the resulting rev expression ends up in git's guts
> as unrecognizable garbage: rev-parse fails, and git-gui hickups in a way
> that it must be restarted.
>
> Fortunately, recent versions of git can refer to the root tree object using
> the notation "$commit:", which avoids the problematic case.
>
> Signed-off-by: Johannes Sixt <johannes.sixt@telecom.at>
> ---
> This is a resend with a slightly improved commit message.
> The first version didn't get through for some reason anyway, it seems.
I did get your patch yesterday. I just didn't finish my replacement
version. Got busy with other things.
I have seen this { issue before. And not just on MSYS. It also
borked on Cygwin. This is why git-gui formats the geometry and
font data the way it does in the .git/config file; by default it
wanted to use {} around strings with spaces in them and this got
all messed up going through the shell. So we s/[{}]/"/g before we
call git-config. Yea, it sucks.
Rather than relying on rev-parse to understand the : syntax here
I'm just going to parse the commit object and yank the first line
out of it. We already do that for an amend to refetch the message
buffer. Either way it is a fork. And its roughly the same amount
of CPU time for both git-gui and C git. :-|
> diff --git a/lib/commit.tcl b/lib/commit.tcl
> index dc7c88c..43a5aca 100644
> --- a/lib/commit.tcl
> +++ b/lib/commit.tcl
> @@ -258,7 +258,7 @@ proc commit_committree {fd_wt curHEAD msg} {
> # -- Verify this wasn't an empty change.
> #
> if {$commit_type eq {normal}} {
> - set old_tree [git rev-parse "$PARENT^{tree}"]
> + set old_tree [git rev-parse "$PARENT:"]
> if {$tree_id eq $old_tree} {
> info_popup {No changes to commit.
--
Shawn.
^ permalink raw reply
* Re: [PATCH] Support wholesale directory renames in fast-import
From: Shawn O. Pearce @ 2007-07-11 7:57 UTC (permalink / raw)
To: David Frech; +Cc: Uwe Kleine-König, git
In-Reply-To: <7154c5c60707101255k7fcd207fg62f1c59518ba5039@mail.gmail.com>
David Frech <david@nimblemachines.com> wrote:
> Hmm. I think Uwe is right. Copy is probably the "right" primitive, and
> rename can always be synthesized from copy+delete.
>
> Since Subversion is built around the idea of "cheap copies" there is
> no incentive for them to represent renames other than as "copy, then
> delete".
>
> But isn't the same true in a way of git? If I copy a directory (a
> tree), then the new tree is the same tree - it has the same SHA-1
> hash, so I can simply refer to the existing object. Same for file
> blobs.
>
> Subversion dump files have *lots* of copies. Might be nice to be able
> to feed these directly into fast-import and have it DTRT, esp if it
> was smart about sharing identical data structures.
Yes. All of that is true. ;-)
I'm tired. I just worked an 18 hour day. I need to go do it all
over again in about 4 hours. So I'm going to head off to bed. But
I did manage to implement this (I think). Its totally untested.
But feel free to poke at it:
git://repo.or.cz/git/fastimport.git copy-wip
I'll write documentation and unit tests tomorrow. And fix any bugs,
if any get identified.
The implementation should copy as little memory as possible to do the
actual copy. This should make a C/D pair about as efficient as an
R command if the directory being copied has not yet been modified
as part of the current commit (this is probably typical for an
SVN dump file). The only difference should be a slight increase
in running time for the C/D pair, as directory entry lookup in
fast-import is O(n).
Oh, and as always, C works with both files and directories...
Hmm. Quickly reading this diff I can actually do it shorter with
a bit of refactoring. I'll clean that up tomorrow night. I blame
it on the lack of sleep that I'm suffering from right now. ;-)
-->8--
WIP Teach fast import how to copy
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
---
fast-import.c | 121 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 120 insertions(+), 1 deletions(-)
diff --git a/fast-import.c b/fast-import.c
index a1cb13f..41c0352 100644
--- a/fast-import.c
+++ b/fast-import.c
@@ -26,10 +26,16 @@ Format of STDIN stream:
lf;
commit_msg ::= data;
- file_change ::= file_clr | file_del | file_rnm | file_obm | file_inm;
+ file_change ::= file_clr
+ | file_del
+ | file_rnm
+ | file_cpy
+ | file_obm
+ | file_inm;
file_clr ::= 'deleteall' lf;
file_del ::= 'D' sp path_str lf;
file_rnm ::= 'R' sp path_str sp path_str lf;
+ file_cpy ::= 'C' sp path_str sp path_str lf;
file_obm ::= 'M' sp mode sp (hexsha1 | idnum) sp path_str lf;
file_inm ::= 'M' sp mode sp 'inline' sp path_str lf
data;
@@ -623,6 +629,33 @@ static void release_tree_entry(struct tree_entry *e)
avail_tree_entry = e;
}
+static struct tree_content *dup_tree_content(struct tree_content *s)
+{
+ struct tree_content *d;
+ struct tree_entry *a, *b;
+ unsigned int i, j;
+
+ if (!s)
+ return NULL;
+ d = new_tree_content(s->entry_count);
+ for (i = 0, j = 0; i < s->entry_count; i++) {
+ a = s->entries[i];
+ if (a->versions[1].mode) {
+ b = new_tree_entry();
+ memcpy(b, a, sizeof(*a));
+ if (is_null_sha1(b->versions[1].sha1))
+ b->tree = dup_tree_content(b->tree);
+ else
+ b->tree = NULL;
+ d->entries[j++] = a;
+ }
+ }
+ d->entry_count = j;
+ d->delta_depth = s->delta_depth;
+
+ return d;
+}
+
static void start_packfile(void)
{
static char tmpfile[PATH_MAX];
@@ -1273,6 +1306,43 @@ del_entry:
return 1;
}
+static int tree_content_get(
+ struct tree_entry *root,
+ const char *p,
+ struct tree_entry *leaf)
+{
+ struct tree_content *t = root->tree;
+ const char *slash1;
+ unsigned int i, n;
+ struct tree_entry *e;
+
+ slash1 = strchr(p, '/');
+ if (slash1)
+ n = slash1 - p;
+ else
+ n = strlen(p);
+
+ for (i = 0; i < t->entry_count; i++) {
+ e = t->entries[i];
+ if (e->name->str_len == n && !strncmp(p, e->name->str_dat, n)) {
+ if (!slash1) {
+ memcpy(leaf, e, sizeof(*leaf));
+ if (is_null_sha1(e->versions[1].sha1))
+ leaf->tree = dup_tree_content(leaf->tree);
+ else
+ leaf->tree = NULL;
+ return 1;
+ }
+ if (!S_ISDIR(e->versions[1].mode))
+ return 0;
+ if (!e->tree)
+ load_tree(e);
+ return tree_content_get(e, slash1 + 1, leaf);
+ }
+ }
+ return 0;
+}
+
static int update_branch(struct branch *b)
{
static const char *msg = "fast-import";
@@ -1706,6 +1776,53 @@ static void file_change_r(struct branch *b)
free(d_uq);
}
+static void file_change_c(struct branch *b)
+{
+ const char *s, *d;
+ char *s_uq, *d_uq;
+ const char *endp;
+ struct tree_entry leaf;
+
+ s = command_buf.buf + 2;
+ s_uq = unquote_c_style(s, &endp);
+ if (s_uq) {
+ if (*endp != ' ')
+ die("Missing space after source: %s", command_buf.buf);
+ }
+ else {
+ endp = strchr(s, ' ');
+ if (!endp)
+ die("Missing space after source: %s", command_buf.buf);
+ s_uq = xmalloc(endp - s + 1);
+ memcpy(s_uq, s, endp - s);
+ s_uq[endp - s] = 0;
+ }
+ s = s_uq;
+
+ endp++;
+ if (!*endp)
+ die("Missing dest: %s", command_buf.buf);
+
+ d = endp;
+ d_uq = unquote_c_style(d, &endp);
+ if (d_uq) {
+ if (*endp)
+ die("Garbage after dest in: %s", command_buf.buf);
+ d = d_uq;
+ }
+
+ memset(&leaf, 0, sizeof(leaf));
+ if (!tree_content_get(&b->branch_tree, s, &leaf))
+ die("Path %s not in branch", s);
+ tree_content_set(&b->branch_tree, d,
+ leaf.versions[1].sha1,
+ leaf.versions[1].mode,
+ leaf.tree);
+
+ free(s_uq);
+ free(d_uq);
+}
+
static void file_change_deleteall(struct branch *b)
{
release_tree_content_recursive(b->branch_tree.tree);
@@ -1875,6 +1992,8 @@ static void cmd_new_commit(void)
file_change_d(b);
else if (!prefixcmp(command_buf.buf, "R "))
file_change_r(b);
+ else if (!prefixcmp(command_buf.buf, "C "))
+ file_change_c(b);
else if (!strcmp("deleteall", command_buf.buf))
file_change_deleteall(b);
else
--
1.5.3.rc0.879.g64b8
--
Shawn.
^ permalink raw reply related
* Re: git-filter-branch exits early
From: Sven Verdoolaege @ 2007-07-11 7:55 UTC (permalink / raw)
To: Johannes Schindelin; +Cc: Alex Riesen, git
In-Reply-To: <Pine.LNX.4.64.0707102222430.4047@racer.site>
On Tue, Jul 10, 2007 at 10:57:44PM +0100, Johannes Schindelin wrote:
> Anyway, "set -e" was one thing I wanted to fix. But I'm not sure I want
> to work on filter-branch now, what with skimo (possibly? hopefully?)
> working on my wishlist for rewrite-commits.
I'm working on it, but only evenings (and weekends).
skimo
^ permalink raw reply
* Re: [PATCH] [RFC] send-email: honor --suppress-from --signed-off-cc
From: Uwe Kleine-König @ 2007-07-11 7:55 UTC (permalink / raw)
To: git
In-Reply-To: <11840869671745-git-send-email-ukleinek@informatik.uni-freiburg.de>
Hello,
please forget that second patch, it was sent with a dirty send-email and
even that was wrong. The first patch however is IMHO a good one.
I will look again into my issues with send-email probably next week.
Best regards
Uwe
--
Uwe Kleine-König
http://www.google.com/search?q=5%2B7
^ permalink raw reply
* Re: --ignore-invalid flag to git log et al.?
From: Alex Riesen @ 2007-07-11 7:46 UTC (permalink / raw)
To: Paul Mackerras; +Cc: Junio C Hamano, git
In-Reply-To: <18068.34542.502048.222112@cargo.ozlabs.ibm.com>
On 7/11/07, Paul Mackerras <paulus@samba.org> wrote:
> An alternative would be to have some way to validate refs. I don't
> know how to do that efficiently. I think I would not want to have to
> do a fork/exec for every ref that I wanted to check.
git rev-parse --revs-only ref1 ref2 ref3 ...?
^ permalink raw reply
* --ignore-invalid flag to git log et al.?
From: Paul Mackerras @ 2007-07-11 7:29 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
Junio,
What would you think about a --ignore-invalid flag for things like git
rev-list and git log, to tell it to ignore any refs on the command
line that are not valid objects?
Currently there is a buglet in gitk where if a user puts some sort of
ref on the command line, and then makes the ref invalid (e.g. by
deleting the ref if it is a head or tag, or doing a git prune if it is
a sha1 ID with no head/tag pointing to it), and then does "Update" in
gitk, it will get an error because of the now-invalid ref. (Yes, this
is a bit of a corner case, but I have had a user point out this
behaviour to me.) With a --ignore-invalid flag, gitk could use this
when doing "Update" to avoid the error.
An alternative would be to have some way to validate refs. I don't
know how to do that efficiently. I think I would not want to have to
do a fork/exec for every ref that I wanted to check.
Thoughts?
Paul.
^ permalink raw reply
* git-cvsimport newbie question
From: Scott Lamb @ 2007-07-11 7:20 UTC (permalink / raw)
To: git
I'm trying to automatically maintain a git mirror of a (very) remote CVS
repository which is suitable for a few people to clone. I'm creating and
updating it now by running this periodically:
$ mkdir ~/git/racoon2.git; cd ~/git/racoon2.git && git-cvsimport -d
:pserver:anoncvs@anoncvs.racoon2.wide.ad.jp:/anoncvs/racoon2 -r wide -i
racoon2
and cloning/pulling it in the simplest possible way:
$ git clone racoon2.git myracoon2
$ cd myracoon2
$ stg init
...work work work...
$ stg pull
But my clones don't see all the upstream branches:
$ git remote show origin
* remote origin
URL: /home/slamb/git/racoon2.git/.git
Remote branch(es) merged with 'git pull' while on branch master
master
Tracked remote branches
master
In fact, the only branch I see is the one which isn't even updated,
which confused into thinking upstream wasn't changing. (I can't say the
manpage didn't warn me, though - "By default initial import will create
and populate a "master" branch from the CVS repository's main branch
which you're free to work with; after that, you need to git merge
incremental imports, or any CVS branches, yourself.")
Okay, it seems like what I actually want is this:
$ git-cvsimport -d $CVSROOT -o master -i racoon2
which essentially creates a repository that is a mirror of upstream
rather than one which pretends to be tracking a nonexistent upstream git
repository. Now on the cloned branches "git branch -r" does what I want,
as does a simple "git pull".
But from the manpage, it appears I'm reverting to a much older way of
doing things. Maybe I should be giving the newer way a shot? Was this
"-r" way meant to be used with cloning the mirrored repository? If so,
what's the workflow there? maybe I should reset racoon2.git's "master"
branch to the beginning of time (to avoid confusion), update head to
point to remotes/wide/master (so simple "git clone" and "git pull"
commands get CVS HEAD), and then update remote.origin.fetch on each
cloned repository to pull in other branches as needed? But even after
doing that, "git remote show origin" on a cloned repository still won't
give me the list of branches I want. So this seems doesn't seem as good
as the old way.
Is there any way to make a repository cloned from a new-style
cvsimported one show the list of branches? It looks like I can't have a
remote in one repository refer to a remote in another repository - it
wants a direct reference. Most things seem to ignore origin's remotes,
at least unless I explicitly name one like "git pull origin
refs/remotes/wide/master".
Best regards,
Scott
--
Scott Lamb <http://www.slamb.org/>
^ permalink raw reply
* Re: git-filter-branch exits early
From: Alex Riesen @ 2007-07-11 6:02 UTC (permalink / raw)
To: Johannes Schindelin; +Cc: git, Sven Verdoolaege
In-Reply-To: <Pine.LNX.4.64.0707102222430.4047@racer.site>
On 7/10/07, Johannes Schindelin <Johannes.Schindelin@gmx.de> wrote:
> On Tue, 10 Jul 2007, Alex Riesen wrote:
>
> > I have a Debian system where git-filter-branch exits immediately after
> > "unset CDPATH" in git-sh-setup (the command exits with 1, as CDPATH is
> > not defined). The system still has bash-2.05a.
> >
> > git-filter-branch has "set -e", which is why the script finishes
> > prematurely. If this is not really needed, maybe it can be removed?
> >
> > I'll see if the system can be upgraded, but I suspect someone can get
> > a similar problem.
>
> I do not really understand why "unset CDPATH" should trigger an error. I
> guess that this is one of the nice braindamages in dash, right?
in bash. Bash-2.05.a
> Anyway, "set -e" was one thing I wanted to fix. ...
BTW, what can break if I just go on and remove it?
> - since it is a C program, it should be more stable, eventually, than a
> shell script, where you have to work around limitations all the time,
right :)
^ permalink raw reply
* Re: test suite fails if sh != bash || tar != GNU tar
From: David Frech @ 2007-07-11 4:08 UTC (permalink / raw)
To: Linus Torvalds; +Cc: Johannes Schindelin, git
In-Reply-To: <alpine.LFD.0.999.0707102020020.3412@woody.linux-foundation.org>
On 7/10/07, Linus Torvalds <torvalds@linux-foundation.org> wrote:
> On Wed, 11 Jul 2007, Johannes Schindelin wrote:
> > As for GNU tar, I think that this is easily fixable if you have access to
> > non-GNU tar. We do not use tar _ever_, except for the test suite, to
> > verify that things are working as expected.
> >
> > If you could put in some time to make the tests work, that would be
> > awesome.
>
> Yeah, it would be a good thing to get rid of any bashisms, but to _keep_
> it working somebody would then need to test every once in a while that it
> still works ;)
I'll see what I can do. As I'm planning on running git on both FreeBSD
and DragonFly for the forseeable future, and plan to track git's
evolution (running stable releases if not more bleeding-edge code), I
can run the test suite every time I build a new git.
Cheers,
- David
>
> Linus
>
--
If I have not seen farther, it is because I have stood in the
footsteps of giants.
^ permalink raw reply
* Re: pushing changes to a remote branch
From: Sean Kelley @ 2007-07-11 3:44 UTC (permalink / raw)
To: git
In-Reply-To: <844FC382-DFB3-4762-93C2-6512612136AC@silverinsanity.com>
Hi,
On 7/10/07, Brian Gernhardt <benji@silverinsanity.com> wrote:
>
> On Jul 10, 2007, at 1:34 PM, Jeff King wrote:
>
> > On Tue, Jul 10, 2007 at 04:36:14PM +0200, martin f krafft wrote:
> >
> >> git checkout origin/vim
> >> Note: moving to "origin/vim" which isn't a local branch
> >> echo change > newfile; git add newfile
> >> git commit -m'make change'
> >> Created commit 64b8b2e: make change
> >> 1 files changed, 1 insertions(+), 0 deletions(-)
> >> create mode 100644 newfile
> >>
> >> If I now checkout master and then return to origin/vim, the commit
> >> is gone.
> >
> > That's because 'origin/vim' is a tracking branch for the remote; it's
> > where you store the information "here's what the remote 'origin'
> > thinks
> > is in the branch 'vim'." That's why you get the "note" warning above.
> >
> > If you want to make changes, you should make a local branch starting
> > from that point:
> >
> > git-checkout -b vim origin/vim
> > # hack hack hack
> > git-commit -m changes
>
> Indeed, in master, git outputs a hint to that when you checkout the
> remote branch.
>
> $ git checkout origin/master
> Note: moving to "origin/master" which isn't a local branch
> If you want to create a new branch from this checkout, you may do so
> (now or later) by using -b with the checkout command again. Example:
> git checkout -b <new_branch_name>
> HEAD is now at f4855d4... 1
>
> Perhaps git-commit should also also output a warning? "Commit made
> on detached HEAD. Use "git branch <new_branch_name>" to save your
> commit"? That's bad wording, but the idea is there.
If you then do a push from that new_branch_name will it create a new
branch on the remote? I am struggling with just being able to add a
remote. Create a local branch that maps to the remote. Then
committing and pushing changes to the remote - all without creating a
new branch on the remote.
Sean
>
> ~~ Brian
> -
> To unsubscribe from this list: send the line "unsubscribe git" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
^ permalink raw reply
* Re: test suite fails if sh != bash || tar != GNU tar
From: Linus Torvalds @ 2007-07-11 3:22 UTC (permalink / raw)
To: Johannes Schindelin; +Cc: David Frech, git
In-Reply-To: <Pine.LNX.4.64.0707110347580.4047@racer.site>
On Wed, 11 Jul 2007, Johannes Schindelin wrote:
>
> Actually, Ubuntu seems to ship with dash as the default shell, and we had
> quite some fallout from that change.
Well, part of it was really dash bugs, no? The whole "'shift' on an empty
argument list" seemed to be a total and outright dash bug, and wasn't
about relying on bash "features".
But we've had tons of issues with different spacing for "wc -l" etc, so
yeah, the silly details matter even when there aren't outright bugs in
tools.
> As for GNU tar, I think that this is easily fixable if you have access to
> non-GNU tar. We do not use tar _ever_, except for the test suite, to
> verify that things are working as expected.
>
> If you could put in some time to make the tests work, that would be
> awesome.
Yeah, it would be a good thing to get rid of any bashisms, but to _keep_
it working somebody would then need to test every once in a while that it
still works ;)
Linus
^ permalink raw reply
* Re: test suite fails if sh != bash || tar != GNU tar
From: Johannes Schindelin @ 2007-07-11 2:49 UTC (permalink / raw)
To: David Frech; +Cc: git
In-Reply-To: <7154c5c60707101939sc921b07wef1d14f85086947d@mail.gmail.com>
Hi,
On Tue, 10 Jul 2007, David Frech wrote:
> Anyone running Linux or Mac OSX won't see these problems, because on
> both platforms /bin/sh == bash and tar == GNU tar.
Actually, Ubuntu seems to ship with dash as the default shell, and we had
quite some fallout from that change.
As for GNU tar, I think that this is easily fixable if you have access to
non-GNU tar. We do not use tar _ever_, except for the test suite, to
verify that things are working as expected.
If you could put in some time to make the tests work, that would be
awesome.
Ciao,
Dscho
^ permalink raw reply
* test suite fails if sh != bash || tar != GNU tar
From: David Frech @ 2007-07-11 2:39 UTC (permalink / raw)
To: git
I've built git on several BSD (FreeBSD and DragonFlyBSD) systems, and
while it builds fine on both platforms, the test suite *fails* on
both.
I tracked most of the problems down to dependencies on bash and GNU
tar. I'm not sure yet what the specific differences are between BSD's
/bin/sh and bash (the two are separate in the BSD world), but it's
obvious what the problem is with tar: the git-archive test parses
datestamps printed out by tar, and the two tar's print datestamps
differently.
If I set SHELL_PATH=/usr/local/bin/bash and TAR=gtar (the name of GNU
tar on BSD systems) I am able to get thru all the tests on FreeBSD
(this is with a checkout of the v1.5.2.3 tag).
On DragonFly there is another problem that I have not yet tracked
down. git-mailinfo fails on 0004 - it fails to extract *anything* from
the message.
Anyone running Linux or Mac OSX won't see these problems, because on
both platforms /bin/sh == bash and tar == GNU tar.
Cheers,
- David
--
If I have not seen farther, it is because I have stood in the
footsteps of giants.
^ permalink raw reply
* Re: [PATCH 3/4] --decorate now decorates ancestors, too
From: Theodore Tso @ 2007-07-11 2:27 UTC (permalink / raw)
To: Johannes Schindelin; +Cc: git, gitster
In-Reply-To: <Pine.LNX.4.64.0707110229320.4047@racer.site>
On Wed, Jul 11, 2007 at 02:29:49AM +0100, Johannes Schindelin wrote:
>
> The option --decorate changed default behavior: Earlier, it decorated
> commits pointed to by any ref. The new behavior is this: decorate the
> with the given refs and its ancestors, i.e.
>
> git log --decorate next master
>
> will show "next", "next^", "next~2", ..., "master", "master^", ...
> in parenthesis after the commit name.
I'm wondering how useful the default is. The arguments get used for
two things; both for git-log to decide what revisions to display, and
which refs to decorate, right? I'm not sure that overloading is such
a great idea.
Also, I note that "git log --decorate" does nothing at all. Maybe it
would be better to keep the default to be "any-ref" instead of "given"?
- Ted
^ permalink raw reply
* [PATCH 4/4] --decorate: prefer shorter names
From: Johannes Schindelin @ 2007-07-11 1:30 UTC (permalink / raw)
To: git, gitster
In-Reply-To: <Pine.LNX.4.64.0707110220340.4047@racer.site>
When saying "--decorate=any", the decoration could get huge pretty
quickly. Especially in a project like git.git, where there is a
lot of back and forth merging, older commits can be named in a
thousand ways.
However, usually you are only interested in short names. For example,
most people are not interested in the fact that the initial commit
can be named by ways like v0.99~31^2~37^2^2~508^2^2~195^2~114, if you
can reference it by v0.99~954 instead.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
commit.c | 39 +++++++++++++++++++++++++++++----------
commit.h | 4 ++--
revision.c | 10 ++++++----
3 files changed, 37 insertions(+), 16 deletions(-)
diff --git a/commit.c b/commit.c
index 3aa21cc..4128ef4 100644
--- a/commit.c
+++ b/commit.c
@@ -1554,25 +1554,43 @@ int in_merge_bases(struct commit *commit, struct commit **reference, int num)
return ret;
}
-void add_name_decoration(const char *prefix, const char *name, int generation, struct object *obj)
+void add_name_decoration(const char *prefix, const char *name, int generation, int distance, struct object *obj)
{
int plen = strlen(prefix);
int nlen = strlen(name);
struct name_decoration *res, *existing;
+ int free_existing = 0;
+
+ existing = lookup_decoration(&name_decoration, obj);
+ if (existing && existing->distance < distance)
+ return;
+
+ if (existing && existing->distance > distance)
+ free_existing = 1;
res = xmalloc(sizeof(struct name_decoration) + plen + nlen);
memcpy(res->name, prefix, plen);
memcpy(res->name + plen, name, nlen + 1);
- for (existing = lookup_decoration(&name_decoration, obj);
- existing; existing = existing->next)
- if (!strcmp(existing->name, res->name)) {
- free(res);
- return;
- }
+ if (!free_existing)
+ for (; existing; existing = existing->next)
+ if (!strcmp(existing->name, res->name)) {
+ free(res);
+ return;
+ }
res->generation = generation;
+ res->distance = distance;
res->next = add_decoration(&name_decoration, obj, res);
+
+ if (free_existing) {
+ for (existing = res->next; existing; ) {
+ struct name_decoration *next = existing->next;
+ free(existing);
+ existing = next;
+ }
+ res->next = NULL;
+ }
}
int add_ref_decoration(const char *refname, const unsigned char *sha1, int flags, void *cb_data)
@@ -1588,12 +1606,12 @@ int add_ref_decoration(const char *refname, const unsigned char *sha1, int flags
refname += 13;
else if (!prefixcmp(refname, "refs/"))
refname += 5;
- add_name_decoration("", refname, 0, obj);
+ add_name_decoration("", refname, 0, 0, obj);
while (obj->type == OBJ_TAG) {
obj = ((struct tag *)obj)->tagged;
if (!obj)
break;
- add_name_decoration("tag: ", refname, 0, obj);
+ add_name_decoration("tag: ", refname, 0, 0, obj);
}
return 0;
}
@@ -1614,7 +1632,7 @@ void add_name_decoration_to_parents(struct commit *commit)
for (decor = decoration; decor; decor = decor->next)
add_name_decoration("", decor->name, decor->generation + 1,
- &parents->item->object);
+ decor->distance + 1, &parents->item->object);
parent_nr = 1;
while (parents->next) {
@@ -1632,6 +1650,7 @@ void add_name_decoration_to_parents(struct commit *commit)
"%s~%d^%d", decor->name,
decor->generation, parent_nr);
add_name_decoration("", buffer, 0,
+ decor->distance + 256,
&parents->item->object);
}
}
diff --git a/commit.h b/commit.h
index 8dafc7b..9b2bd55 100644
--- a/commit.h
+++ b/commit.h
@@ -26,11 +26,11 @@ extern const char *commit_type;
extern struct decoration name_decoration;
struct name_decoration {
struct name_decoration *next;
- int generation;
+ int generation, distance;
char name[1];
};
-void add_name_decoration(const char *prefix, const char *name, int generation, struct object *obj);
+void add_name_decoration(const char *prefix, const char *name, int generation, int distance, struct object *obj);
int add_ref_decoration(const char *refname, const unsigned char *sha1, int flags, void *cb_data);
void add_name_decoration_to_parents(struct commit *commit);
diff --git a/revision.c b/revision.c
index 79880b4..796275d 100644
--- a/revision.c
+++ b/revision.c
@@ -642,7 +642,7 @@ static int add_parents_only(struct rev_info *revs, const char *arg, int flags)
return 0;
commit = (struct commit *)it;
if (revs->decorate & DECORATE_GIVEN_REFS)
- add_name_decoration("", arg, 0, it);
+ add_name_decoration("", arg, 0, 0, it);
if (revs->decorate & DECORATE_RECURSIVE)
add_name_decoration_to_parents(commit);
for (parents = commit->parents; parents; parents = parents->next) {
@@ -783,8 +783,10 @@ int handle_revision_arg(const char *arg, struct rev_info *revs,
}
if (revs->decorate & DECORATE_GIVEN_REFS) {
- add_name_decoration("", this, 0, &a->object);
- add_name_decoration("", next, 0, &b->object);
+ add_name_decoration("", this, 0, 0,
+ &a->object);
+ add_name_decoration("", next, 0, 0,
+ &b->object);
}
if (symmetric) {
@@ -827,7 +829,7 @@ int handle_revision_arg(const char *arg, struct rev_info *revs,
verify_non_filename(revs->prefix, arg);
object = get_reference(revs, arg, sha1, flags ^ local_flags);
if (revs->decorate & DECORATE_GIVEN_REFS)
- add_name_decoration("", arg, 0, object);
+ add_name_decoration("", arg, 0, 0, object);
add_pending_object_with_mode(revs, object, arg, mode);
return 0;
}
--
1.5.3.rc0.2783.gf3f7
^ permalink raw reply related
* [PATCH 3/4] --decorate now decorates ancestors, too
From: Johannes Schindelin @ 2007-07-11 1:29 UTC (permalink / raw)
To: git, gitster
In-Reply-To: <Pine.LNX.4.64.0707110220340.4047@racer.site>
The option --decorate changed default behavior: Earlier, it decorated
commits pointed to by any ref. The new behavior is this: decorate the
with the given refs and its ancestors, i.e.
git log --decorate next master
will show "next", "next^", "next~2", ..., "master", "master^", ...
in parenthesis after the commit name.
However, you can still get the old behavior by giving --decorate=<mode>.
The available modes are:
- 'given' the new default behavior,
- 'given-refs' only decorate with the given refs, not their ancestors,
- 'tag' decorate with all tag refs and their ancestors,
- 'tag-refs' decorate with all tag refs, but not their ancestors,
- 'any' decorate with all refs and their ancestors,
- 'any-ref' decorate only with the refs, not their ancestors
The old behavior was 'any-ref'.
NOTE: Calling "git log --decorate=tag <commit>" is _not_ the same as
calling "git log <commit> | git -p name-rev --stdin":
For one, the latter will only try to name 40-character hex sequences
(which the former does not care about), but then it will also try
to name such sequences in the commit messages and the diffs.
More importantly, though, "--decorate=tag" will only build the names
while traversing commits, which makes it faster, but will fail to
correctly identify something like "git log --decorate=tag v0.99~2".
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
Documentation/pretty-options.txt | 17 ++++++++--
commit.c | 68 +++++++++++++++++++++++++++++++++++--
commit.h | 4 ++-
log-tree.c | 4 ++
revision.c | 43 +++++++++++++++++++++++-
revision.h | 9 +++++
6 files changed, 136 insertions(+), 9 deletions(-)
diff --git a/Documentation/pretty-options.txt b/Documentation/pretty-options.txt
index 3b21e0d..f82b1e9 100644
--- a/Documentation/pretty-options.txt
+++ b/Documentation/pretty-options.txt
@@ -21,6 +21,17 @@ people using 80-column terminals.
preferred by the user. For non plumbing commands this
defaults to UTF-8.
---decorate::
- When a commit is shown, and it matches a ref, print that ref name
- in brackets after the commit name.
+--decorate[=<mode>]::
+ When a commit is shown, decorate its commit name with the refs
+ specified on the command line or their ancestors which point to
+ that commit.
++
+You can influence the behaviour by givin a mode:
+- 'given' is the default mode,
+- 'given-refs' skips the decoration for ancestors,
+- 'tag-refs' decorates only the tagged commits,
+- 'tag' decorates tagged commits and their ancestors,
+- 'any-ref' means that those commits are decorated that match any ref
+ exactly, but no ancestors, and
+- 'any' means that all commits that are pointed at by _any_ reachable
+ commit are decorated by the appropriate names.
diff --git a/commit.c b/commit.c
index c0748ed..3aa21cc 100644
--- a/commit.c
+++ b/commit.c
@@ -1554,13 +1554,24 @@ int in_merge_bases(struct commit *commit, struct commit **reference, int num)
return ret;
}
-void add_name_decoration(const char *prefix, const char *name, struct object *obj)
+void add_name_decoration(const char *prefix, const char *name, int generation, struct object *obj)
{
int plen = strlen(prefix);
int nlen = strlen(name);
- struct name_decoration *res = xmalloc(sizeof(struct name_decoration) + plen + nlen);
+ struct name_decoration *res, *existing;
+
+ res = xmalloc(sizeof(struct name_decoration) + plen + nlen);
memcpy(res->name, prefix, plen);
memcpy(res->name + plen, name, nlen + 1);
+
+ for (existing = lookup_decoration(&name_decoration, obj);
+ existing; existing = existing->next)
+ if (!strcmp(existing->name, res->name)) {
+ free(res);
+ return;
+ }
+
+ res->generation = generation;
res->next = add_decoration(&name_decoration, obj, res);
}
@@ -1569,12 +1580,61 @@ int add_ref_decoration(const char *refname, const unsigned char *sha1, int flags
struct object *obj = parse_object(sha1);
if (!obj)
return 0;
- add_name_decoration("", refname, obj);
+ if (!prefixcmp(refname, "refs/heads/"))
+ refname += 11;
+ else if (!prefixcmp(refname, "refs/tags/"))
+ refname += 10;
+ else if (!prefixcmp(refname, "refs/remotes/"))
+ refname += 13;
+ else if (!prefixcmp(refname, "refs/"))
+ refname += 5;
+ add_name_decoration("", refname, 0, obj);
while (obj->type == OBJ_TAG) {
obj = ((struct tag *)obj)->tagged;
if (!obj)
break;
- add_name_decoration("tag: ", refname, obj);
+ add_name_decoration("tag: ", refname, 0, obj);
}
return 0;
}
+
+void add_name_decoration_to_parents(struct commit *commit)
+{
+ struct name_decoration *decoration, *decor;
+ struct commit_list *parents;
+ int parent_nr;
+
+ parents = commit->parents;
+ if (!parents)
+ return;
+
+ decoration = lookup_decoration(&name_decoration, &commit->object);
+ if (!decoration)
+ return;
+
+ for (decor = decoration; decor; decor = decor->next)
+ add_name_decoration("", decor->name, decor->generation + 1,
+ &parents->item->object);
+
+ parent_nr = 1;
+ while (parents->next) {
+ char buffer[PATH_MAX];
+ parents = parents->next;
+ parent_nr++;
+ for (decor = decoration; decor; decor = decor->next) {
+ if (decor->generation < 2)
+ snprintf(buffer, sizeof(buffer),
+ "%s%s^%d", decor->name,
+ decor->generation ? "^" : "",
+ parent_nr);
+ else
+ snprintf(buffer, sizeof(buffer),
+ "%s~%d^%d", decor->name,
+ decor->generation, parent_nr);
+ add_name_decoration("", buffer, 0,
+ &parents->item->object);
+ }
+ }
+}
+
+
diff --git a/commit.h b/commit.h
index 787ae5e..8dafc7b 100644
--- a/commit.h
+++ b/commit.h
@@ -26,11 +26,13 @@ extern const char *commit_type;
extern struct decoration name_decoration;
struct name_decoration {
struct name_decoration *next;
+ int generation;
char name[1];
};
-void add_name_decoration(const char *prefix, const char *name, struct object *obj);
+void add_name_decoration(const char *prefix, const char *name, int generation, struct object *obj);
int add_ref_decoration(const char *refname, const unsigned char *sha1, int flags, void *cb_data);
+void add_name_decoration_to_parents(struct commit *commit);
struct commit *lookup_commit(const unsigned char *sha1);
struct commit *lookup_commit_reference(const unsigned char *sha1);
diff --git a/log-tree.c b/log-tree.c
index 8624d5a..eb7641a 100644
--- a/log-tree.c
+++ b/log-tree.c
@@ -26,6 +26,10 @@ static void show_decorations(struct commit *commit)
prefix = " (";
while (decoration) {
printf("%s%s", prefix, decoration->name);
+ if (decoration->generation == 1)
+ putchar('^');
+ else if (decoration->generation > 1)
+ printf("~%d", decoration->generation);
prefix = ", ";
decoration = decoration->next;
}
diff --git a/revision.c b/revision.c
index 7683d0a..79880b4 100644
--- a/revision.c
+++ b/revision.c
@@ -641,6 +641,10 @@ static int add_parents_only(struct rev_info *revs, const char *arg, int flags)
if (it->type != OBJ_COMMIT)
return 0;
commit = (struct commit *)it;
+ if (revs->decorate & DECORATE_GIVEN_REFS)
+ add_name_decoration("", arg, 0, it);
+ if (revs->decorate & DECORATE_RECURSIVE)
+ add_name_decoration_to_parents(commit);
for (parents = commit->parents; parents; parents = parents->next) {
it = &parents->item->object;
it->flags |= flags;
@@ -778,6 +782,11 @@ int handle_revision_arg(const char *arg, struct rev_info *revs,
verify_non_filename(revs->prefix, arg);
}
+ if (revs->decorate & DECORATE_GIVEN_REFS) {
+ add_name_decoration("", this, 0, &a->object);
+ add_name_decoration("", next, 0, &b->object);
+ }
+
if (symmetric) {
exclude = get_merge_bases(a, b, 1);
add_pending_commit_list(revs, exclude,
@@ -817,6 +826,8 @@ int handle_revision_arg(const char *arg, struct rev_info *revs,
if (!cant_be_filename)
verify_non_filename(revs->prefix, arg);
object = get_reference(revs, arg, sha1, flags ^ local_flags);
+ if (revs->decorate & DECORATE_GIVEN_REFS)
+ add_name_decoration("", arg, 0, object);
add_pending_object_with_mode(revs, object, arg, mode);
return 0;
}
@@ -1177,7 +1188,29 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch
continue;
}
if (!strcmp(arg, "--decorate")) {
- for_each_ref(add_ref_decoration, NULL);
+ revs->decorate = DECORATE_GIVEN_REFS |
+ DECORATE_RECURSIVE;
+ continue;
+ }
+ if (!prefixcmp(arg, "--decorate=")) {
+ if (!strcmp(arg + 11, "any-ref"))
+ revs->decorate = DECORATE_ALL_REFS;
+ else if (!strcmp(arg + 11, "given-refs"))
+ revs->decorate = DECORATE_GIVEN_REFS;
+ else if (!strcmp(arg + 11, "given"))
+ revs->decorate = DECORATE_GIVEN_REFS |
+ DECORATE_RECURSIVE;
+ else if (!strcmp(arg + 11, "any"))
+ revs->decorate = DECORATE_GIVEN_REFS |
+ DECORATE_ALL_REFS |
+ DECORATE_RECURSIVE;
+ else if (!strcmp(arg + 11, "tag-refs"))
+ revs->decorate = DECORATE_TAG_REFS;
+ else if (!strcmp(arg + 11, "tag"))
+ revs->decorate = DECORATE_TAG_REFS |
+ DECORATE_RECURSIVE;
+ else
+ die("Unknown argument: %s", arg);
continue;
}
@@ -1213,6 +1246,11 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch
}
}
+ if (revs->decorate & DECORATE_ALL_REFS)
+ for_each_ref(add_ref_decoration, NULL);
+ if (revs->decorate & DECORATE_TAG_REFS)
+ for_each_tag_ref(add_ref_decoration, NULL);
+
if (revs->grep_filter)
revs->grep_filter->regflags |= regflags;
@@ -1372,6 +1410,9 @@ static struct commit *get_revision_1(struct rev_info *revs)
revs->commits = entry->next;
free(entry);
+ if (revs->decorate & DECORATE_RECURSIVE)
+ add_name_decoration_to_parents(commit);
+
if (revs->reflog_info)
fake_reflog_parent(revs->reflog_info, commit);
diff --git a/revision.h b/revision.h
index f46b4d5..0c3dc67 100644
--- a/revision.h
+++ b/revision.h
@@ -16,6 +16,14 @@ struct log_info;
typedef void (prune_fn_t)(struct rev_info *revs, struct commit *commit);
+enum decorate {
+ DECORATE_NONE = 0,
+ DECORATE_RECURSIVE = 1,
+ DECORATE_ALL_REFS = 2,
+ DECORATE_TAG_REFS = 4,
+ DECORATE_GIVEN_REFS = 8,
+};
+
struct rev_info {
/* Starting list */
struct commit_list *commits;
@@ -65,6 +73,7 @@ struct rev_info {
unsigned int shown_one:1,
abbrev_commit:1;
enum date_mode date_mode;
+ enum decorate decorate;
const char **ignore_packed; /* pretend objects in these are unpacked */
int num_ignore_packed;
--
1.5.3.rc0.2783.gf3f7
^ permalink raw reply related
* [PATCH 2/4] Move the --decorate option from builtin-log.c to revision.c.
From: Johannes Schindelin @ 2007-07-11 1:29 UTC (permalink / raw)
To: git, gitster
In-Reply-To: <Pine.LNX.4.64.0707110220340.4047@racer.site>
It is more logical to have the --decorate option in revision, like
many others affecting the way how commits are shown.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
Documentation/git-log.txt | 3 ---
Documentation/pretty-options.txt | 4 ++++
builtin-log.c | 14 ++------------
revision.c | 4 ++++
4 files changed, 10 insertions(+), 15 deletions(-)
diff --git a/Documentation/git-log.txt b/Documentation/git-log.txt
index 7adcdef..b55a87e 100644
--- a/Documentation/git-log.txt
+++ b/Documentation/git-log.txt
@@ -51,9 +51,6 @@ include::pretty-options.txt[]
a record about how the tip of a reference was changed.
See also gitlink:git-reflog[1].
---decorate::
- Print out the ref names of any commits that are shown.
-
--full-diff::
Without this flag, "git log -p <paths>..." shows commits that
touch the specified paths, and diffs about the same specified
diff --git a/Documentation/pretty-options.txt b/Documentation/pretty-options.txt
index 746bc5b..3b21e0d 100644
--- a/Documentation/pretty-options.txt
+++ b/Documentation/pretty-options.txt
@@ -20,3 +20,7 @@ people using 80-column terminals.
command to re-code the commit log message in the encoding
preferred by the user. For non plumbing commands this
defaults to UTF-8.
+
+--decorate::
+ When a commit is shown, and it matches a ref, print that ref name
+ in brackets after the commit name.
diff --git a/builtin-log.c b/builtin-log.c
index c14eea5..59372bb 100644
--- a/builtin-log.c
+++ b/builtin-log.c
@@ -24,9 +24,6 @@ void add_head(struct rev_info *revs);
static void cmd_log_init(int argc, const char **argv, const char *prefix,
struct rev_info *rev)
{
- int i;
- int decorate = 0;
-
rev->abbrev = DEFAULT_ABBREV;
rev->commit_format = CMIT_FMT_DEFAULT;
rev->verbose_header = 1;
@@ -40,15 +37,8 @@ static void cmd_log_init(int argc, const char **argv, const char *prefix,
if (rev->diffopt.nr_paths != 1)
usage("git logs can only follow renames on one pathname at a time");
}
- for (i = 1; i < argc; i++) {
- const char *arg = argv[i];
- if (!strcmp(arg, "--decorate")) {
- if (!decorate)
- for_each_ref(add_ref_decoration, NULL);
- decorate = 1;
- } else
- die("unrecognized argument: %s", arg);
- }
+ if (argc > 1)
+ die("unrecognized argument: %s", argv[1]);
}
static int cmd_log_walk(struct rev_info *rev)
diff --git a/revision.c b/revision.c
index 33ee9ee..7683d0a 100644
--- a/revision.c
+++ b/revision.c
@@ -1176,6 +1176,10 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch
revs->reverse ^= 1;
continue;
}
+ if (!strcmp(arg, "--decorate")) {
+ for_each_ref(add_ref_decoration, NULL);
+ continue;
+ }
opts = diff_opt_parse(&revs->diffopt, argv+i, argc-i);
if (opts > 0) {
--
1.5.3.rc0.2783.gf3f7
^ permalink raw reply related
* [PATCH 1/4] Move add_name_decoration() and add_ref_decoration() to commit.[ch]
From: Johannes Schindelin @ 2007-07-11 1:28 UTC (permalink / raw)
To: git, gitster
In-Reply-To: <Pine.LNX.4.64.0707110220340.4047@racer.site>
The functions add_{name,ref}_decoration() should really be in
commit.[ch], since the struct they are modifying is there, too.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
builtin-log.c | 25 -------------------------
commit.c | 25 +++++++++++++++++++++++++
commit.h | 3 +++
3 files changed, 28 insertions(+), 25 deletions(-)
diff --git a/builtin-log.c b/builtin-log.c
index 13bae31..c14eea5 100644
--- a/builtin-log.c
+++ b/builtin-log.c
@@ -21,31 +21,6 @@ static const char *fmt_patch_subject_prefix = "PATCH";
/* this is in builtin-diff.c */
void add_head(struct rev_info *revs);
-static void add_name_decoration(const char *prefix, const char *name, struct object *obj)
-{
- int plen = strlen(prefix);
- int nlen = strlen(name);
- struct name_decoration *res = xmalloc(sizeof(struct name_decoration) + plen + nlen);
- memcpy(res->name, prefix, plen);
- memcpy(res->name + plen, name, nlen + 1);
- res->next = add_decoration(&name_decoration, obj, res);
-}
-
-static int add_ref_decoration(const char *refname, const unsigned char *sha1, int flags, void *cb_data)
-{
- struct object *obj = parse_object(sha1);
- if (!obj)
- return 0;
- add_name_decoration("", refname, obj);
- while (obj->type == OBJ_TAG) {
- obj = ((struct tag *)obj)->tagged;
- if (!obj)
- break;
- add_name_decoration("tag: ", refname, obj);
- }
- return 0;
-}
-
static void cmd_log_init(int argc, const char **argv, const char *prefix,
struct rev_info *rev)
{
diff --git a/commit.c b/commit.c
index 03436b1..c0748ed 100644
--- a/commit.c
+++ b/commit.c
@@ -1553,3 +1553,28 @@ int in_merge_bases(struct commit *commit, struct commit **reference, int num)
free_commit_list(bases);
return ret;
}
+
+void add_name_decoration(const char *prefix, const char *name, struct object *obj)
+{
+ int plen = strlen(prefix);
+ int nlen = strlen(name);
+ struct name_decoration *res = xmalloc(sizeof(struct name_decoration) + plen + nlen);
+ memcpy(res->name, prefix, plen);
+ memcpy(res->name + plen, name, nlen + 1);
+ res->next = add_decoration(&name_decoration, obj, res);
+}
+
+int add_ref_decoration(const char *refname, const unsigned char *sha1, int flags, void *cb_data)
+{
+ struct object *obj = parse_object(sha1);
+ if (!obj)
+ return 0;
+ add_name_decoration("", refname, obj);
+ while (obj->type == OBJ_TAG) {
+ obj = ((struct tag *)obj)->tagged;
+ if (!obj)
+ break;
+ add_name_decoration("tag: ", refname, obj);
+ }
+ return 0;
+}
diff --git a/commit.h b/commit.h
index 467872e..787ae5e 100644
--- a/commit.h
+++ b/commit.h
@@ -29,6 +29,9 @@ struct name_decoration {
char name[1];
};
+void add_name_decoration(const char *prefix, const char *name, struct object *obj);
+int add_ref_decoration(const char *refname, const unsigned char *sha1, int flags, void *cb_data);
+
struct commit *lookup_commit(const unsigned char *sha1);
struct commit *lookup_commit_reference(const unsigned char *sha1);
struct commit *lookup_commit_reference_gently(const unsigned char *sha1,
--
1.5.3.rc0.2783.gf3f7
^ permalink raw reply related
* [PATCH 0/4] Make --decorate more useful
From: Johannes Schindelin @ 2007-07-11 1:28 UTC (permalink / raw)
To: git, gitster
This series is meant to (partially) replace the patch I posted in
http://article.gmane.org/gmane.comp.version-control.git/24383
Often it is useful to find out what feature came in when, to quickly
find out if some version of the software is sufficient, or if the
other person has to upgrade.
With this series applied, you can say
git log --decorate=tag -S<some keyword> <file>
to find out what that version was, indeed you even get a human readable
name for that commit, in addition to the commit name.
Johannes Schindelin (4):
Move add_name_decoration() and add_ref_decoration() to commit.[ch]
Move the --decorate option from builtin-log.c to revision.c.
--decorate now decorates ancestors, too
--decorate: prefer shorter names
Documentation/git-log.txt | 3 -
Documentation/pretty-options.txt | 15 ++++++
builtin-log.c | 39 +-------------
commit.c | 104 ++++++++++++++++++++++++++++++++++++++
commit.h | 5 ++
log-tree.c | 4 ++
revision.c | 47 +++++++++++++++++
revision.h | 9 +++
8 files changed, 186 insertions(+), 40 deletions(-)
^ permalink raw reply
* Re: What happened with git-note?
From: Johannes Schindelin @ 2007-07-11 1:17 UTC (permalink / raw)
To: Alberto Bertogli; +Cc: git, gitster, Johan Herland
In-Reply-To: <20070710231735.GZ1813@gmail.com>
Hi,
[Johan, I Cc'ed you, since you were the person pushing for git-notes
originally. Junio, I Cc'ed you, because you correctly pointed out the
flaws in my approach.]
On Tue, 10 Jul 2007, Alberto Bertogli wrote:
> There was a very long thread about a proposed feature, git-note
> (http://thread.gmane.org/gmane.comp.version-control.git/46770/focus=48540),
> around May this year.
>
> I was wondering what happened to it, because some issues were brought up
> but then everything seem to have stalled.
>
> Is someone working on it? Is there a clear list of the pending issues
> somewhere?
Okay, I seem to be at fault for the stalling. So I better speak up about
what my proof-of-concept did:
It creates a new ref, "refs/notes/commits", which had a tree object in it.
The tree entries were actually fan-out directories a la .git/objects/??/.
So if you added a not to commit abcdef01234..., it created a "file" named
refs/notes/commits:ab/cdef01234...
The advantages of this approach, as compared to an external list, or even
SQLite database were, amongst others:
- you can use most of the existing framework (storage, pruning, etc.),
- there is an obvious way how to fetch the notes from someone else,
- there is an obvious way how to deal with conflicts when merging notes
from someone else,
- it is conceptually trivial.
However, the biggest disadvantage was pointed out by Junio:
The tree objects under refs/notes/commits:??/ can get pretty large, in
theory. Suppose you have a rate of a couple of hundred commits a day, and
you want to use the notes framework, amongst others, to be able to add
Acked-by's all over the place. Pretty soon we are in the hundreds of
entries in the tree objects.
I thought that this is not a problem, since the names all have the same
length. Alas, Git is general purpose, so it does not, and cannot, assume
a certain filename format. Git might be considered a stupid content
tracker, but it is not quite that stupid.
Since the tree objects just contain lists of tree entries, and each tree
entry is variable length, you have to look through half of the entries on
average, before you find the one you look for.
Possible solutions I can come up with:
There was a lot of talk, and quite a few good ideas, in the packv4 side
branch, which was undertaken by Nico and Shawn. The basic idea, IIUC, is
to store objects differently, by having nice things like a filename table
containing the most common names, sorted, which are then not only
addressed much more efficiently (by a 16-bit index), but reverse indexing
is also much more efficient, since you do not have to expand and compare
the full filenames, but instead compare 16-bin numbers.
This format would help with the approach I presented above.
Another idea which just crossed my mind, is to add indexes which are
generated locally, but not transmitted when fetching, much like the pack
indices, which are generated from the pack while fetching it.
There are a couple of possible technical ways to do that efficiently, such
as mmap()ed rbtrees, or hashtables. Of course, Git's own history suggests
to prefer hashtables over other data structures, when your keys are
already pretty good hashes, which they are. However, I have not thought
it through, what with the issue of growing the data structure, or
thrashing the I/O caches.
Of course, one does not have to go with the approach of storing the things
as blobs. There might well be a genius coming along, reading this mail,
and proposing the uber-solution. But dammit, I am pretty sure that we
have a real good framework, and that a proper solution is just a stone's
throw away.
Ciao,
Dscho
^ permalink raw reply
* Re: how to combine two clones in a collection
From: Robin Rosenberg @ 2007-07-10 23:45 UTC (permalink / raw)
To: Brian Gernhardt; +Cc: Kalle Pokki, git
In-Reply-To: <47015E14-FEA7-45C5-B9CB-C949B87B6494@silverinsanity.com>
tisdag 10 juli 2007 skrev Brian Gernhardt:
>
> On Jul 10, 2007, at 3:27 PM, Kalle Pokki wrote:
>
> > You can also just create two different git repositories and start
> > making
> > the commits in the master (or any other) branch. Then combine the
> > repositories by fetching
> >
> > cd repo1
> > git fetch ../repo2 master:repo2
> >
> > This way the branches don't share anything, do they?
>
> Yes, that's what I was referring to at the end when I wrote:
>
> > You could also create the branch in a second repository and pull it
> > from there into the first (probably simpler),
>
> But it seemed too simple. ;-) And that is exactly how I'd do it...
> Assuming I thought of it before using write-tree, commit-tree, and
> update-ref. (Which is what happened. I thought of the complicated
> method and wrote it up before thinking "duh, just use a second repo.")
And the simplest way to create an new indpendent branch:
echo ref: refs/heads/newbranch >.git/HEAD
Then prepare the content and commit like you used to do.
-- robin
^ permalink raw reply
* Re: [PATCH] gitweb: snapshot cleanups & support for offering multiple formats
From: Jakub Narebski @ 2007-07-10 23:41 UTC (permalink / raw)
To: git
In-Reply-To: <1184023318.9703.1.camel@mattlaptop2>
Matt McCutchen wrote:
> - Centralize knowledge about snapshot formats (mime types, extensions,
> commands) in %known_snapshot_formats and improve how some of that
> information is specified. In particular, zip files are no longer a
> special case.
>
> - Add support for offering multiple snapshot formats to the user so
> that he/she can download a snapshot in the format he/she prefers.
> The site-wide or project configuration now gives a list of formats
> to offer, and the "_snapshot_" link is replaced with, say,
> "snapshot (_tbz2_ _zip_)".
>
> - Fix out-of-date "tarball" -> "archive" in comment.
>
> Alert for gitweb site administrators: This patch changes the format of
> $feature{'snapshot'}{'default'} in gitweb_config.perl from a list of three
> pieces of information about a single format to a list of one or more formats
> you wish to offer from the set ('tgz', 'tbz2', 'zip'). Update your
> gitweb_config.perl appropriately.
Quite nice and I think needed refactoring of a snapshot code. Nevertheless
I have some comments on the changes introduced by this patch; not only
change to gitweb_config.perl is needed (which gitweb admin has control
over), but also repo config for individual repositories might need to
be changed (which gitweb admin might not have control over, and which is
much harder to do).
> +# information about snapshot formats that gitweb is capable of serving
> +# name => [mime type, filename suffix, --format for git-archive,
> +# compressor command suffix]
> +our %known_snapshot_formats = (
> + 'tgz' => ['application/x-gzip' , '.tar.gz' , 'tar', '| gzip' ],
> + 'tbz2' => ['application/x-bzip2', '.tar.bz2', 'tar', '| bzip2'],
> + 'zip' => ['application/zip' , '.zip' , 'zip', '' ],
> +);
First, is full mimetype really needed? Earlier code assumed that mimetype
for snapshot is of the form of application/<something>, and it provided
only <something>.
Second, I'd rather have 'gzip' and 'bzip2' aliases to 'tgz' and 'tbz2',
so the old config continues to work. I can see that it would be hard
to do without special-casing code, or changing the assumption that list
of default available snapshot formats is keys of above hash.
> - # and in project config gitweb.snapshot = none|gzip|bzip2|zip;
> + # and in project config, a comma-separated list of formats or "none"
> + # to disable. Example: gitweb.snapshot = tbz2,zip;
I would relax the syntax, so "tbz2, zip" would also work, or even
"tbz2 zip". I'd like for old config to also work, meaning that "gzip"
would be the same as "tgz" and "bzip2" as "tbz2".
> - if ($val eq 'gzip') {
> - return ('x-gzip', 'gz', 'gzip');
> - } elsif ($val eq 'bzip2') {
> - return ('x-bzip2', 'bz2', 'bzip2');
> - } elsif ($val eq 'zip') {
> - return ('x-zip', 'zip', '');
> - } elsif ($val eq 'none') {
> - return ();
Very nice getting rid of this swith-like statement...
> + if ($val) {
> + @fmts = ($val eq 'none' ? () : split /,/, $val);
... but I would relax this regexp.
> +# Generates undef or something like "snapshot (tbz2 zip)", linked.
> +# Pass the hash.
> +sub format_snapshot_links {
> + my ($hash) = @_;
> + my @snapshot_fmts = gitweb_check_feature('snapshot');
> + if (@snapshot_fmts) {
> + return "snapshot (" . join(' ', map $cgi->a(
> + {-href => href(action=>"snapshot", hash=>$hash, snapshot_format=>$_)}, "$_"),
> + @snapshot_fmts)
> + . ")";
> + } else {
> + return undef;
> + }
> +}
Nice separation into subroutine.
--
Jakub Narebski
Warsaw, Poland
ShadeHawk on #git
^ permalink raw reply
* What happened with git-note?
From: Alberto Bertogli @ 2007-07-10 23:17 UTC (permalink / raw)
To: git
Hi!
There was a very long thread about a proposed feature, git-note
(http://thread.gmane.org/gmane.comp.version-control.git/46770/focus=48540),
around May this year.
I was wondering what happened to it, because some issues were brought up
but then everything seem to have stalled.
Is someone working on it? Is there a clear list of the pending issues
somewhere?
Thanks,
Alberto
^ permalink raw reply
* [PATCH] t7004: Add tests for the git tag -n option.
From: Carlos Rica @ 2007-07-10 23:11 UTC (permalink / raw)
To: git, Junio C Hamano, Johannes Schindelin
These tests check the syntax for the git tag -n option
and its output when one, none or many lines of the
message are requested.
Also this commit adds a missing && in the test
that checks the sorted output of git tag -l.
Signed-off-by: Carlos Rica <jasampler@gmail.com>
---
t/t7004-tag.sh | 202 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 201 insertions(+), 1 deletions(-)
diff --git a/t/t7004-tag.sh b/t/t7004-tag.sh
index b785080..17de2a9 100755
--- a/t/t7004-tag.sh
+++ b/t/t7004-tag.sh
@@ -164,7 +164,7 @@ test_expect_success 'listing all tags should print them ordered' '
git tag a1 &&
git tag v1.0 &&
git tag t210 &&
- git tag -l > actual
+ git tag -l > actual &&
git diff expect actual
'
@@ -437,6 +437,106 @@ test_expect_success \
git diff expect actual
'
+# listing messages for annotated non-signed tags:
+
+test_expect_success \
+ 'listing the one-line message of a non-signed tag should succeed' '
+ git-tag -m "A msg" tag-one-line &&
+
+ echo "tag-one-line" >expect &&
+ git-tag -l | grep "^tag-one-line" >actual &&
+ git diff expect actual &&
+ git-tag -n 0 -l | grep "^tag-one-line" >actual &&
+ git diff expect actual &&
+ git-tag -n 0 -l tag-one-line >actual &&
+ git diff expect actual &&
+
+ echo "tag-one-line A msg" >expect &&
+ git-tag -n xxx -l | grep "^tag-one-line" >actual &&
+ git diff expect actual &&
+ git-tag -n "" -l | grep "^tag-one-line" >actual &&
+ git diff expect actual &&
+ git-tag -n 1 -l | grep "^tag-one-line" >actual &&
+ git diff expect actual &&
+ git-tag -n -l | grep "^tag-one-line" >actual &&
+ git diff expect actual &&
+ git-tag -n 1 -l tag-one-line >actual &&
+ git diff expect actual &&
+ git-tag -n 2 -l tag-one-line >actual &&
+ git diff expect actual &&
+ git-tag -n 999 -l tag-one-line >actual &&
+ git diff expect actual
+'
+
+test_expect_success \
+ 'listing the zero-lines message of a non-signed tag should succeed' '
+ git-tag -m "" tag-zero-lines &&
+
+ echo "tag-zero-lines" >expect &&
+ git-tag -l | grep "^tag-zero-lines" >actual &&
+ git diff expect actual &&
+ git-tag -n 0 -l | grep "^tag-zero-lines" >actual &&
+ git diff expect actual &&
+ git-tag -n 0 -l tag-zero-lines >actual &&
+ git diff expect actual &&
+
+ echo "tag-zero-lines " >expect &&
+ git-tag -n 1 -l | grep "^tag-zero-lines" >actual &&
+ git diff expect actual &&
+ git-tag -n -l | grep "^tag-zero-lines" >actual &&
+ git diff expect actual &&
+ git-tag -n 1 -l tag-zero-lines >actual &&
+ git diff expect actual &&
+ git-tag -n 2 -l tag-zero-lines >actual &&
+ git diff expect actual &&
+ git-tag -n 999 -l tag-zero-lines >actual &&
+ git diff expect actual
+'
+
+echo 'tag line one' >annotagmsg
+echo 'tag line two' >>annotagmsg
+echo 'tag line three' >>annotagmsg
+test_expect_success \
+ 'listing many message lines of a non-signed tag should succeed' '
+ git-tag -F annotagmsg tag-lines &&
+
+ echo "tag-lines" >expect &&
+ git-tag -l | grep "^tag-lines" >actual &&
+ git diff expect actual &&
+ git-tag -n 0 -l | grep "^tag-lines" >actual &&
+ git diff expect actual &&
+ git-tag -n 0 -l tag-lines >actual &&
+ git diff expect actual &&
+
+ echo "tag-lines tag line one" >expect &&
+ git-tag -n 1 -l | grep "^tag-lines" >actual &&
+ git diff expect actual &&
+ git-tag -n -l | grep "^tag-lines" >actual &&
+ git diff expect actual &&
+ git-tag -n 1 -l tag-lines >actual &&
+ git diff expect actual &&
+
+ echo " tag line two" >>expect &&
+ git-tag -n 2 -l | grep "^ *tag.line" >actual &&
+ git diff expect actual &&
+ git-tag -n 2 -l tag-lines >actual &&
+ git diff expect actual &&
+
+ echo " tag line three" >>expect &&
+ git-tag -n 3 -l | grep "^ *tag.line" >actual &&
+ git diff expect actual &&
+ git-tag -n 3 -l tag-lines >actual &&
+ git diff expect actual &&
+ git-tag -n 4 -l | grep "^ *tag.line" >actual &&
+ git diff expect actual &&
+ git-tag -n 4 -l tag-lines >actual &&
+ git diff expect actual &&
+ git-tag -n 99 -l | grep "^ *tag.line" >actual &&
+ git diff expect actual &&
+ git-tag -n 99 -l tag-lines >actual &&
+ git diff expect actual
+'
+
# trying to verify annotated non-signed tags:
test_expect_success \
@@ -651,6 +751,106 @@ test_expect_success \
git-tag -v commentnonlfile-signed-tag
'
+# listing messages for signed tags:
+
+test_expect_success \
+ 'listing the one-line message of a signed tag should succeed' '
+ git-tag -s -m "A message line signed" stag-one-line &&
+
+ echo "stag-one-line" >expect &&
+ git-tag -l | grep "^stag-one-line" >actual &&
+ git diff expect actual &&
+ git-tag -n 0 -l | grep "^stag-one-line" >actual &&
+ git diff expect actual &&
+ git-tag -n 0 -l stag-one-line >actual &&
+ git diff expect actual &&
+
+ echo "stag-one-line A message line signed" >expect &&
+ git-tag -n xxx -l | grep "^stag-one-line" >actual &&
+ git diff expect actual &&
+ git-tag -n "" -l | grep "^stag-one-line" >actual &&
+ git diff expect actual &&
+ git-tag -n 1 -l | grep "^stag-one-line" >actual &&
+ git diff expect actual &&
+ git-tag -n -l | grep "^stag-one-line" >actual &&
+ git diff expect actual &&
+ git-tag -n 1 -l stag-one-line >actual &&
+ git diff expect actual &&
+ git-tag -n 2 -l stag-one-line >actual &&
+ git diff expect actual &&
+ git-tag -n 999 -l stag-one-line >actual &&
+ git diff expect actual
+'
+
+test_expect_success \
+ 'listing the zero-lines message of a signed tag should succeed' '
+ git-tag -s -m "" stag-zero-lines &&
+
+ echo "stag-zero-lines" >expect &&
+ git-tag -l | grep "^stag-zero-lines" >actual &&
+ git diff expect actual &&
+ git-tag -n 0 -l | grep "^stag-zero-lines" >actual &&
+ git diff expect actual &&
+ git-tag -n 0 -l stag-zero-lines >actual &&
+ git diff expect actual &&
+
+ echo "stag-zero-lines " >expect &&
+ git-tag -n 1 -l | grep "^stag-zero-lines" >actual &&
+ git diff expect actual &&
+ git-tag -n -l | grep "^stag-zero-lines" >actual &&
+ git diff expect actual &&
+ git-tag -n 1 -l stag-zero-lines >actual &&
+ git diff expect actual &&
+ git-tag -n 2 -l stag-zero-lines >actual &&
+ git diff expect actual &&
+ git-tag -n 999 -l stag-zero-lines >actual &&
+ git diff expect actual
+'
+
+echo 'stag line one' >sigtagmsg
+echo 'stag line two' >>sigtagmsg
+echo 'stag line three' >>sigtagmsg
+test_expect_success \
+ 'listing many message lines of a signed tag should succeed' '
+ git-tag -s -F sigtagmsg stag-lines &&
+
+ echo "stag-lines" >expect &&
+ git-tag -l | grep "^stag-lines" >actual &&
+ git diff expect actual &&
+ git-tag -n 0 -l | grep "^stag-lines" >actual &&
+ git diff expect actual &&
+ git-tag -n 0 -l stag-lines >actual &&
+ git diff expect actual &&
+
+ echo "stag-lines stag line one" >expect &&
+ git-tag -n 1 -l | grep "^stag-lines" >actual &&
+ git diff expect actual &&
+ git-tag -n -l | grep "^stag-lines" >actual &&
+ git diff expect actual &&
+ git-tag -n 1 -l stag-lines >actual &&
+ git diff expect actual &&
+
+ echo " stag line two" >>expect &&
+ git-tag -n 2 -l | grep "^ *stag.line" >actual &&
+ git diff expect actual &&
+ git-tag -n 2 -l stag-lines >actual &&
+ git diff expect actual &&
+
+ echo " stag line three" >>expect &&
+ git-tag -n 3 -l | grep "^ *stag.line" >actual &&
+ git diff expect actual &&
+ git-tag -n 3 -l stag-lines >actual &&
+ git diff expect actual &&
+ git-tag -n 4 -l | grep "^ *stag.line" >actual &&
+ git diff expect actual &&
+ git-tag -n 4 -l stag-lines >actual &&
+ git diff expect actual &&
+ git-tag -n 99 -l | grep "^ *stag.line" >actual &&
+ git diff expect actual &&
+ git-tag -n 99 -l stag-lines >actual &&
+ git diff expect actual
+'
+
# tags pointing to objects different from commits:
tree=$(git rev-parse HEAD^{tree})
--
1.5.0
^ permalink raw reply related
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