* Re: git-p4import.py robustness changes
From: Shawn O. Pearce @ 2007-06-04 6:18 UTC (permalink / raw)
To: Dana How; +Cc: Scott Lamb, Simon Hausmann, Junio C Hamano, git
In-Reply-To: <56b7f5510706032309w4aee791dnd3bf5d46974bdaba@mail.gmail.com>
Dana How <danahow@gmail.com> wrote:
> On 6/3/07, Shawn O. Pearce <spearce@spearce.org> wrote:
> >I think writing data to fast-import is much easier than running
> >the raw Git commands, especially when you are talking about an
> >import engine where you need to set all of the special environment
> >variables for git-commit-tree or git-tag to do its job properly.
> >Its a good tool that simply doesn't get enough use, partly because
> >nobody is using it...
>
> Well, perhaps they use it *once*, in that they write a wrapper script for
> it and then forget about it. At least that's what I did. And the _only_
> annoyance was the trailing NL requirement on the delimited "data" statement,
> so you don't get much noise/complaints when people use it.
True. I did try to make fast-import take a simple enough format
that you could write throwaway code against it, run it, and never
look back...
The trailing NL after data was because of cvs2svn. The SVN dump
file format apparently does something like this, and the version
of cvs2svn that Jon Smirl was working on output that trailing NL.
Accepting it in fast-import was easier than fixing cvs2svn to not
create it.
I'll admit the error handling in fast-import could probably
be easier, and that NL after data probably could be optional.
I don't think the input stream parser needs it to understand what
is going on. Its just sheer laziness on my part that the code
requires it there.
--
Shawn.
^ permalink raw reply
* Re: git-p4import.py robustness changes
From: Dana How @ 2007-06-04 6:09 UTC (permalink / raw)
To: Shawn O. Pearce; +Cc: Scott Lamb, Simon Hausmann, Junio C Hamano, git, danahow
In-Reply-To: <20070604055433.GD4507@spearce.org>
On 6/3/07, Shawn O. Pearce <spearce@spearce.org> wrote:
> I think writing data to fast-import is much easier than running
> the raw Git commands, especially when you are talking about an
> import engine where you need to set all of the special environment
> variables for git-commit-tree or git-tag to do its job properly.
> Its a good tool that simply doesn't get enough use, partly because
> nobody is using it...
Well, perhaps they use it *once*, in that they write a wrapper script for
it and then forget about it. At least that's what I did. And the _only_
annoyance was the trailing NL requirement on the delimited "data" statement,
so you don't get much noise/complaints when people use it.
Thanks,
--
Dana L. How danahow@gmail.com +1 650 804 5991 cell
^ permalink raw reply
* Re: [PATCH 1/6] Refactor git tag objects; make "tag" header optional; introduce new optional "keywords" header
From: Matthias Lederhofer @ 2007-06-04 6:08 UTC (permalink / raw)
To: Johan Herland; +Cc: git
In-Reply-To: <200706040252.55152.johan@herland.net>
Johan Herland <johan@herland.net> wrote:
> 1. Make the "tag" header optional. The "tag" header contains the tag name,
> which is optional for 'notes'. The new semantics for the "tag" header
> are as follows: The tag header _must_ be given for signed tags (this
> is already enforced by git-tag.sh). When the tag header is not given,
> its value defaults to the empty string.
Why must signed tags have a tag header? Will notes optionally have a
tag header?
^ permalink raw reply
* Re: Improved git-gui blame viewer
From: Shawn O. Pearce @ 2007-06-04 6:07 UTC (permalink / raw)
To: Matthijs Melchior; +Cc: git
In-Reply-To: <f3rhme$2h9$1@sea.gmane.org>
Matthijs Melchior <mmelchior@xs4all.nl> wrote:
> The colors look much better.
Thank Linus. He's not a user inteface guy, but his idea was actually
pretty good. ;-)
> The behavior has some rough edges. I don't like the following:
> When clicking on a link in the left column, the file as present in
> that commit is loaded, positioned at the top. I would like for the
> line where I clicked is to stay at the same position on the screen,
> so I do not have to find it again.
Me too. Unfortunately I'm fighting with Tk to make this work.
Right now I've got the code written to do this, and I see it happen
internally, but then something causes Tk to reset the viewport back
to the top. Arrrrrrgh. I haven't pushed it out because it doesn't
work.
> Also, when returning I would like most lines on the screen stay the
> same.
Ditto.
> When clicking on a light gray line to become a green line, then
> adjacent areas are not correctly colored. A few adjacent entries
> become all same gray... [Look around git-gui.sh:340]
This (I think) is because of the way the color selections are
being done. git-gui is being stupid and just alternating colors to
commits as they come in from `git blame --incremental`. The thing
about the incremental blame is I can receive data for any part of
the file at any time. So in general what happens is I get data for
one part of the file, give it color A, then data for another part,
give it color B, and then get data for part that is right next to the
first A and assign it A again. So you see chunks where there is no
alternating...
> Something I want for the normal window, in the Staged and Unstaged
> file lists, high-lite the last entry selected so it becomes easy to
> click on the next one and I can see more clearly what is displayed
> in the bottom area.
I'm not sure I understand what you are looking for here. Right now
git-gui should be inverting the foreground/background colors on
the file that is "selected" (shown in the lower diff view pane).
So the background should be black, and the foreground white.
Is this not happening? Or are you looking for something else?
--
Shawn.
^ permalink raw reply
* Re: [PATCH 3/6] git-fsck: Do thorough verification of tag objects.
From: Matthias Lederhofer @ 2007-06-04 5:56 UTC (permalink / raw)
To: Johan Herland; +Cc: git
In-Reply-To: <200706040253.51920.johan@herland.net>
Johan Herland <johan@herland.net> wrote:
> diff --git a/builtin-fsck.c b/builtin-fsck.c
> index cbbcaf0..a8914ae 100644
> --- a/builtin-fsck.c
> +++ b/builtin-fsck.c
> @@ -344,6 +344,20 @@ static int fsck_commit(struct commit *commit)
> static int fsck_tag(struct tag *tag)
> {
> struct object *tagged = tag->tagged;
> + enum object_type type;
> + unsigned long size;
> + char *data = (char *) read_sha1_file(tag->object.sha1, &type, &size);
> + if (!data)
> + return error("Could not read tag %s", sha1_to_hex(tag->object.sha1));
> + if (type != OBJ_TAG) {
> + free(data);
> + return error("Internal error: Tag %s not a tag", sha1_to_hex(tag->object.sha1));
> + }
> + if (parse_and_verify_tag_buffer(0, data, size, 1)) { /* Thoroughly verify tag object */
> + free(data);
> + return error("Tag %s failed thorough tag object verification", sha1_to_hex(tag->object.sha1));
> + }
> + free(data);
>
> if (!tagged) {
> return objerror(&tag->object, "could not load tagged object");
The objerror() function prints the sha1 and object type, I think this
one should be used instead of error() here.
^ permalink raw reply
* Re: git-p4import.py robustness changes
From: Shawn O. Pearce @ 2007-06-04 5:56 UTC (permalink / raw)
To: Simon Hausmann; +Cc: Junio C Hamano, git
In-Reply-To: <200706031511.31157.simon@lst.de>
Simon Hausmann <simon@lst.de> wrote:
> On the topic of git integration with perforce, what are the chances of getting
> git-p4 ( http://repo.or.cz/w/fast-export.git ) into git's contrib/fast-export
> area? :)
>
> git-p4 can do everything git-p4import can do plus a lot more (it can track
> multiple branches, it's a hell of a lot faster, it can export back to p4 and
> it also works on Windows!).
I was sort of hoping we could fold the fast-export Git repository
on repo.or.cz into core Git at some point. Right now the only
thing in contrib/fast-export is the import-tars.perl script that
I maintain in my fastimport repository... ;-)
Like Junio I don't use Perforce, and can't test against it, but
if you can maintain git-p4 (and I think the history on repo.or.cz
shows that you do) then it may be a good idea to add it to core Git.
Send a patch to add it. Worst that happens is both Junio and I
decide not to apply it. Or I apply it, but Junio refuses to pull
from me afterwards. ;-)
--
Shawn.
^ permalink raw reply
* Re: [PATCH 1/2] gitview: Use new-style classes
From: Michael Ellerman @ 2007-06-04 5:54 UTC (permalink / raw)
To: Junio C Hamano; +Cc: aneesh.kumar, git
In-Reply-To: <7vsl9awva8.fsf@assigned-by-dhcp.cox.net>
[-- Attachment #1: Type: text/plain, Size: 2052 bytes --]
On Sat, 2007-06-02 at 02:38 -0700, Junio C Hamano wrote:
> Michael Ellerman <michael@ellerman.id.au> writes:
>
> > Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
>
> Aneesh, this one is in your bailiwick.
>
> Michael, it would have been nicer to have a real log message,
> not just the Subject line, in your message. The Subject line
> says what the patch does in what subarea of the git.git tree,
> which is very appropriate, but that can be seen from the diff
> even if you did not say so. The log message (before your
> Signed-off-by line) is where you describe _why_ you would think
> it is a good change. "What" and "how" are usually evident in
> well written code without much explanation, but "why" is often
> more useful when reviewing the patch, and reading and studying
> the history of the code.
>
> I would have written something like:
>
> This changes the Commit class to use new-style class,
> which has been available since Python 2.2 (Dec 2001).
> This is a necessary step in order to use __slots__
> declaration so that we can reduce the memory footprint
> with my next patch.
>
> I have no strong preference on this change myself. "Classes
> that derive from type" are relatively recent invention but I
> would personally feel that Python 2.2 is ancient enough that
> using it would not pose any practical portability issues, but
> what would I know...
Hi Junio,
Why write my own changelog when you do such a good job! ;)
But seriously, sorry about that. It was a case of me hacking on my local
git tree, not thinking anything would come of it, and then when I saw
the memory reduction from using __slots__ I decided to send off what I'd
done. I should have reset and recommitted with a decent changelog.
cheers
--
Michael Ellerman
OzLabs, IBM Australia Development Lab
wwweb: http://michael.ellerman.id.au
phone: +61 2 6212 1183 (tie line 70 21183)
We do not inherit the earth from our ancestors,
we borrow it from our children. - S.M.A.R.T Person
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply
* Re: git-p4import.py robustness changes
From: Shawn O. Pearce @ 2007-06-04 5:54 UTC (permalink / raw)
To: Scott Lamb; +Cc: Simon Hausmann, Junio C Hamano, git
In-Reply-To: <839AEF71-ED29-4A79-BE97-C79EAFEDC466@slamb.org>
Scott Lamb <slamb@slamb.org> wrote:
> On Jun 3, 2007, at 6:11 AM, Simon Hausmann wrote:
> >On the topic of git integration with perforce, what are the chances
> >of getting
> >git-p4 ( http://repo.or.cz/w/fast-export.git ) into git's contrib/
> >fast-export
> >area? :)
>
> I missed that one...I just saw Tailor and the Perl script someone
> else had written.
Perhaps why it should be in contrib/fast-import? ;-)
> As for performance...hmm. Looks like git-p4import.py runs these
> commands for each Perforce revision:
>
> realtime operation
> 3.4% p4 describe -s N
> 66.6% p4 sync ...@N
> [*] 10.2% git ls-files -m -d -o -z | git update-index --add --
> remove -z --stdin
> 2.6% git rev-parse --verify HEAD
> 4.2% git write-tree
> 2.8% git commit-tree xxxxxx
> 7.5% git tag -f p4/N xxxxxx
> 2.7% git update-ref HEAD xxxxxx
...
> git-p4 seems to use "git fast-import". I guess the big performance
> improvement there is removing the ls-files operation? So we're
> talking about a 0-10% speedup, right? Plus some fork()/exec() overhead.
fast-import folds all of the git commands you list above behind
a single engine that is *fast*. So its actually a 0-30% gain
that is available by using the fast-import backend, with a single
fork()/exec() for the *entire import*. The local object IO performed
by Git is also minimized, so large imports have much better IO
behavior from the Git perspective. Its not something to sneeze at.
fast-import also can run in parallel with the frontend process,
allowing you to use a dual-core system, to the extent that your
disk(s) and network can keep up. Generally p4 is going to be
the bottleneck.
I think writing data to fast-import is much easier than running
the raw Git commands, especially when you are talking about an
import engine where you need to set all of the special environment
variables for git-commit-tree or git-tag to do its job properly.
Its a good tool that simply doesn't get enough use, partly because
nobody is using it...
--
Shawn.
^ permalink raw reply
* Re: [PATCH] Support environment variables in config file
From: Matthias Lederhofer @ 2007-06-04 5:34 UTC (permalink / raw)
To: Martin Waitz; +Cc: git
In-Reply-To: <20070603223727.GA16637@admingilde.org>
Martin Waitz <tali@admingilde.org> wrote:
> Environment variables (e.g. $HOME) can be helpful for the GIT configuration.
> With this change you can use them with the normal shell "$" syntax.
> If you want to insert a plain "$" in a variable, it can be escaped as \$
> or put inside quotes (").
Perhaps we should also allow variable interpolation in double quoted
strings as this is quite common in various languages.
> diff --git a/Documentation/config.txt b/Documentation/config.txt
> index 5868d58..042a354 100644
> --- a/Documentation/config.txt
> +++ b/Documentation/config.txt
> @@ -65,17 +65,24 @@ a string, an integer, or a boolean. Boolean values may be given as yes/no,
> converting value to the canonical form using '--bool' type specifier;
> `git-config` will ensure that the output is "true" or "false".
>
> +You can use the $VARIABLE shell syntax to use environment variables
> +in the configuration file. All alpha-numeric characters after the
> +leading '`$`' will be interpreted as name of an environment variable
> +and the value of this variable will be used instead.
> +If the variable does not exist it will be treated as an empty string.
We could have a short example here how to concatenate a variable and a
string without a space in between. I came up with '$FOO""bar' which
is not that obvious imo.
> diff --git a/config.c b/config.c
> index 0614c2b..058c0df 100644
> --- a/config.c
> +++ b/config.c
> @@ -43,12 +43,27 @@ static int get_next_char(void)
> static char *parse_value(void)
> {
> static char value[1024];
> - int quote = 0, comment = 0, len = 0, space = 0;
> + int quote = 0, comment = 0, envvar = -1, len = 0, space = 0;
>
> for (;;) {
> int c = get_next_char();
> if (len >= sizeof(value))
> return NULL;
> + if ((envvar >= 0) && !isalnum(c)) {
You should allow at least underscores in environment variables too.
> diff --git a/t/t1300-repo-config.sh b/t/t1300-repo-config.sh
> index 3f3fd2d..eb84437 100755
> --- a/t/t1300-repo-config.sh
> +++ b/t/t1300-repo-config.sh
> @@ -513,5 +513,18 @@ git config --list > result
>
> test_expect_success 'value continued on next line' 'cmp result expect'
>
> +cat > .git/config <<\EOF
> +[quoted]
> + withvar = "$HOME/foo"
> +[unquoted]
> + withvar = $HOME/foo
> +EOF
> +
> +test_expect_success 'quoted $VAR' \
> + 'test x"\$HOME/foo" = x$(git config quoted.withvar)'
> +
> +test_expect_success 'unquoted $VAR' \
> + 'test x"$HOME/foo" = x$(git config unquoted.withvar)'
> +
> test_done
If you use the HOME environment variable without setting it yourself
you should place quotes around the $(..) in case there is a space in
$HOME:
$ ./git-config test.var '$HOME'
$ export HOME='/tmp/foo bar'
$ ./git-config test.var
/tmp/foo bar
$ test x"$HOME/foo" = x$(./git-config test.var)
test: 4: bar: unexpected operator
$ test x"$HOME/foo" = x"$(./git-config test.var)"
^ permalink raw reply
* git submodule init
From: Aneesh Kumar @ 2007-06-04 4:47 UTC (permalink / raw)
To: Git Mailing List
Hi,
I guess git submodule init should support different options for
cloning such as -l -s --reference etc.
-aneesh
^ permalink raw reply
* [PATCH 6/6] Add fsck_verify_ref_to_tag_object() to verify that refname matches name stored in tag object
From: Johan Herland @ 2007-06-04 0:54 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano
In-Reply-To: <200706040251.52613.johan@herland.net>
On Monday 28 May 2007, Junio C Hamano wrote:
> However it would be a good
> idea to add logic to fsck to warn upon inconsistencis (perhaps
> by mistake) between refname and tag's true name.
>
> The check would say something like:
>
> If an annotated (signed or unsigned) tag has a "tag"
> line to give it the official $name, and if it is pointed
> at by a ref, the refname must end with "/$name".
> Otherwise we warn.
>
> Trivially, the above rule says that having v2.6.22 tag under
> refs/tags/v2.6.20 is a mistake we would want to be warned upon.
This patch adds the check described by Junio.
Signed-off-by: Johan Herland <johan@herland.net>
---
builtin-fsck.c | 21 +++++++++++++++++++++
1 files changed, 21 insertions(+), 0 deletions(-)
diff --git a/builtin-fsck.c b/builtin-fsck.c
index a8914ae..379317e 100644
--- a/builtin-fsck.c
+++ b/builtin-fsck.c
@@ -515,6 +515,25 @@ static int fsck_handle_reflog(const char *logname, const unsigned char *sha1, in
return 0;
}
+static void fsck_verify_ref_to_tag_object(const char *refname, struct object *obj)
+{
+ /* Verify that refname matches the name stored in obj's "tag" header */
+ struct tag *tagobj = (struct tag *) parse_object(obj->sha1);
+ size_t tagname_len = strlen(tagobj->tag);
+ size_t refname_len = strlen(refname);
+
+ if (!tagname_len) return; /* No tag name stored in tagobj. Nothing to do. */
+
+ if (tagname_len < refname_len &&
+ !memcmp(tagobj->tag, refname + (refname_len - tagname_len), tagname_len) &&
+ refname[(refname_len - tagname_len) - 1] == '/') {
+ /* OK: tag name is "$name", and refname ends with "/$name" */
+ return;
+ }
+ else
+ error("%s: Mismatch between tag ref and tag object's name %s", refname, tagobj->tag);
+}
+
static int fsck_handle_ref(const char *refname, const unsigned char *sha1, int flag, void *cb_data)
{
struct object *obj;
@@ -529,6 +548,8 @@ static int fsck_handle_ref(const char *refname, const unsigned char *sha1, int f
/* We'll continue with the rest despite the error.. */
return 0;
}
+ if (obj->type == OBJ_TAG) /* ref to tag object */
+ fsck_verify_ref_to_tag_object(refname, obj);
default_refs++;
obj->used = 1;
mark_reachable(obj, REACHABLE);
--
1.5.2
^ permalink raw reply related
* [PATCH 5/6] git-mktag tests: Fix and expand the mktag tests according to the new tag object structure
From: Johan Herland @ 2007-06-04 0:54 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano
In-Reply-To: <200706040251.52613.johan@herland.net>
The existing tests are updated to reflect the changes in the tag object.
Additionally some more tests are added to test the new "keywords" header,
and to test the more thorough verification routine.
Signed-off-by: Johan Herland <johan@herland.net>
---
t/t3800-mktag.sh | 204 ++++++++++++++++++++++++++++++++++++++++++++++++++----
1 files changed, 190 insertions(+), 14 deletions(-)
diff --git a/t/t3800-mktag.sh b/t/t3800-mktag.sh
index 7c7e433..f6e3d10 100755
--- a/t/t3800-mktag.sh
+++ b/t/t3800-mktag.sh
@@ -34,7 +34,7 @@ too short for a tag
EOF
cat >expect.pat <<EOF
-^error: .*size wrong.*$
+^error: .* size .*$
EOF
check_verify_failure 'Tag object length check'
@@ -46,6 +46,8 @@ cat >tag.sig <<EOF
xxxxxx 139e9b33986b1c2670fff52c5067603117b3e895
type tag
tag mytag
+tagger foo
+
EOF
cat >expect.pat <<EOF
@@ -61,6 +63,8 @@ cat >tag.sig <<EOF
object zz9e9b33986b1c2670fff52c5067603117b3e895
type tag
tag mytag
+tagger foo
+
EOF
cat >expect.pat <<EOF
@@ -76,6 +80,8 @@ cat >tag.sig <<EOF
object 779e9b33986b1c2670fff52c5067603117b3e895
xxxx tag
tag mytag
+tagger foo
+
EOF
cat >expect.pat <<EOF
@@ -91,7 +97,7 @@ echo "object 779e9b33986b1c2670fff52c5067603117b3e895" >tag.sig
printf "type tagsssssssssssssssssssssssssssssss" >>tag.sig
cat >expect.pat <<EOF
-^error: char48: .*"[\]n"$
+^error: char48: .*"[\]n" after "type"$
EOF
check_verify_failure '"type" line eol check'
@@ -103,10 +109,12 @@ cat >tag.sig <<EOF
object 779e9b33986b1c2670fff52c5067603117b3e895
type tag
xxx mytag
+tagger foo
+
EOF
cat >expect.pat <<EOF
-^error: char57: no "tag " found$
+^error: char57: .*$
EOF
check_verify_failure '"tag" line label check #1'
@@ -118,21 +126,27 @@ cat >tag.sig <<EOF
object 779e9b33986b1c2670fff52c5067603117b3e895
type taggggggggggggggggggggggggggggggg
tag
+keywords foo
+tagger bar@baz.com
+
EOF
cat >expect.pat <<EOF
-^error: char87: no "tag " found$
+^error: char87: .*$
EOF
check_verify_failure '"tag" line label check #2'
############################################################
-# 8. type line type-name length check
+# 8. type line type name length check
cat >tag.sig <<EOF
object 779e9b33986b1c2670fff52c5067603117b3e895
type taggggggggggggggggggggggggggggggg
tag mytag
+keywords foo
+tagger bar@baz.com
+
EOF
cat >expect.pat <<EOF
@@ -148,6 +162,9 @@ cat >tag.sig <<EOF
object 779e9b33986b1c2670fff52c5067603117b3e895
type tagggg
tag mytag
+keywords foo
+tagger bar@baz.com
+
EOF
cat >expect.pat <<EOF
@@ -157,12 +174,15 @@ EOF
check_verify_failure 'verify object (SHA1/type) check'
############################################################
-# 10. verify tag-name check
+# 10. verify tag name check
cat >tag.sig <<EOF
object $head
type commit
tag my tag
+keywords foo
+tagger bar@baz.com
+
EOF
cat >expect.pat <<EOF
@@ -172,56 +192,212 @@ EOF
check_verify_failure 'verify tag-name check'
############################################################
-# 11. tagger line label check #1
+# 11. keywords line label check #1
+
+cat >tag.sig <<EOF
+object $head
+type commit
+tag mytag
+xxxxxxxx foo
+tagger bar@baz.com
+
+EOF
+
+cat >expect.pat <<EOF
+^error: char70: .*$
+EOF
+
+check_verify_failure '"keywords" line label check #1'
+
+############################################################
+# 12. keywords line label check #2
+
+cat >tag.sig <<EOF
+object $head
+type commit
+tag mytag
+keywords
+tagger bar@baz.com
+
+EOF
+
+cat >expect.pat <<EOF
+^error: char70: .*$
+EOF
+
+check_verify_failure '"keywords" line label check #2'
+
+############################################################
+# 13. keywords line check #1
+
+cat >tag.sig <<EOF
+object $head
+type commit
+tag mytag
+keywords foo bar baz
+tagger bar@baz.com
+
+EOF
+
+cat >expect.pat <<EOF
+^error: char83: .*$
+EOF
+
+check_verify_failure '"keywords" line check #1'
+
+############################################################
+# 14. keywords line check #2
+
+cat >tag.sig <<EOF
+object $head
+type commit
+tag mytag
+keywords foo,bar baz
+tagger bar@baz.com
+
+EOF
+
+cat >expect.pat <<EOF
+^error: char87: .*$
+EOF
+
+check_verify_failure '"keywords" line check #2'
+
+############################################################
+# 15. keywords line check #3
+
+cat >tag.sig <<EOF
+object $head
+type commit
+tag mytag
+keywords foo,,bar
+tagger bar@baz.com
+
+EOF
+
+cat >expect.pat <<EOF
+^error: char83: .*$
+EOF
+
+check_verify_failure '"keywords" line check #3'
+
+############################################################
+# 16. tagger line label check #1
cat >tag.sig <<EOF
object $head
type commit
tag mytag
+
EOF
cat >expect.pat <<EOF
-^error: char70: could not find "tagger"$
+^error: char70: .*$
EOF
check_verify_failure '"tagger" line label check #1'
############################################################
-# 12. tagger line label check #2
+# 17. tagger line label check #2
cat >tag.sig <<EOF
object $head
type commit
tag mytag
-tagger
+xxxxxx bar@baz.com
+
EOF
cat >expect.pat <<EOF
-^error: char70: could not find "tagger"$
+^error: char70: .*$
EOF
check_verify_failure '"tagger" line label check #2'
############################################################
-# 13. create valid tag
+# 18. tagger line label check #3
+
+cat >tag.sig <<EOF
+object $head
+type commit
+tag mytag
+keywords foo
+tagger
+
+EOF
+
+cat >expect.pat <<EOF
+^error: char83: .*$
+EOF
+
+check_verify_failure '"tagger" line label check #3'
+
+############################################################
+# 19. create valid tag #1
cat >tag.sig <<EOF
object $head
type commit
tag mytag
tagger another@example.com
+
EOF
test_expect_success \
- 'create valid tag' \
+ 'create valid tag #1' \
'git-mktag <tag.sig >.git/refs/tags/mytag 2>message'
############################################################
-# 14. check mytag
+# 20. check mytag
test_expect_success \
'check mytag' \
'git-tag -l | grep mytag'
+############################################################
+# 21. create valid tag #2
+
+cat >tag.sig <<EOF
+object $head
+type commit
+tagger another@example.com
+
+EOF
+
+test_expect_success \
+ 'create valid tag #2' \
+ 'git-mktag <tag.sig >.git/refs/tags/mytag 2>message'
+
+############################################################
+# 22. create valid tag #3
+
+cat >tag.sig <<EOF
+object $head
+type commit
+keywords foo,bar,baz,spam,spam,spam,spam,spam,spam,spam,spam
+tagger another@example.com
+
+EOF
+
+test_expect_success \
+ 'create valid tag #3' \
+ 'git-mktag <tag.sig >.git/refs/tags/mytag 2>message'
+
+############################################################
+# 23. create valid tag #4
+
+cat >tag.sig <<EOF
+object $head
+type commit
+tag mytag
+keywords note
+tagger another@example.com
+
+EOF
+
+test_expect_success \
+ 'create valid tag #4' \
+ 'git-mktag <tag.sig >.git/refs/tags/mytag 2>message'
+
test_done
--
1.5.2
^ permalink raw reply related
* [PATCH 4/6] Documentation/git-mktag: Document the changes in tag object structure
From: Johan Herland @ 2007-06-04 0:54 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano
In-Reply-To: <200706040251.52613.johan@herland.net>
The new structure of tag objects is documented.
Also some much-needed cleanup is done. E.g. remove the paragraph on the
8kB limit, since this limit was removed ages ago.
Signed-off-by: Johan Herland <johan@herland.net>
---
Documentation/git-mktag.txt | 42 ++++++++++++++++++++++++++++++------------
1 files changed, 30 insertions(+), 12 deletions(-)
diff --git a/Documentation/git-mktag.txt b/Documentation/git-mktag.txt
index 2860a3d..411105d 100644
--- a/Documentation/git-mktag.txt
+++ b/Documentation/git-mktag.txt
@@ -8,40 +8,58 @@ git-mktag - Creates a tag object
SYNOPSIS
--------
-'git-mktag' < signature_file
+[verse]
+'git-mktag' < tag_data_file
+
DESCRIPTION
-----------
-Reads a tag contents on standard input and creates a tag object
+Reads tag object data on standard input and creates a tag object
that can also be used to sign other objects.
The output is the new tag's <object> identifier.
-Tag Format
+
+DISCUSSION
----------
-A tag signature file has a very simple fixed format: three lines of
+Tag object data has the following format
+[verse]
object <sha1>
type <typename>
- tag <tagname>
+ tag <tagname> (optional)
+ keywords <keywords> (optional)
+ tagger <committer>
+
+followed by a blank line and a free-form message and an optional signature
+that git itself doesn't care about, but that may be verified with gpg or
+similar.
-followed by some 'optional' free-form signature that git itself
-doesn't care about, but that can be verified with gpg or similar.
+In the above listing, `<sha1>` represents the object pointed to by this tag,
+`<typename>` is the type of the object pointed to ("tag", "blob", "tree" or
+"commit"), `<tagname>` is the name of this tag object (and must correspond
+to the name of the corresponding ref (if any) in `.git/refs/`). `<keywords>`
+is a comma-separated list of keywords associated with this tag object, and
+`<committer>` holds the "`name <email>`" of the tag creator and timestamp
+of when the tag object was created (analogous to "committer" in commit
+objects).
-The size of the full object is artificially limited to 8kB. (Just
-because I'm a lazy bastard, and if you can't fit a signature in that
-size, you're doing something wrong)
+If "`tag <tagname>`" is omitted, <tagname> defaults to the empty string.
+If "`keywords <keywords>`" is omitted, <keywords> defaults to "`tag`" if
+a <tagname> was given, "`note`" otherwise.
Author
------
Written by Linus Torvalds <torvalds@osdl.org>
+
Documentation
--------------
-Documentation by David Greaves, Junio C Hamano and the git-list <git@vger.kernel.org>.
+Documentation by Johan Herland, David Greaves, Junio C Hamano and the
+git-list <git@vger.kernel.org>.
+
GIT
---
Part of the gitlink:git[7] suite
-
--
1.5.2
^ permalink raw reply related
* [PATCH 3/6] git-fsck: Do thorough verification of tag objects.
From: Johan Herland @ 2007-06-04 0:53 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano
In-Reply-To: <200706040251.52613.johan@herland.net>
Teach git-fsck to do the same kind of verification on tag objects that is
already done by git-mktag.
Signed-off-by: Johan Herland <johan@herland.net>
---
builtin-fsck.c | 14 ++++++++++++++
1 files changed, 14 insertions(+), 0 deletions(-)
diff --git a/builtin-fsck.c b/builtin-fsck.c
index cbbcaf0..a8914ae 100644
--- a/builtin-fsck.c
+++ b/builtin-fsck.c
@@ -344,6 +344,20 @@ static int fsck_commit(struct commit *commit)
static int fsck_tag(struct tag *tag)
{
struct object *tagged = tag->tagged;
+ enum object_type type;
+ unsigned long size;
+ char *data = (char *) read_sha1_file(tag->object.sha1, &type, &size);
+ if (!data)
+ return error("Could not read tag %s", sha1_to_hex(tag->object.sha1));
+ if (type != OBJ_TAG) {
+ free(data);
+ return error("Internal error: Tag %s not a tag", sha1_to_hex(tag->object.sha1));
+ }
+ if (parse_and_verify_tag_buffer(0, data, size, 1)) { /* Thoroughly verify tag object */
+ free(data);
+ return error("Tag %s failed thorough tag object verification", sha1_to_hex(tag->object.sha1));
+ }
+ free(data);
if (!tagged) {
return objerror(&tag->object, "could not load tagged object");
--
1.5.2
^ permalink raw reply related
* [PATCH 2/6] git-show: When showing tag objects with no tag name, show tag object's SHA1 instead of an empty string
From: Johan Herland @ 2007-06-04 0:53 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano
In-Reply-To: <200706040251.52613.johan@herland.net>
This is a consequence of making the "tag" header in tag objects optional.
Signed-off-by: Johan Herland <johan@herland.net>
---
builtin-log.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/builtin-log.c b/builtin-log.c
index 3744712..1a0f111 100644
--- a/builtin-log.c
+++ b/builtin-log.c
@@ -181,7 +181,7 @@ int cmd_show(int argc, const char **argv, const char *prefix)
printf("%stag %s%s\n\n",
diff_get_color(rev.diffopt.color_diff,
DIFF_COMMIT),
- t->tag,
+ *(t->tag) ? t->tag : name,
diff_get_color(rev.diffopt.color_diff,
DIFF_RESET));
ret = show_object(o->sha1, 1);
--
1.5.2
^ permalink raw reply related
* [PATCH 1/6] Refactor git tag objects; make "tag" header optional; introduce new optional "keywords" header
From: Johan Herland @ 2007-06-04 0:52 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano
In-Reply-To: <200706040251.52613.johan@herland.net>
In order to support ref-less tag objects (aka. 'notes'), we want to do
some changes to the tag object structure. The new structure implemented
in this patch is backward-compatible in the way that all existing tag
objects (valid in the old implementation) will remain valid in the new
implementation. The following changes are done:
1. Make the "tag" header optional. The "tag" header contains the tag name,
which is optional for 'notes'. The new semantics for the "tag" header
are as follows: The tag header _must_ be given for signed tags (this
is already enforced by git-tag.sh). When the tag header is not given,
its value defaults to the empty string.
2. Introduce a new optional "keywords" header. The "keywords" header is a
comma-separated list of free-form values. However, two certain value
have special meaning: "tag" and "note": When the "keywords" header is
missing, its default value is set to "tag" if a "tag" header is
present; else the default "keywords" value is set to "note". The
"keywords" header is meant to be used by porcelains for classifying
different types of tag objects. This classification may then be used to
filter tag objects in the presentation layer (e.g. by implementing
extra filter options to --decorate, etc.)
3. Make the "tagger" header mandatory. This header has already for a long
time been "de facto" mandatory, in that it is automatically generated
by git-tag.sh. This patch verifies the existence of the header when
creating tag objects. However, since there exists old tags without
the "tagger" header, the verification should not be done when parsing
tag objects.
4. Consolidate the parsing and verification of tag objects. Currently
parsing is done in tag.c:parse_tag_buffer(), and verification is done
with a very similar piece of code in mktag.c:verify_tag(). This patch
unifies the parsing and verification of tag objects in a new function
parse_and_verify_tag_buffer() which is then called from the other
places.
Signed-off-by: Johan Herland <johan@herland.net>
---
mktag.c | 148 ++++++++---------------------------
tag.c | 266 +++++++++++++++++++++++++++++++++++++++++++++++++++------------
tag.h | 4 +-
3 files changed, 251 insertions(+), 167 deletions(-)
diff --git a/mktag.c b/mktag.c
index 9310111..cde6036 100644
--- a/mktag.c
+++ b/mktag.c
@@ -2,128 +2,42 @@
#include "tag.h"
/*
- * A signature file has a very simple fixed format: four lines
- * of "object <sha1>" + "type <typename>" + "tag <tagname>" +
+ * Tag object data has the following format: two mandatory lines of
+ * "object <sha1>" + "type <typename>", plus two optional lines of
+ * "tag <tagname>" + "keywords <keywords>", plus a mandatory line of
* "tagger <committer>", followed by a blank line, a free-form tag
- * message and a signature block that git itself doesn't care about,
- * but that can be verified with gpg or similar.
+ * message and an optional signature block that git itself doesn't
+ * care about, but that can be verified with gpg or similar.
*
- * The first three lines are guaranteed to be at least 63 bytes:
- * "object <sha1>\n" is 48 bytes, "type tag\n" at 9 bytes is the
- * shortest possible type-line, and "tag .\n" at 6 bytes is the
- * shortest single-character-tag line.
+ * <sha1> represents the object pointed to by this tag, <typename> is
+ * the type of the object pointed to ("tag", "blob", "tree" or "commit"),
+ * <tagname> is the name of this tag object (and must correspond to the
+ * name of the corresponding ref (if any) in '.git/refs/'). <keywords> is
+ * a comma-separated list of keywords associated with this tag object, and
+ * <committer> holds the "name <email>" of the tag creator and timestamp
+ * of when the tag object was created (analogous to "committer" in commit
+ * objects).
*
- * We also artificially limit the size of the full object to 8kB.
- * Just because I'm a lazy bastard, and if you can't fit a signature
- * in that size, you're doing something wrong.
- */
-
-/* Some random size */
-#define MAXSIZE (8192)
-
-/*
- * We refuse to tag something we can't verify. Just because.
+ * The first two lines are guaranteed to be at least 57 bytes:
+ * "object <sha1>\n" is 48 bytes, and "type tag\n" at 9 bytes is
+ * the shortest possible "type" line. The tagger line is at least
+ * "tagger \n" (8 bytes), and a blank line is also needed (1 byte).
+ * Therefore a tag object _must_ have >= 66 bytes.
+ *
+ * If "tag <tagname>" is omitted, <tagname> defaults to the empty string.
+ * If "keywords <keywords>" is omitted, <keywords> defaults to "tag" if
+ * a <tagname> was given, "note" otherwise.
*/
-static int verify_object(unsigned char *sha1, const char *expected_type)
-{
- int ret = -1;
- enum object_type type;
- unsigned long size;
- void *buffer = read_sha1_file(sha1, &type, &size);
-
- if (buffer) {
- if (type == type_from_string(expected_type))
- ret = check_sha1_signature(sha1, buffer, size, expected_type);
- free(buffer);
- }
- return ret;
-}
-
-#ifdef NO_C99_FORMAT
-#define PD_FMT "%d"
-#else
-#define PD_FMT "%td"
-#endif
-
-static int verify_tag(char *buffer, unsigned long size)
-{
- int typelen;
- char type[20];
- unsigned char sha1[20];
- const char *object, *type_line, *tag_line, *tagger_line;
-
- if (size < 64)
- return error("wanna fool me ? you obviously got the size wrong !");
-
- buffer[size] = 0;
-
- /* Verify object line */
- object = buffer;
- if (memcmp(object, "object ", 7))
- return error("char%d: does not start with \"object \"", 0);
-
- if (get_sha1_hex(object + 7, sha1))
- return error("char%d: could not get SHA1 hash", 7);
-
- /* Verify type line */
- type_line = object + 48;
- if (memcmp(type_line - 1, "\ntype ", 6))
- return error("char%d: could not find \"\\ntype \"", 47);
-
- /* Verify tag-line */
- tag_line = strchr(type_line, '\n');
- if (!tag_line)
- return error("char" PD_FMT ": could not find next \"\\n\"", type_line - buffer);
- tag_line++;
- if (memcmp(tag_line, "tag ", 4) || tag_line[4] == '\n')
- return error("char" PD_FMT ": no \"tag \" found", tag_line - buffer);
-
- /* Get the actual type */
- typelen = tag_line - type_line - strlen("type \n");
- if (typelen >= sizeof(type))
- return error("char" PD_FMT ": type too long", type_line+5 - buffer);
-
- memcpy(type, type_line+5, typelen);
- type[typelen] = 0;
-
- /* Verify that the object matches */
- if (verify_object(sha1, type))
- return error("char%d: could not verify object %s", 7, sha1_to_hex(sha1));
-
- /* Verify the tag-name: we don't allow control characters or spaces in it */
- tag_line += 4;
- for (;;) {
- unsigned char c = *tag_line++;
- if (c == '\n')
- break;
- if (c > ' ')
- continue;
- return error("char" PD_FMT ": could not verify tag name", tag_line - buffer);
- }
-
- /* Verify the tagger line */
- tagger_line = tag_line;
-
- if (memcmp(tagger_line, "tagger", 6) || (tagger_line[6] == '\n'))
- return error("char" PD_FMT ": could not find \"tagger\"", tagger_line - buffer);
-
- /* TODO: check for committer info + blank line? */
- /* Also, the minimum length is probably + "tagger .", or 63+8=71 */
-
- /* The actual stuff afterwards we don't care about.. */
- return 0;
-}
-
-#undef PD_FMT
int main(int argc, char **argv)
{
unsigned long size = 4096;
char *buffer = xmalloc(size);
+ struct tag result_tag;
unsigned char result_sha1[20];
if (argc != 1)
- usage("git-mktag < signaturefile");
+ usage("git-mktag < tag_data_file");
setup_git_directory();
@@ -132,16 +46,18 @@ int main(int argc, char **argv)
die("could not read from stdin");
}
- /* Verify it for some basic sanity: it needs to start with
- "object <sha1>\ntype\ntagger " */
- if (verify_tag(buffer, size) < 0)
- die("invalid tag signature file");
+ /* Verify tag object data */
+ if (parse_and_verify_tag_buffer(&result_tag, buffer, size, 1)) {
+ free(buffer);
+ die("invalid tag data file");
+ }
- if (write_sha1_file(buffer, size, tag_type, result_sha1) < 0)
+ if (write_sha1_file(buffer, size, tag_type, result_sha1) < 0) {
+ free(buffer);
die("unable to write tag file");
+ }
free(buffer);
-
printf("%s\n", sha1_to_hex(result_sha1));
return 0;
}
diff --git a/tag.c b/tag.c
index bbacd59..9c95e0b 100644
--- a/tag.c
+++ b/tag.c
@@ -33,65 +33,231 @@ struct tag *lookup_tag(const unsigned char *sha1)
return (struct tag *) obj;
}
-int parse_tag_buffer(struct tag *item, void *data, unsigned long size)
+/*
+ * We refuse to tag something we can't verify. Just because.
+ */
+static int verify_object(unsigned char *sha1, const char *expected_type)
+{
+ int ret = -1;
+ enum object_type type;
+ unsigned long size;
+ void *buffer = read_sha1_file(sha1, &type, &size);
+
+ if (buffer) {
+ if (type == type_from_string(expected_type))
+ ret = check_sha1_signature(sha1, buffer, size, expected_type);
+ free(buffer);
+ }
+ return ret;
+}
+
+/*
+ * Perform parsing and verification of tag object data.
+ *
+ * The 'item' parameter may be set to NULL if only verification is desired.
+ */
+int parse_and_verify_tag_buffer(struct tag *item, const char *data, const unsigned long size, int thorough_verify)
{
- int typelen, taglen;
+#ifdef NO_C99_FORMAT
+#define PD_FMT "%d"
+#else
+#define PD_FMT "%td"
+#endif
+
unsigned char sha1[20];
- const char *type_line, *tag_line, *sig_line;
char type[20];
+ const char *type_line, *tag_line, *keywords_line, *tagger_line;
+ unsigned long type_len, tag_len, keywords_len, tagger_len;
+ const char *header_end, *end = data + size;
- if (item->object.parsed)
- return 0;
- item->object.parsed = 1;
-
- if (size < 64)
- return -1;
- if (memcmp("object ", data, 7) || get_sha1_hex((char *) data + 7, sha1))
- return -1;
-
- type_line = (char *) data + 48;
- if (memcmp("\ntype ", type_line-1, 6))
- return -1;
-
- tag_line = strchr(type_line, '\n');
- if (!tag_line || memcmp("tag ", ++tag_line, 4))
- return -1;
-
- sig_line = strchr(tag_line, '\n');
- if (!sig_line)
- return -1;
- sig_line++;
-
- typelen = tag_line - type_line - strlen("type \n");
- if (typelen >= 20)
- return -1;
- memcpy(type, type_line + 5, typelen);
- type[typelen] = '\0';
- taglen = sig_line - tag_line - strlen("tag \n");
- item->tag = xmalloc(taglen + 1);
- memcpy(item->tag, tag_line + 4, taglen);
- item->tag[taglen] = '\0';
-
- if (!strcmp(type, blob_type)) {
- item->tagged = &lookup_blob(sha1)->object;
- } else if (!strcmp(type, tree_type)) {
- item->tagged = &lookup_tree(sha1)->object;
- } else if (!strcmp(type, commit_type)) {
- item->tagged = &lookup_commit(sha1)->object;
- } else if (!strcmp(type, tag_type)) {
- item->tagged = &lookup_tag(sha1)->object;
- } else {
- error("Unknown type %s", type);
- item->tagged = NULL;
+ if (item) {
+ if (item->object.parsed)
+ return 0;
+ item->object.parsed = 1;
}
- if (item->tagged && track_object_refs) {
- struct object_refs *refs = alloc_object_refs(1);
- refs->ref[0] = item->tagged;
- set_object_refs(&item->object, refs);
+ if (size < 66)
+ return error("failed preliminary size check");
+
+ /* Verify mandatory object line */
+ if (memcmp(data, "object ", 7))
+ return error("char%d: does not start with \"object \"", 0);
+
+ if (get_sha1_hex(data + 7, sha1))
+ return error("char%d: could not get SHA1 hash", 7);
+
+ /* Verify mandatory type line */
+ type_line = data + 48;
+ if (memcmp(type_line - 1, "\ntype ", 6))
+ return error("char%d: could not find \"\\ntype \"", 47);
+
+ /* Verify optional tag line */
+ tag_line = memchr(type_line, '\n', end - type_line);
+ if (!tag_line++)
+ return error("char" PD_FMT ": could not find \"\\n\" after \"type\"", type_line - data);
+ if (end - tag_line < 4)
+ return error("char" PD_FMT ": premature end of data", tag_line - data);
+ if (memcmp("tag ", tag_line, 4))
+ keywords_line = tag_line; /* no tag name given */
+ else { /* tag name given */
+ keywords_line = memchr(tag_line, '\n', end - tag_line);
+ if (!keywords_line++)
+ return error("char" PD_FMT ": could not find \"\\n\" after \"tag\"", tag_line - data);
+ }
+
+ /* Verify optional keywords line */
+ if (end - keywords_line < 9)
+ return error("char" PD_FMT ": premature end of data", keywords_line - data);
+ if (memcmp("keywords ", keywords_line, 9))
+ tagger_line = keywords_line; /* no keywords given */
+ else { /* keywords given */
+ tagger_line = memchr(keywords_line, '\n', end - keywords_line);
+ if (!tagger_line++)
+ return error("char" PD_FMT ": could not find \"\\n\" after \"keywords\"", keywords_line - data);
+ }
+
+ if (thorough_verify) {
+ /*
+ * Verify mandatory tagger line, but only when we're checking
+ * thoroughly, i.e. on inserting a new tag, and on fsck.
+ * There are existing tag objects without a tagger line (most
+ * notably the "v0.99" tag in the main git repo), and we don't
+ * want to fail parsing on these.
+ */
+ if (end - tagger_line < 7)
+ return error("char" PD_FMT ": premature end of data", tagger_line - data);
+ if (memcmp("tagger ", tagger_line, 7))
+ return error("char" PD_FMT ": could not find \"tagger \"", tagger_line - data);
+ header_end = memchr(tagger_line, '\n', end - tagger_line);
+ if (!header_end++)
+ return error("char" PD_FMT ": could not find \"\\n\" after \"tagger\"", tagger_line - data);
+ if (end - header_end < 1)
+ return error("char" PD_FMT ": premature end of data", header_end - data);
+ if (*header_end != '\n') /* header must end with "\n\n" */
+ return error("char" PD_FMT ": could not find blank line after header section", header_end - data);
+ }
+ else {
+ /* Treat tagger line as optional */
+ if (end - tagger_line >= 7 && !memcmp("tagger ", tagger_line, 7)) {
+ /* Found tagger line */
+ header_end = memchr(tagger_line, '\n', end - tagger_line);
+ if (!header_end++)
+ return error("char" PD_FMT ": could not find \"\\n\" after \"tagger\"", tagger_line - data);
+ }
+ else /* No tagger line */
+ header_end = tagger_line;
}
+ if (end - header_end < 1)
+ return error("char" PD_FMT ": premature end of data", header_end - data);
+ if (*header_end != '\n') /* header must end with "\n\n" */
+ return error("char" PD_FMT ": could not find blank line after header section", header_end - data);
+
+ /* Calculate lengths of header fields */
+ type_len = tag_line == type_line ? 0 : /* 0 if not given, > 0 if given */
+ (tag_line - type_line) - strlen("type \n");
+ tag_len = keywords_line == tag_line ? 0 : /* 0 if not given, > 0 if given */
+ (keywords_line - tag_line) - strlen("tag \n");
+ keywords_len = tagger_line == keywords_line ? 0 : /* 0 if not given, > 0 if given */
+ (tagger_line - keywords_line) - strlen("keywords \n");
+ tagger_len = header_end == tagger_line ? 0 : /* 0 if not given, > 0 if given */
+ (header_end - tagger_line) - strlen("tagger \n");
+
+ /* Get the actual type */
+ if (type_len >= sizeof(type))
+ return error("char" PD_FMT ": type too long", (type_line + 5) - data);
+ memcpy(type, type_line + 5, type_len);
+ type[type_len] = '\0';
+
+ if (thorough_verify) {
+ /* Verify that the object matches */
+ if (verify_object(sha1, type))
+ return error("char%d: could not verify object %s", 7, sha1_to_hex(sha1));
+
+ /* Verify the tag name: we don't allow control characters or spaces in it */
+ if (tag_len > 0) { /* tag name was given */
+ tag_line += 4; /* skip past "tag " */
+ for (;;) {
+ unsigned char c = *tag_line++;
+ if (c == '\n')
+ break;
+ if (c > ' ' && c != 0x7f)
+ continue;
+ return error("char" PD_FMT ": could not verify tag name", tag_line - data);
+ }
+ }
+
+ /* Verify the keywords line: we don't allow control characters or spaces in it, or two subsequent commas */
+ if (keywords_len > 0) { /* keywords line was given */
+ keywords_line += 9; /* skip past "keywords " */
+ for (;;) {
+ unsigned char c = *keywords_line++;
+ if (c == '\n')
+ break;
+ if (c == ',' && *keywords_line == ',')
+ return error("char" PD_FMT ": found empty keyword", keywords_line - data);
+ if (c > ' ' && c != 0x7f)
+ continue;
+ return error("char" PD_FMT ": could not verify keywords", keywords_line - data);
+ }
+ }
+
+ /* Verify the tagger line */
+ /* TODO: check for committer/tagger info */
+
+ /* The actual stuff afterwards we don't care about.. */
+ }
+
+ if (item) { /* Store parsed information into item */
+ if (tag_len > 0) { /* optional tag name was given */
+ item->tag = xmalloc(tag_len + 1);
+ memcpy(item->tag, tag_line + 4, tag_len);
+ item->tag[tag_len] = '\0';
+ }
+ else { /* optional tag name not given */
+ item->tag = xmalloc(1);
+ item->tag[0] = '\0';
+ }
+
+ if (keywords_len > 0) { /* optional keywords string was given */
+ item->keywords = xmalloc(keywords_len + 1);
+ memcpy(item->keywords, keywords_line + 9, keywords_len);
+ item->keywords[keywords_len] = '\0';
+ }
+ else { /* optional keywords string not given. Set default keywords */
+ /* if tag name is set, use "tag"; otherwise use "note" */
+ const char *default_kw = item->tag ? "tag" : "note";
+ item->keywords = xmalloc(strlen(default_kw) + 1);
+ memcpy(item->keywords, default_kw, strlen(default_kw) + 1);
+ }
+
+ if (!strcmp(type, blob_type)) {
+ item->tagged = &lookup_blob(sha1)->object;
+ } else if (!strcmp(type, tree_type)) {
+ item->tagged = &lookup_tree(sha1)->object;
+ } else if (!strcmp(type, commit_type)) {
+ item->tagged = &lookup_commit(sha1)->object;
+ } else if (!strcmp(type, tag_type)) {
+ item->tagged = &lookup_tag(sha1)->object;
+ } else {
+ error("Unknown type %s", type);
+ item->tagged = NULL;
+ }
+
+ if (item->tagged && track_object_refs) {
+ struct object_refs *refs = alloc_object_refs(1);
+ refs->ref[0] = item->tagged;
+ set_object_refs(&item->object, refs);
+ }
+ }
return 0;
+
+#undef PD_FMT
+}
+
+int parse_tag_buffer(struct tag *item, void *data, unsigned long size)
+{
+ return parse_and_verify_tag_buffer(item, (const char *) data, size, 0);
}
int parse_tag(struct tag *item)
diff --git a/tag.h b/tag.h
index 7a0cb00..6853594 100644
--- a/tag.h
+++ b/tag.h
@@ -8,11 +8,13 @@ extern const char *tag_type;
struct tag {
struct object object;
struct object *tagged;
- char *tag;
+ char *tag; /* optional, may be empty ("") */
+ char *keywords; /* optional, defaults to tag ? "tag" : "note" */
char *signature; /* not actually implemented */
};
extern struct tag *lookup_tag(const unsigned char *sha1);
+extern int parse_and_verify_tag_buffer(struct tag *item, const char *data, const unsigned long size, int thorough_verify);
extern int parse_tag_buffer(struct tag *item, void *data, unsigned long size);
extern int parse_tag(struct tag *item);
extern struct object *deref_tag(struct object *, const char *, int);
--
1.5.2
^ permalink raw reply related
* [PATCH 0/6] Refactor the tag object
From: Johan Herland @ 2007-06-04 0:51 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano
In-Reply-To: <200706040251.05286.johan@herland.net>
This patch series implements part of the ground work for the 'notes'
feature discussed earlier in the thread "[PATCH 00/15] git-note: A
mechanism for providing free-form after-the-fact annotations on commits".
The following patches refactors the tag object by:
1. Making the "tag" header optional
2. Introducing a new optional "keywords" header
3. Making the "tagger" header mandatory as far as possible
4. Do better and more thorough verification of tag objects
Unfortunately the first patch in the series is bigger than I would have
liked, but I couldn't find an easy way to split it up.
Here's the shortlog:
Johan Herland (6):
Refactor git tag objects; make "tag" header optional; introduce new optional "keywords" header
git-show: When showing tag objects with no tag name, show tag object's SHA1 instead of an empty string
git-fsck: Do thorough verification of tag objects.
Documentation/git-mktag: Document the changes in tag object structure
git-mktag tests: Fix and expand the mktag tests according to the new tag object structure
Add fsck_verify_ref_to_tag_object() to verify that refname matches name stored in tag object
Documentation/git-mktag.txt | 42 +++++--
builtin-fsck.c | 35 ++++++
builtin-log.c | 2 +-
mktag.c | 148 +++++-------------------
t/t3800-mktag.sh | 204 ++++++++++++++++++++++++++++++---
tag.c | 266 +++++++++++++++++++++++++++++++++++--------
tag.h | 4 +-
7 files changed, 507 insertions(+), 194 deletions(-)
Have fun!
...Johan
--
Johan Herland, <johan@herland.net>
www.herland.net
^ permalink raw reply
* Refactoring the tag object; Introducing soft references (softrefs); Git 'notes' (take 2)
From: Johan Herland @ 2007-06-04 0:51 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano
(In response to the earlier thread on the git 'notes' feature/idea: "[PATCH
00/15] git-note: A mechanism for providing free-form after-the-fact
annotations on commits")
Ok, this is getting too big for me to ship all in one patch series, so I'm
gonna have to split it up. Right now I'm thinking three patch series, but
as I'm not near finished yet, that may change.
The three patch series I'm talking about are:
1. Refactoring the git tag object. This lays down part of the groundwork
needed to support the second incarnation of git 'notes'. This is all ready
to go and should follow shortly after this mail.
2. Introducing soft references (softrefs). Softrefs is the general mechanism
behind the "reverse mapping" needed to support 'notes', as discussed in the
previous thread. I'm still working on this patch series, and it will
hopefully be ready soon-ish.
3. Reimplementing git 'notes' on top of (1) and (2). This should be fairly
easy (once (2) is done), as it's mostly a matter of building a simple
porcelain on top of (1) and (2).
Have fun!
...Johan
--
Johan Herland, <johan@herland.net>
www.herland.net
^ permalink raw reply
* Re: [PATCH] Use git-tag in git-cvsimport
From: Junio C Hamano @ 2007-06-04 0:01 UTC (permalink / raw)
To: Martin Waitz; +Cc: Elvis Pranskevichus, git
In-Reply-To: <20070603225354.GB16637@admingilde.org>
Martin Waitz <tali@admingilde.org> writes:
> hoi :)
>
> On Sun, Jun 03, 2007 at 02:56:36AM -0400, Elvis Pranskevichus wrote:
>> Fix this by calling git-tag instead. This also has a nice side effect of
>> not creating the tag object but only the lightweight tag as that's the only
>> thing CVS has anyways.
>
> but lightweight tags are not fetched by default.
Are you sure about that?
^ permalink raw reply
* Re: [RFC/PATCH 4/3] Simplify naming (versioning) of non-release tig tarball and rpm file
From: Jakub Narebski @ 2007-06-03 21:12 UTC (permalink / raw)
To: Jonas Fonseca; +Cc: git
In-Reply-To: <20070603091126.GA1419@diku.dk>
On Sun, 3 Jun 2007, Jonas Fonseca wrote:
> Jakub Narebski <jnareb@gmail.com> wrote Sat, Jun 02, 2007:
>> This is proposal to simplify naming of non-release tarballs and rpm file,
>> both for tig and also for git itself. Instead of using whole git-describe
>> output as version number in tarball/rpm name (BTW. it would be nice to
>> have command line switch to git-describe which would return old output,
>> without number of commits since given tag) use tag part as version number,
>> and number of commits since (plus optional marking dirty) as release
>> number.
>>
>> What do you think about this?
>
> I like the simpler and less confusing names. How about the simpler
> version below?
This version would work for tig now, but is not very generic. See also
comments below.
> BTW, I also added `make dist DIST_VERSION=X.Y` to make it easy to force
> a version. I used it when building the documentation in the release
> branch.
Nice idea.
>> diff --git a/Makefile b/Makefile
>> index b49d7f8..1e67586 100644
>> --- a/Makefile
>> +++ b/Makefile
>> @@ -17,7 +17,13 @@ ifdef DIST_VERSION
>> VERSION = $(DIST_VERSION)
>> endif
>>
>> -RPM_VERSION = $(subst -,.,$(VERSION))
>> +# $(GITDESC) looks like either x.y, or like x.y-z-g<sha1>
>> +SPLIT_VERSION := $(shell echo $(GITDESC) | \
>> + sed -e 's/^\(.*\)-\([0-9]\+\)-\(g[0-9a-f]\+\)$$/\1 \2 \3/g')
>> +RPM_VERSION = $(subst -,.,$(word 1,$(SPLIT_VERSION)))
>> +RPM_RELEASE = $(strip \
>> + $(subst -,.,$(if $(word 2,$(SPLIT_VERSION)),\
>> + $(word 2,$(SPLIT_VERSION)),0)$(WTDIRTY)))
>>
>> LDLIBS = -lcurses
>> CFLAGS = -Wall -O2 '-DVERSION="$(VERSION)"'
>
> diff --git a/Makefile b/Makefile
> index 91cb097..622a916 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -17,7 +17,11 @@ ifdef DIST_VERSION
> VERSION = $(DIST_VERSION)
> endif
>
> -RPM_VERSION = $(subst -,.,$(VERSION))
> +# Split the version "TAG-OFFSET-gSHA1-DIRTY" into "TAG OFFSET"
> +# and append 0 as a fallback offset for "exact" tagged versions.
> +RPM_VERLIST = $(filter-out g% dirty,$(subst -, ,$(VERSION))) 0
> +RPM_VERSION = $(word 1,$(RPM_VERLIST))
> +RPM_RELEASE = $(word 2,$(RPM_VERLIST))$(if $(WTDIRTY),.dirty)
>
> LDLIBS = -lcurses
> CFLAGS = -Wall -O2
I'd like to note that I wanted to make _generic_ version of generating
RPM_VERSION and RPM_RELEASE from the output of git-describe (also with
marking that working directory was in dirty state). Your simpler version
works for tags used in tig repository, but for example not necessarily
so for git repository.
I assume that "version tags" are of the form
[<prefix>]<version>
where optional <prefix> is "v" for git and linux repositories, "tig-"
for tig repository, "gitgui-" for git-gui repository. <version> starts
with a number, and usually consists of numbers separated by dots, but
it can contain also alphanumeric suffix, for example "-rc1", "-pre7",
"b" (c.f. v0.99.9b tag in git repository), etc. I assume that <version>
is the part that starts with the number.
This means that git-describe output is either of the form
[<prefix>]<version>
(if there is exact match), or of the form
[<prefix>]<version>-<number of additional commits>-g<abbreviated sha-1>
For exact match (release tarball) I'd like to have
RPM_VERSION = $(subst -,.,<version>)
RPM_RELEASE = 0
and for non-exact match to have
RPM_VERSION = $(subst -,.,<version>)
RPM_RELEASE = <number of additional commits>.g<abbreviated sha-1>
The "g<abbreviated sha-1>", which was missing from my (and yours)
proposal is needed because we can have multiple branches, and the
part before "-g<abbreviated sha-1>" could be the same for different
commits (on different branches, e.g. 'master' and 'next').
For "make dist" run from a dirty tree we want to have ".dirty" suffix
added to RPM_RELEASE.
Example: if git-describe returns v1.4.3-rc2-21-g0a7a9a1 in a dirty tree
(with uncommitted changes) I'd like to have 1.4.3.rc2 as version number
and 21.g0a7a9a1.dirty as release number, so tarball would be named
git-1.4.3.rc2-21.g0a7a9a1.dirty.tar.gz
Now to the implementation. I wanted to do the above using only Makefile
functions, if not for two complications. First I didn't know how to
get second-to-last word, or how to remove last word from variable;
trick with filter-out could work there. Second in generic version is
quite hard to distinguish using only make functions between exact and
non-exact match for arbitrary versioning (tagging versions) scheme.
P.S. Perhaps instead of RPM_VERSION we should (re)use DIST_VERSION,
and instead of RPM_RELEASE use DIST_RELEASE?
--
Jakub Narebski
Poland
^ permalink raw reply
* Re: [PATCH] Add git-filter-branch
From: Johannes Schindelin @ 2007-06-03 23:07 UTC (permalink / raw)
To: Jakub Narebski; +Cc: git
In-Reply-To: <200706031228.58779.jnareb@gmail.com>
Hi,
On Sun, 3 Jun 2007, Jakub Narebski wrote:
> On Sun, 3 Jun 2007, Johannes Schindelin wrote:
> > On Sun, 3 Jun 2007, Jakub Narebski wrote:
> >> Johannes Schindelin wrote:
> >>
> >>> This script is derived from Pasky's cg-admin-rewritehist.
> >>>
> >>> In fact, it _is_ the same script, minimally adapted to work without cogito.
> >>> It _should_ be able to perform the same tasks, even if only relying on
> >>> core-git programs.
> >>>
> >>> All the work is Pasky's, just the adaption is mine.
> >>
> >> I was thinking about rewriting cg-adin-rewritehist as git-rewritehist
> >> using Perl (IIRC it needs bash, not only POSIX shell), and make it
> >> use git-fast-import.
>
> By the way, why did you change name to git-filter-branch, instead of
> leaving it [almost] as is, i.e. git-rewritehist. Or if you wanted to
> emphasize that it rewrites only one branch at a time, git-rewrite-branch?
It does not rewrite the branch. It writes a filtered _copy_. That is what
I wanted to make clear by that renaming.
> Note that history (branch) gets rewritten also in absence of filters, if
> there are any grafts in place. But I might be mistaken.
Actually, if you check the first non-setup test in the provide test
script, no. It is not _really_ rewritten. As the commit names stay exactly
the same.
> > First, it does not need Perl.
> >
> > Second, it does not even need bash.
>
> If I remember correctly (but I can be wrong here) Pasky said that he had
> to use arrays in cg-admin-rewritehist. Because introducing dependency on
> bash would be bad, that was the cause of thought to rewrite it in Perl
> (which we depend on anyway).
I rewrote the only instance where arrays were used:
> > At least that is what I tried to make sure. I replaced the only
> > instance of a bashim I was aware, namely the arrayism of $unchanged.
> > It can be a string just as well, as we are only storing object names
> > in it.
>
> I'm sorry, I haven't reviewed your patch carefully enough, it seems
> like. If you can translate cg-admin-rewritehist to POSIX shell, more
> power to you.
Actually, that is my understanding.
> Few notes of lesser importance (meaning they can go into subsequent
> commits).
>
> 1. Documentation: Cogito had documentation together with the command
> described, similarly to Perl POD, or LaTeX doc package + DocStrip,
> etc. It has IIRC rules in Makefile to extract documentation.
>
> In git we have documentation in separate files. The commands
> themselves have only usage, and sometimes long usage embedded.
> It would be nice of git-filter-branch / git-rewrite-branch also
> followed this convention.
Yes, I did not plan to provide documentation with the first patch, since I
wanted to encourage _review_ of the patch. Obviously, I failed ;-)
> 2. Using fast-import.
>
> >> +# Note that since this operation is extensively I/O expensive, it might
> >> +# be a good idea to do it off-disk, e.g. on tmpfs. Reportedly the speedup
> >> +# is very noticeable.
>
> Would it be possible to use git-fast-import to reduce I/O in this
> command? Cogito didn't use it because it is quite new, but there
> is no reason to not to use it now, I think.
It is overkill, usually.
The only thing that could benefit from it, would be complicated tree
filters.
But _the_ main usage for this script (in my expectation, at least) will be
to split projects into subprojects.
For this, we _still_ don't need fast-import, but maybe a better
tree-filter (something like --subdir-filter, which only checks out the
subdir (in the root), and also only takes those revisions into account
that actually touch that subdir).
Ciao,
Dscho
^ permalink raw reply
* Re: [RFC] git integrated bugtracking
From: Martin Waitz @ 2007-06-03 23:07 UTC (permalink / raw)
To: Linus Torvalds, git
In-Reply-To: <20070603201632.GF30347@artemis>
[-- Attachment #1: Type: text/plain, Size: 862 bytes --]
hoi :)
On Sun, Jun 03, 2007 at 10:16:32PM +0200, Pierre Habouzit wrote:
> Well I went that way, but we loose the quite cool "if I branch my
> repository I branch the bugs coming with them too"-feature. And I'd be
> sad to give that up. But maybe it's an error to want to use git to
> encode that relation.
Just store the commit which introduced the bug (or where the bug
was first found) and you will get that, too. You only have to check
if this commit is reachable by a given branch to see if it is affected.
When you fix the bug you store the commit id that fixed it and then
you can check every branch if it points into bad..good.
You can also do this for released versions.
If you have the bug database inside the repository you can't report
any bugs for a released version, because it is, well already released.
--
Martin Waitz
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply
* Re: [PATCH] Use git-tag in git-cvsimport
From: Martin Waitz @ 2007-06-03 22:53 UTC (permalink / raw)
To: Elvis Pranskevichus; +Cc: git
In-Reply-To: <11808537962798-git-send-email-el@prans.net>
[-- Attachment #1: Type: text/plain, Size: 549 bytes --]
hoi :)
On Sun, Jun 03, 2007 at 02:56:36AM -0400, Elvis Pranskevichus wrote:
> Fix this by calling git-tag instead. This also has a nice side effect of
> not creating the tag object but only the lightweight tag as that's the only
> thing CVS has anyways.
but lightweight tags are not fetched by default.
And only leaving them in the repository that actually did the cvsimport
makes them much less valuable.
> +
> + system("git-tag $xtag $cid") == 0
I suggest adding something like -m "import label from CVS".
--
Martin Waitz
[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply
* [StGIT PATCH not for master] Use gitk --argscmd in contrib/stg-gitk.
From: Yann Dirson @ 2007-06-03 22:52 UTC (permalink / raw)
To: Catalin Marinas; +Cc: git
This allows to ask gitk to recompute the list of patches to show at
every refresh. Before this, we had problems with 'stg-gitk --all':
- deleting a patch that was existing at startup time would trigger an
"unknown ref" error from gitk and force to quit/restart manually;
- patches created since startup were only visible when applied, or
when below one of the startup patches.
Signed-off-by: Yann Dirson <ydirson@altern.org>
---
Note that this flag is added by the gitk patch I just posted, so it
should not be applied to StGIT master right now - we want that git
gets released with the necessary support before we do that.
contrib/stg-gitk | 26 ++++++++++++++++++++------
1 files changed, 20 insertions(+), 6 deletions(-)
diff --git a/contrib/stg-gitk b/contrib/stg-gitk
index dd01ef0..f2fca84 100755
--- a/contrib/stg-gitk
+++ b/contrib/stg-gitk
@@ -20,11 +20,16 @@ usage()
}
allbranches=0
-case "$1" in
---all) allbranches=1; shift ;;
---*) usage ;;
-*) break ;;
-esac
+refsonly=0
+while [ "$#" -gt 0 ]; do
+ case "$1" in
+ --refs) refsonly=1 ;;
+ --all) allbranches=1 ;;
+ --*) usage ;;
+ *) break ;;
+ esac
+ shift
+done
if [ $allbranches = 1 ] && [ "$#" -gt 0 ]; then
usage
@@ -58,4 +63,13 @@ else
done
fi
-gitk $(find $refdirs -type f -not -name '*.log' | cut -c${GIT_DIR_SPKIPLEN}- )
+printrefs()
+{
+ find $refdirs -type f -not -name '*.log' | cut -c${GIT_DIR_SPKIPLEN}-
+}
+
+if [ $refsonly = 1 ]; then
+ printrefs
+else
+ gitk --argscmd="$0 --refs $@"
+fi
^ permalink raw reply related
* [PATCH] Add to gitk an --argscmd flag to get the list of refs to draw at refresh time.
From: Yann Dirson @ 2007-06-03 22:49 UTC (permalink / raw)
To: paulus; +Cc: git
This flag is meant for porcelains which can modify the list of
meaningful refs to graph. It allows gitk's refresh operation to be
always up-to-date wrt the list of refs to graph.
Primary target is stg-gitk (in StGIT contrib/ dir), which requests
gitk to graph all patches in a stack: patches can be created and
deleted, so we need a way to tell gitk that something has changed.
This patch does not allow setting this parameter in a saved profile,
although it reserves a slot in the savefile format, and will read it
when it finds one.
Signed-off-by: Yann Dirson <ydirson@altern.org>
---
Documentation/gitk.txt | 6 ++++++
gitk | 28 +++++++++++++++++++++++-----
2 files changed, 29 insertions(+), 5 deletions(-)
diff --git a/Documentation/gitk.txt b/Documentation/gitk.txt
index 48c5894..21d002b 100644
--- a/Documentation/gitk.txt
+++ b/Documentation/gitk.txt
@@ -41,6 +41,12 @@ frequently used options.
Show all branches.
+--argscmd=<command>::
+ Command to be run each time gitk has to determine the list of
+ <revs> to show. Use this instead of explicitely specifying
+ <revs> if the list 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 a57e84c..6d4d10a 100755
--- a/gitk
+++ b/gitk
@@ -19,12 +19,23 @@ proc gitdir {} {
proc start_rev_list {view} {
global startmsecs nextupdate
global commfd leftover tclencoding datemode
- global viewargs viewfiles commitidx
+ global viewargs viewargscmd viewfiles commitidx
set startmsecs [clock clicks -milliseconds]
set nextupdate [expr {$startmsecs + 100}]
set commitidx($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 [read $fd 500000]
+ close $fd
+ } else {
+ set args $viewargs($view)
+ }
if {$viewfiles($view) ne {}} {
set args [concat $args "--" $viewfiles($view)]
}
@@ -823,7 +834,7 @@ proc savestuff {w} {
global canv canv2 canv3 ctext cflist mainfont textfont uifont
global stuffsaved findmergefiles maxgraphpct
global maxwidth showneartags
- global viewname viewfiles viewargs viewperm nextviewnum
+ global viewname viewfiles viewargs viewargscmd viewperm nextviewnum
global cmitmode wrapcomment
global colors bgcolor fgcolor diffcolors
@@ -856,7 +867,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 "}"
@@ -6298,10 +6309,14 @@ catch {source ~/.gitk}
font create optionfont -family sans-serif -size -12
set revtreeargs {}
+set revtreeargscmd None
foreach arg $argv {
switch -regexp -- $arg {
"^$" { }
"^-d" { set datemode 1 }
+ "^--argscmd=" {
+ regexp {^--argscmd=(.*)} $arg match revtreeargscmd
+ }
default {
lappend revtreeargs $arg
}
@@ -6357,6 +6372,7 @@ set selectedhlview None
set viewfiles(0) {}
set viewperm(0) 0
set viewargs(0) {}
+set viewargscmd(0) None
set cmdlineok 0
set stopped 0
@@ -6367,7 +6383,7 @@ makewindow
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
@@ -6375,6 +6391,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
@@ -6388,6 +6405,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
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