* Re: [PATCH] Allow --quiet option to git remote, particularly for `git remote update`
From: Alex Vandiver @ 2009-12-07 7:23 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <7vd42soo2p.fsf@alter.siamese.dyndns.org>
At Sat Dec 05 21:04:14 -0500 2009, Junio C Hamano wrote:
> Alex Vandiver <alex@chmrr.net> writes:
> > ...
> > "git remote prune [-n | --dry-run] <name>",
> > - "git remote [-v | --verbose] update [-p | --prune] [group | remote]",
> > + "git remote [-v | --verbose] [-q | --quiet] update [-p | --prune] [group]",
Hm, I hadn't noticed that I'd changed "[group | remote]" to "[group]".
I think this is due to a mismerge on my part -- apologies. As another
data point, `git fetch` describes this as "[<repository> | <group>]".
> Three issues to consider:
>
> - shouldn't we use the same typography, i.e. <group>?
>
> - should we say <name> _if_ we are not going to say <group>|<remote>?
>
> - should we keep it as <group>|<remote> to make it clear that only this
> subcommand allows the group nickname?
>
> The first two are easy and I expect the answers to be both yes. The third
> one needs some studying and further thought.
>
> - is "remote update" the only one that takes group nickname?
My quick skim of the code says "yes" -- the other commands only deal
with single remotes at a time, and prune is oblivious to groups.
> - should "remote update" the only one? e.g. does "remote prune" also
> take group? if not, shouldn't it?
Properly, it "ought" to, though I don't see much utility over `git
remote fetch --prune groupname`. Probably at the same time, the
parallel pruning codepaths in builtin-fetch.c:prune_refs() and
builtin-remote.c:prune_remote() should be unified.
- Alex
--
Networking -- only one letter away from not working
^ permalink raw reply
* Re: [PATCH v2] Detailed diagnosis when parsing an object name fails.
From: Junio C Hamano @ 2009-12-07 7:27 UTC (permalink / raw)
To: Matthieu Moy; +Cc: git
In-Reply-To: <vpqhbs4dkjr.fsf@bauges.imag.fr>
Matthieu Moy <Matthieu.Moy@grenoble-inp.fr> writes:
The second round still had a few compilation warnings (turned to errors in
my environment) so I fixed them up somewhat. I stopped before getting a
clean compile, though---you will still get:
sha1_name.c: In function 'get_sha1_with_mode_1':
sha1_name.c:956: error: 'object_name' may be used uninitialized in this function
even with this fix-up.
>> Instead of doing a leaky allocation, it may make sense to pass the tree
>> object name as <const char *, size_t> pair, and print it with "%.*s" in
>> the error reporting codepath. After all, object_name is used only for
>> that purpose in diagnose_invalid_sha1_path(), no?
>
> matter of taste,...
I thought generally it is accepted that I had a better taste on this list?
;-)
-- squashed --
cache.h | 4 ++--
sha1_name.c | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/cache.h b/cache.h
index 952bd51..3f9ee86 100644
--- a/cache.h
+++ b/cache.h
@@ -702,11 +702,11 @@ static inline unsigned int hexval(unsigned char c)
#define DEFAULT_ABBREV 7
extern int get_sha1(const char *str, unsigned char *sha1);
-static inline get_sha1_with_mode(const char *str, unsigned char *sha1, unsigned *mode)
+extern int get_sha1_with_mode_1(const char *str, unsigned char *sha1, unsigned *mode, int gently, const char *prefix);
+static inline int get_sha1_with_mode(const char *str, unsigned char *sha1, unsigned *mode)
{
return get_sha1_with_mode_1(str, sha1, mode, 1, NULL);
}
-extern int get_sha1_with_mode_1(const char *str, unsigned char *sha1, unsigned *mode, int gently, const char *prefix);
extern int get_sha1_hex(const char *hex, unsigned char *sha1);
extern char *sha1_to_hex(const unsigned char *sha1); /* static buffer result! */
extern int read_ref(const char *filename, unsigned char *sha1);
diff --git a/sha1_name.c b/sha1_name.c
index 1bc09ac..025244a 100644
--- a/sha1_name.c
+++ b/sha1_name.c
@@ -807,7 +807,7 @@ int get_sha1(const char *name, unsigned char *sha1)
/* Must be called only when object_name:filename doesn't exist. */
static void diagnose_invalid_sha1_path(const char *prefix,
const char *filename,
- const char *tree_sha1,
+ const unsigned char *tree_sha1,
const char *object_name)
{
struct stat st;
^ permalink raw reply related
* Re: [PATCH 1/2] Documentation: 'git add -A' can remove files
From: Junio C Hamano @ 2009-12-07 7:34 UTC (permalink / raw)
To: Björn Steinbrink; +Cc: Björn Gustavsson, git
In-Reply-To: <20091207005732.GA20909@atjola.homenet>
Björn Steinbrink <B.Steinbrink@gmx.de> writes:
> What I usually say on #git is something like:
>
> "git add <path>" looks at the working tree to find files
> matching <path>. "git add -u <path>" looks at the index, and
> "git add -A <path>" looks at both. Therefore "add" and "add -A"
> can add new files to the index, and "add -u" and "add -A" can
> remove files from it.
>
> And for convenience, -u and -A default to "." as the path argument.
Hmm, an interesting way of teaching. How effective is it with the real new
to mid-level users we see on the #git channel?
> So maybe something like this?
> ...
> -A, --all
> Like -u, but matches <filepattern> against files in the index in
> addition to the files in working tree. This means that it can find
> new files as well.
Sounds easier to read to me but I think this description of "-A" seems
backwards from your explanation. "Like -u" means "matches the index" and
the difference is it in addition matches with the work tree, so it should
probably be the other way around, i.e.
Like -u, but matches <filepattern> against files in the work tree in
addition to the index. This means that it can find new files as well.
^ permalink raw reply
* Re: [RFC PATCH v3 0/8] Remote helpers smart transport extensions
From: Junio C Hamano @ 2009-12-07 7:36 UTC (permalink / raw)
To: Ilari Liusvaara; +Cc: git
In-Reply-To: <1260116931-16549-1-git-send-email-ilari.liusvaara@elisanet.fi>
I queued to ease the discussion in 'pu'. I had to fix-up some conflicts
while doing so. Please sanity check the result.
Thanks.
^ permalink raw reply
* [PATCH] Documentation: 'git add -A' can remove files
From: Björn Gustavsson @ 2009-12-07 8:20 UTC (permalink / raw)
To: git; +Cc: Junio C Hamano
The current documentation fails to mention that 'git add -A/--all'
can remove files as well as add them, and it also does not
say anything about filepatterns (whether they are allowed,
mandatory, or optional). It is also not clear what the similarities
and differences to the -u option are.
Update the intro paragraph (as suggested by Junio, with some minor
edits) to make it clear that 'git add' is able to delete and to
also cover the -p option.
Reword the description of -u to make it clearer (based on by
Björn Steinbrink's suggestion).
Simplify the description of -A by saying "Like -u" and then
describe the differences (based on the suggestions by Björn
Steinbrink and Junio).
Signed-off-by: Björn Gustavsson <bgustavsson@gmail.com>
---
I have to leave for work now, so I'll just send the first part
now, which I think is much improved compared to
the previous version. Thanks Junio and Björn S for the
suggestions.
Documentation/git-add.txt | 33 ++++++++++++++++++++-------------
1 files changed, 20 insertions(+), 13 deletions(-)
diff --git a/Documentation/git-add.txt b/Documentation/git-add.txt
index e93e606..ed68ea3 100644
--- a/Documentation/git-add.txt
+++ b/Documentation/git-add.txt
@@ -14,8 +14,12 @@ SYNOPSIS
DESCRIPTION
-----------
-This command adds the current content of new or modified files to the
-index, thus staging that content for inclusion in the next commit.
+This command updates the index using the current content found in
+the working tree, to prepare the content staged for the next commit.
+It typically adds the current content of existing paths as a whole,
+but with some options it can also be used to add content with
+only part of the changes made to the working tree files applied, or
+remove paths that do not exist in the working tree anymore.
The "index" holds a snapshot of the content of the working tree, and it
is this snapshot that is taken as the contents of the next commit. Thus
@@ -92,20 +96,23 @@ apply.
-u::
--update::
- Update only files that git already knows about, staging modified
- content for commit and marking deleted files for removal. This
- is similar
- to what "git commit -a" does in preparation for making a commit,
- except that the update is limited to paths specified on the
- command line. If no paths are specified, all tracked files in the
- current directory and its subdirectories are updated.
+ Only match <filepattern> against already tracked files in
+ the index rather than the working tree. That means that it
+ will never stage new files, but that it will stage modified
+ new contents of tracked files and that it will remove files
+ from the index if the corresponding files in the working tree
+ have been removed.
++
+If no <filepattern> is given, default to "."; in other words,
+update all tracked files in the current directory and its
+subdirectories.
-A::
--all::
- Update files that git already knows about (same as '\--update')
- and add all untracked files that are not ignored by '.gitignore'
- mechanism.
-
+ Like `-u`, but match <filepattern> against files in the
+ working tree in addition to the index. That means that it
+ will find new files as well as staging modified content and
+ removing files that are no longer in the working tree.
-N::
--intent-to-add::
--
1.6.6.rc1.31.g1a56b
^ permalink raw reply related
* Re: [PATCH] cvsserver: make the output of 'update' more compatible with cvs.
From: Sergei Organov @ 2009-12-07 8:27 UTC (permalink / raw)
To: mmogilvi_git; +Cc: git, gitster
In-Reply-To: <20091205234831.GA925@comcast.net>
mmogilvi_git@miniinfo.net writes:
> On Thu, Dec 03, 2009 at 11:12:47PM +0300, Sergei Organov wrote:
>>
>> + my $last_dirname = "///";
>> +
>> # foreach file specified on the command line ...
>> foreach my $filename ( @{$state->{args}} )
>> {
>> $filename = filecleanup($filename);
>> + my $cur_dirname = dirname($filename);
>> + if ( $cur_dirname ne $last_dirname )
>> + {
>> + $last_dirname = $cur_dirname;
>> + if ( $cur_dirname eq "" )
>> + {
>> + $cur_dirname = ".";
>> + }
>> + print "E cvs update: Updating $cur_dirname\n";
>> + }
>>
>> $log->debug("Processing file $filename");
>
> This should probably be conditional on the absense of the
> global "cvs -q update" and "cvs -Q update" options, in case
> other CVS clients depend on quiet operation when they specify
> those options.
Good catch, thanks! I'll redo the patch.
-- Sergei.
^ permalink raw reply
* Re: [PATCH 2/2] status -s: obey color.status
From: Michael J Gruber @ 2009-12-07 8:33 UTC (permalink / raw)
To: Jeff King; +Cc: git, Junio C Hamano
In-Reply-To: <20091207051715.GA17521@coredump.intra.peff.net>
Jeff King venit, vidit, dixit 07.12.2009 06:17:
> On Sat, Dec 05, 2009 at 04:04:38PM +0100, Michael J Gruber wrote:
>
>> Make the short version of status obey the color.status boolean. We color
>> the status letters only, because they carry the state information and are
>> potentially colored differently, such as for a file with staged changes
>> as well as changes in the worktree against the index.
>
> This seems to also turn on color for --porcelain in some cases, because
> git_status_config unconditionally sets s->use_color if you are using
> color.status instead of color.ui. I think we are probably best just
> explicitly disabling options for the "porcelain" format rather than
> trying to come up with some trickery to make sure they never get set.
> Like:
Thanks. I let myself get fooled by the apparent option handling within
the switch statement (which is OK for relativePaths) (and some
subconscious link between null_termination and porcelain, which goes one
way only).
I guess this shows (again) that one needs tests for everything... If I
get around to I'll amend t$(relevantoneicantrecallrightnow) with tests
for long and short status with color and porcelain with the various options.
Michael
^ permalink raw reply
* Re: git-blame.el: what is format-spec?
From: Sergei Organov @ 2009-12-07 8:36 UTC (permalink / raw)
To: David Kågedal; +Cc: Andreas Schwab, git
In-Reply-To: <87d42s3pv2.fsf@lysator.liu.se>
David Kågedal <davidk@lysator.liu.se> writes:
> Sergei Organov <osv@javad.com> writes:
>
>> Then there should be (require 'format-spec) in git-blame.el, right? Due
>> to:
>
> Of course. I must have missed that since I already had it loaded.
>
>> Now, I've evaluated (require 'format-spec) in my Emacs 22 (yes, 22, not
>> 23), and now git-blame almost works there. The problem I see is that it
>> doesn't output anything in the echo area. It color-codes the buffer, it
>> does show correct pop-up when mouse is over a region, but it doesn't
>> print anything in the echo area when I move cursor through the regions.
>> Any idea how to debug/fix this?
>
> Well, it appears I removed the output to the echo area. I didn't think
> it worked very well, and the new output format mostly replaces it by
> showing the hash.
>
> There are also technical reasons for removing it (it couldn't be
> implemented very cleanly).
I didn't know you deliberately removed it, -- I thought it's some
Emacs22 - related problem. I have no problem then, except that I don't
know how to get the hash into my kill-ring or X selection.
While we are at it, why is git-blame-identify interactive and how is it
useful?
>
> It would of course be possible to restore the old way, but I think it
> would be good to ask ourselves what we really would like to see? Some
> ideas:
>
> * A keybinding to show the commit introducing the current line,
> including diff and all.
>
> * A keybinding to show the commit message in the echo areia.
For me, these 2 would be more than enough, I think.
-- Sergei.
^ permalink raw reply
* Re: [PATCH 1/2] Documentation: 'git add -A' can remove files
From: Björn Steinbrink @ 2009-12-07 8:48 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Björn Gustavsson, git
In-Reply-To: <7vbpib9r10.fsf@alter.siamese.dyndns.org>
On 2009.12.06 23:34:03 -0800, Junio C Hamano wrote:
> Björn Steinbrink <B.Steinbrink@gmx.de> writes:
>
> > What I usually say on #git is something like:
> >
> > "git add <path>" looks at the working tree to find files
> > matching <path>. "git add -u <path>" looks at the index, and
> > "git add -A <path>" looks at both. Therefore "add" and "add -A"
> > can add new files to the index, and "add -u" and "add -A" can
> > remove files from it.
> >
> > And for convenience, -u and -A default to "." as the path argument.
>
> Hmm, an interesting way of teaching. How effective is it with the real new
> to mid-level users we see on the #git channel?
Hm, I wanted to check the channel logs for some reactions, but couldn't
find much. Apparently, I've not answered many question about add -u/-A
on #git since I switched to the above explanation (instead of saying
"git add -A is like git add . && git add -u" as I did in the past). For
the cases I found, the users didn't reply to the explanation. I can't
tell whether the explanation sucks, or whether the user was happy with
it or simply didn't care because he got the command he wanted.
I have two more data points for that kind of explanation in my Jabber
history, but those users aren't "new to mid-level" anymore.
And I recall only one really new user I told this to in face-to-face
"teaching", and that was right after explaining the index, so the
concept was present.
I guess the explanation might not be as easy to grok for someone that
doesn't have a good understanding of the index. For example, those that
still think that the index only stores changes (and is empty when no
"changes" have been staged) probably won't be able to make any sense out
of it.
Guess I'll have to apply a bunch of context when choosing which
explanation to use.
>
> > So maybe something like this?
> > ...
> > -A, --all
> > Like -u, but matches <filepattern> against files in the index in
> > addition to the files in working tree. This means that it can find
> > new files as well.
>
> Sounds easier to read to me but I think this description of "-A" seems
> backwards from your explanation. "Like -u" means "matches the index" and
> the difference is it in addition matches with the work tree, so it should
> probably be the other way around, i.e.
>
> Like -u, but matches <filepattern> against files in the work tree in
> addition to the index. This means that it can find new files as well.
Hm, I meant that to show that while -u uses the index _instead_ of the
working tree, -A uses the index _in_addition_to_ the working tree, i.e.
I meant to say how -A differs from -u WRT its effect compared to a plain
"git add".
IOW, I treat "git add" (working tree only) as the default behaviour. And
-u changes it to "index only", while -A changes it to "working tree +
index". Your version makes it look more like -A is a modification of -u.
OTOH, I also used to say "to update all tracked files, use add -u, and
to also add new files use add -A", which is better matched by your
wording. Though I'd go for this then:
Like -u, but also match <filepattern> against files in the working
tree. This means that it can find new files as well
Which just says what -A does on top of -u, without repeating what -u
does.
Björn
^ permalink raw reply
* Re: git-blame.el: what is format-spec?
From: David Kågedal @ 2009-12-07 9:05 UTC (permalink / raw)
To: Sergei Organov; +Cc: git, Andreas Schwab
In-Reply-To: <87k4wzdvuk.fsf@osv.gnss.ru>
Sergei Organov <osv@javad.com> writes:
> David Kågedal <davidk@lysator.liu.se> writes:
>
>> Sergei Organov <osv@javad.com> writes:
>>
>>> Then there should be (require 'format-spec) in git-blame.el, right? Due
>>> to:
>>
>> Of course. I must have missed that since I already had it loaded.
>>
>>> Now, I've evaluated (require 'format-spec) in my Emacs 22 (yes, 22, not
>>> 23), and now git-blame almost works there. The problem I see is that it
>>> doesn't output anything in the echo area. It color-codes the buffer, it
>>> does show correct pop-up when mouse is over a region, but it doesn't
>>> print anything in the echo area when I move cursor through the regions.
>>> Any idea how to debug/fix this?
>>
>> Well, it appears I removed the output to the echo area. I didn't think
>> it worked very well, and the new output format mostly replaces it by
>> showing the hash.
>>
>> There are also technical reasons for removing it (it couldn't be
>> implemented very cleanly).
>
> I didn't know you deliberately removed it, -- I thought it's some
> Emacs22 - related problem. I have no problem then, except that I don't
> know how to get the hash into my kill-ring or X selection.
>
> While we are at it, why is git-blame-identify interactive and how is it
> useful?
I think I need to go over this file with a fine-tooth coam to remove or
fix bitrot. This command seems to try to show the hash in the echo area,
but probably doesn't work. New and better commands should be deviced.
I'll try to find some time to work on this soon.
Thanks a lot for the feedback.
--
David Kågedal
^ permalink raw reply
* [PATCHv3 0/2] Add a "fixup" command to "rebase --interactive"
From: Michael Haggerty @ 2009-12-07 9:20 UTC (permalink / raw)
To: git; +Cc: gitster, git, Johannes.Schindelin, bgustavsson, Michael Haggerty
In-Reply-To: <7vskbn9s1k.fsf@alter.siamese.dyndns.org>
Junio C Hamano wrote:
> Michael Haggerty <mhagger@alum.mit.edu> writes:
>
>> diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh
>> index 0bd3bf7..a7de5ea 100755
>> --- a/git-rebase--interactive.sh
>> +++ b/git-rebase--interactive.sh
>> @@ -302,7 +302,13 @@ nth_string () {
>>
>> make_squash_message () {
>> if test -f "$SQUASH_MSG"; then
>> - COUNT=$(($(sed -n "s/^# This is [^0-9]*\([1-9][0-9]*\).*/\1/p" \
>> + # We want to be careful about matching only the commit
>> + # message comment lines generated by this function.
>
>> + # But supposedly some sed versions don't handle "\|"
>> + # correctly, so instead of "\(st\|nd\|rd\|th\)", use
>> + # the less accurate "[snrt][tdh]" to match the
>> + # nth_string endings.
>
> I'd drop this comment; blaming POSIX-compliant sed without GNU extension
> is simply wrong.
Fair enough. I hope you don't mind my leaving a line explaining the
cryptic "[snrt][tdh]" to save Dscho a couple of seconds next time :-).
>> + COUNT=$(($(sed -n "s/^# Th[^0-9]*\([1-9][0-9]*\)[snrt][tdh] commit message.*:/\1/p" \
>> < "$SQUASH_MSG" | sed -ne '$p')+1))
>> echo "# This is a combination of $COUNT commits."
>> sed -e 1d -e '2,/^./{
>> @@ -315,10 +321,26 @@ make_squash_message () {
>> echo
>> git cat-file commit HEAD | sed -e '1,/^$/d'
>> fi
>> - echo
>> - echo "# This is the $(nth_string $COUNT) commit message:"
>> - echo
>> - git cat-file commit $1 | sed -e '1,/^$/d'
>> + case $1 in
>> + squash)
>> + echo
>> + echo "# This is the $(nth_string $COUNT) commit message:"
>> + echo
>> + git cat-file commit $2 | sed -e '1,/^$/d'
>> + ;;
>> + fixup)
>> + echo
>> + echo "# The $(nth_string $COUNT) commit message will be skipped:"
>> + echo
>> + # Comment the lines of the commit message out using
>> + # "#" rather than "# " (a) to make them more distinct
>> + # from the explanatory comments added by this function
>> + # and (b) to make it less likely that the sed regexp
>> + # above will be confused by a commented-out commit
>> + # message.
>
> Use "# " as prefix and you won't have to worry about a line in the log
> message that begins with " Th", no?
The scenario seems pretty unlikely to me. The line would not only
have to start with " Th" but also match the rest of the regexp. And
as far as I can see, the only ill effect of a mismatch would be to
throw off COUNT, which itself is only used in the instruction
comments.
By the way, if you are really worried about accidental matches to the
regexp, this is not the end of the story. It could be that a squashed
commit's log message has lines that match the regexp; e.g.,
commit -m '# This is my 380th commit message today:'
The commented-out line survives this first commit and would confuse an
interactive squash (with or without my patch).
Amusingly, if you want to indicate at commit time that a commit
message should be omitted at rebase time, you can add a comment
character intentionally:
commit -m '# this comment will be stripped out at the next squash'
This peculiarity also has nothing to do with the new "fixup" feature.
> In any case, I agree that a comment like this is necessary to warn anybody
> who will be touching the code that the COUNT=$((...)) needs to avoid
> matching what is produced here, but I find the above 6-line comment a bit
> too excessive.
I have substituted a terser alternative. Feel free to edit the
comment or delete it altogether.
Michael
Michael Haggerty (2):
t3404: Use test_commit to set up test repository
Add a command "fixup" to rebase --interactive
Documentation/git-rebase.txt | 13 +++--
git-rebase--interactive.sh | 45 +++++++++++++++----
t/lib-rebase.sh | 7 ++-
t/t3404-rebase-interactive.sh | 96 +++++++++++++++++++++-------------------
4 files changed, 97 insertions(+), 64 deletions(-)
^ permalink raw reply
* [PATCHv3 1/2] t3404: Use test_commit to set up test repository
From: Michael Haggerty @ 2009-12-07 9:20 UTC (permalink / raw)
To: git; +Cc: gitster, git, Johannes.Schindelin, bgustavsson, Michael Haggerty
In-Reply-To: <cover.1260177312.git.mhagger@alum.mit.edu>
Also adjust "expected" text to reflect the file contents generated by
test_commit, which are slightly different than those generated by the
old code.
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
---
t/t3404-rebase-interactive.sh | 66 ++++++++++++----------------------------
1 files changed, 20 insertions(+), 46 deletions(-)
diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh
index 3a37793..778daf4 100755
--- a/t/t3404-rebase-interactive.sh
+++ b/t/t3404-rebase-interactive.sh
@@ -16,53 +16,26 @@ set_fake_editor
# set up two branches like this:
#
-# A - B - C - D - E
+# A - B - C - D - E (master)
# \
-# F - G - H
+# F - G - H (branch1)
# \
-# I
+# I (branch2)
#
-# where B, D and G touch the same file.
+# where A, B, D and G touch the same file.
test_expect_success 'setup' '
- : > file1 &&
- git add file1 &&
- test_tick &&
- git commit -m A &&
- git tag A &&
- echo 1 > file1 &&
- test_tick &&
- git commit -m B file1 &&
- : > file2 &&
- git add file2 &&
- test_tick &&
- git commit -m C &&
- echo 2 > file1 &&
- test_tick &&
- git commit -m D file1 &&
- : > file3 &&
- git add file3 &&
- test_tick &&
- git commit -m E &&
+ test_commit A file1 &&
+ test_commit B file1 &&
+ test_commit C file2 &&
+ test_commit D file1 &&
+ test_commit E file3 &&
git checkout -b branch1 A &&
- : > file4 &&
- git add file4 &&
- test_tick &&
- git commit -m F &&
- git tag F &&
- echo 3 > file1 &&
- test_tick &&
- git commit -m G file1 &&
- : > file5 &&
- git add file5 &&
- test_tick &&
- git commit -m H &&
+ test_commit F file4 &&
+ test_commit G file1 &&
+ test_commit H file5 &&
git checkout -b branch2 F &&
- : > file6 &&
- git add file6 &&
- test_tick &&
- git commit -m I &&
- git tag I
+ test_commit I file6
'
test_expect_success 'no changes are a nop' '
@@ -111,19 +84,20 @@ test_expect_success 'exchange two commits' '
cat > expect << EOF
diff --git a/file1 b/file1
-index e69de29..00750ed 100644
+index f70f10e..fd79235 100644
--- a/file1
+++ b/file1
-@@ -0,0 +1 @@
-+3
+@@ -1 +1 @@
+-A
++G
EOF
cat > expect2 << EOF
<<<<<<< HEAD
-2
+D
=======
-3
->>>>>>> b7ca976... G
+G
+>>>>>>> 91201e5... G
EOF
test_expect_success 'stop on conflicting pick' '
--
1.6.5.5
^ permalink raw reply related
* [PATCHv3 2/2] Add a command "fixup" to rebase --interactive
From: Michael Haggerty @ 2009-12-07 9:20 UTC (permalink / raw)
To: git; +Cc: gitster, git, Johannes.Schindelin, bgustavsson, Michael Haggerty
In-Reply-To: <cover.1260177312.git.mhagger@alum.mit.edu>
The command is like "squash", except that it discards the commit message
of the corresponding commit.
Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
---
Documentation/git-rebase.txt | 13 +++++++----
git-rebase--interactive.sh | 45 +++++++++++++++++++++++++++++++---------
t/lib-rebase.sh | 7 +++--
t/t3404-rebase-interactive.sh | 30 +++++++++++++++++++++++++++
4 files changed, 77 insertions(+), 18 deletions(-)
diff --git a/Documentation/git-rebase.txt b/Documentation/git-rebase.txt
index ca5e1e8..9b648ec 100644
--- a/Documentation/git-rebase.txt
+++ b/Documentation/git-rebase.txt
@@ -382,9 +382,12 @@ If you just want to edit the commit message for a commit, replace the
command "pick" with the command "reword".
If you want to fold two or more commits into one, replace the command
-"pick" with "squash" for the second and subsequent commit. If the
-commits had different authors, it will attribute the squashed commit to
-the author of the first commit.
+"pick" for the second and subsequent commits with "squash" or "fixup".
+If the commits had different authors, the folded commit will be
+attributed to the author of the first commit. The suggested commit
+message for the folded commit is the concatenation of the commit
+messages of the first commit and of those with the "squash" command,
+but omits the commit messages of commits with the "fixup" command.
'git-rebase' will stop when "pick" has been replaced with "edit" or
when a command fails due to merge errors. When you are done editing
@@ -512,8 +515,8 @@ Easy case: The changes are literally the same.::
Hard case: The changes are not the same.::
This happens if the 'subsystem' rebase had conflicts, or used
- `\--interactive` to omit, edit, or squash commits; or if the
- upstream used one of `commit \--amend`, `reset`, or
+ `\--interactive` to omit, edit, squash, or fixup commits; or
+ if the upstream used one of `commit \--amend`, `reset`, or
`filter-branch`.
diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh
index 0bd3bf7..cd2dce1 100755
--- a/git-rebase--interactive.sh
+++ b/git-rebase--interactive.sh
@@ -302,7 +302,10 @@ nth_string () {
make_squash_message () {
if test -f "$SQUASH_MSG"; then
- COUNT=$(($(sed -n "s/^# This is [^0-9]*\([1-9][0-9]*\).*/\1/p" \
+ # We want to be careful about matching only the commit
+ # message comment lines generated by this function.
+ # "[snrt][tdh]" matches the nth_string endings.
+ COUNT=$(($(sed -n "s/^# Th[^0-9]*\([1-9][0-9]*\)[snrt][tdh] commit message.*:/\1/p" \
< "$SQUASH_MSG" | sed -ne '$p')+1))
echo "# This is a combination of $COUNT commits."
sed -e 1d -e '2,/^./{
@@ -315,10 +318,23 @@ make_squash_message () {
echo
git cat-file commit HEAD | sed -e '1,/^$/d'
fi
- echo
- echo "# This is the $(nth_string $COUNT) commit message:"
- echo
- git cat-file commit $1 | sed -e '1,/^$/d'
+ case $1 in
+ squash)
+ echo
+ echo "# This is the $(nth_string $COUNT) commit message:"
+ echo
+ git cat-file commit $2 | sed -e '1,/^$/d'
+ ;;
+ fixup)
+ echo
+ echo "# The $(nth_string $COUNT) commit message will be skipped:"
+ echo
+ # Comment the lines of the commit message out using
+ # "#" rather than "# " to make them less likely to
+ # confuse the sed regexp above.
+ git cat-file commit $2 | sed -e '1,/^$/d' -e 's/^/#/'
+ ;;
+ esac
}
peek_next_command () {
@@ -367,20 +383,28 @@ do_next () {
warn
exit 0
;;
- squash|s)
- comment_for_reflog squash
+ squash|s|fixup|f)
+ case "$command" in
+ squash|s)
+ squash_style=squash
+ ;;
+ fixup|f)
+ squash_style=fixup
+ ;;
+ esac
+ comment_for_reflog $squash_style
test -f "$DONE" && has_action "$DONE" ||
- die "Cannot 'squash' without a previous commit"
+ die "Cannot '$squash_style' without a previous commit"
mark_action_done
- make_squash_message $sha1 > "$MSG"
+ make_squash_message $squash_style $sha1 > "$MSG"
failed=f
author_script=$(get_author_ident_from_commit HEAD)
output git reset --soft HEAD^
pick_one -n $sha1 || failed=t
case "$(peek_next_command)" in
- squash|s)
+ squash|s|fixup|f)
USE_OUTPUT=output
MSG_OPT=-F
EDIT_OR_FILE="$MSG"
@@ -768,6 +792,7 @@ first and then run 'git rebase --continue' again."
# r, reword = use commit, but edit the commit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
+# f, fixup = like "squash", but discard this commit's log message
#
# If you remove a line here THAT COMMIT WILL BE LOST.
# However, if you remove everything, the rebase will be aborted.
diff --git a/t/lib-rebase.sh b/t/lib-rebase.sh
index 62f452c..f4dda02 100644
--- a/t/lib-rebase.sh
+++ b/t/lib-rebase.sh
@@ -9,8 +9,9 @@
#
# "[<lineno1>] [<lineno2>]..."
#
-# If a line number is prefixed with "squash", "edit", or "reword", the
-# respective line's command will be replaced with the specified one.
+# If a line number is prefixed with "squash", "fixup", "edit", or
+# "reword", the respective line's command will be replaced with the
+# specified one.
set_fake_editor () {
echo "#!$SHELL_PATH" >fake-editor.sh
@@ -32,7 +33,7 @@ cat "$1".tmp
action=pick
for line in $FAKE_LINES; do
case $line in
- squash|edit|reword)
+ squash|fixup|edit|reword)
action="$line";;
*)
echo sed -n "${line}s/^pick/$action/p"
diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh
index 778daf4..ea26115 100755
--- a/t/t3404-rebase-interactive.sh
+++ b/t/t3404-rebase-interactive.sh
@@ -235,6 +235,36 @@ test_expect_success 'multi-squash only fires up editor once' '
test 1 = $(git show | grep ONCE | wc -l)
'
+test_expect_success 'multi-fixup only fires up editor once' '
+ git checkout -b multi-fixup E &&
+ base=$(git rev-parse HEAD~4) &&
+ FAKE_COMMIT_AMEND="ONCE" FAKE_LINES="1 fixup 2 fixup 3 fixup 4" \
+ git rebase -i $base &&
+ test $base = $(git rev-parse HEAD^) &&
+ test 1 = $(git show | grep ONCE | wc -l) &&
+ git checkout to-be-rebased &&
+ git branch -D multi-fixup
+'
+
+cat > expect-squash-fixup << EOF
+B
+
+D
+
+ONCE
+EOF
+
+test_expect_success 'squash and fixup generate correct log messages' '
+ git checkout -b squash-fixup E &&
+ base=$(git rev-parse HEAD~4) &&
+ FAKE_COMMIT_AMEND="ONCE" FAKE_LINES="1 fixup 2 squash 3 fixup 4" \
+ git rebase -i $base &&
+ git cat-file commit HEAD | sed -e 1,/^\$/d > actual-squash-fixup &&
+ test_cmp expect-squash-fixup actual-squash-fixup &&
+ git checkout to-be-rebased &&
+ git branch -D squash-fixup
+'
+
test_expect_success 'squash works as expected' '
for n in one two three four
do
--
1.6.5.5
^ permalink raw reply related
* Re: [PATCH v2] Detailed diagnosis when parsing an object name fails.
From: Matthieu Moy @ 2009-12-07 10:07 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <7vk4wz9rbt.fsf@alter.siamese.dyndns.org>
Junio C Hamano <gitster@pobox.com> writes:
> Matthieu Moy <Matthieu.Moy@grenoble-inp.fr> writes:
>
> The second round still had a few compilation warnings (turned to errors in
> my environment) so I fixed them up somewhat.
Thanks. For some reasons, I had CFLAGS=-g and I didn't see the
warnings :-(
> I stopped before getting a
> clean compile, though---you will still get:
>
> sha1_name.c: In function 'get_sha1_with_mode_1':
> sha1_name.c:956: error: 'object_name' may be used uninitialized in this function
This one is strange. I don't git it with gcc 4.4, even with -Wall
-Werror. And indeed, object_name is initialized when !gently, which is
precisely when we use it.
I did
- char *object_name;
+ char *object_name = NULL;
to make sure the warning goes away on your machine, but I don't
understand what's going on.
> cache.h | 4 ++--
> sha1_name.c | 2 +-
Squashed into v3, together with initialisation of object_name, and two
s/int/unsigned/ to please gcc -Wextra.
--
Matthieu Moy
http://www-verimag.imag.fr/~moy/
^ permalink raw reply
* [PATCH v3] Detailed diagnosis when parsing an object name fails.
From: Matthieu Moy @ 2009-12-07 10:10 UTC (permalink / raw)
To: git, gitster; +Cc: Matthieu Moy
In-Reply-To: <vpqws0zcd1c.fsf@bauges.imag.fr>
The previous error message was the same in many situations (unknown
revision or path not in the working tree). We try to help the user as
much as possible to understand the error, especially with the
sha1:filename notation. In this case, we say whether the sha1 or the
filename is problematic, and diagnose the confusion between
relative-to-root and relative-to-$PWD confusion precisely.
The 7 new error messages are tested.
Signed-off-by: Matthieu Moy <Matthieu.Moy@imag.fr>
---
cache.h | 6 ++-
setup.c | 15 +++++-
sha1_name.c | 115 ++++++++++++++++++++++++++++++++++++++--
t/t1506-rev-parse-diagnosis.sh | 69 ++++++++++++++++++++++++
4 files changed, 198 insertions(+), 7 deletions(-)
create mode 100755 t/t1506-rev-parse-diagnosis.sh
diff --git a/cache.h b/cache.h
index 0e69384..c122bfa 100644
--- a/cache.h
+++ b/cache.h
@@ -708,7 +708,11 @@ static inline unsigned int hexval(unsigned char c)
#define DEFAULT_ABBREV 7
extern int get_sha1(const char *str, unsigned char *sha1);
-extern int get_sha1_with_mode(const char *str, unsigned char *sha1, unsigned *mode);
+extern int get_sha1_with_mode_1(const char *str, unsigned char *sha1, unsigned *mode, int gently, const char *prefix);
+static inline int get_sha1_with_mode(const char *str, unsigned char *sha1, unsigned *mode)
+{
+ return get_sha1_with_mode_1(str, sha1, mode, 1, NULL);
+}
extern int get_sha1_hex(const char *hex, unsigned char *sha1);
extern char *sha1_to_hex(const unsigned char *sha1); /* static buffer result! */
extern int read_ref(const char *filename, unsigned char *sha1);
diff --git a/setup.c b/setup.c
index f67250b..5792eb7 100644
--- a/setup.c
+++ b/setup.c
@@ -74,6 +74,18 @@ int check_filename(const char *prefix, const char *arg)
die_errno("failed to stat '%s'", arg);
}
+static void NORETURN die_verify_filename(const char *prefix, const char *arg)
+{
+ unsigned char sha1[20];
+ unsigned mode;
+ /* try a detailed diagnostic ... */
+ get_sha1_with_mode_1(arg, sha1, &mode, 0, prefix);
+ /* ... or fall back the most general message. */
+ die("ambiguous argument '%s': unknown revision or path not in the working tree.\n"
+ "Use '--' to separate paths from revisions", arg);
+
+}
+
/*
* Verify a filename that we got as an argument for a pathspec
* entry. Note that a filename that begins with "-" never verifies
@@ -87,8 +99,7 @@ void verify_filename(const char *prefix, const char *arg)
die("bad flag '%s' used after filename", arg);
if (check_filename(prefix, arg))
return;
- die("ambiguous argument '%s': unknown revision or path not in the working tree.\n"
- "Use '--' to separate paths from revisions", arg);
+ die_verify_filename(prefix, arg);
}
/*
diff --git a/sha1_name.c b/sha1_name.c
index 44bb62d..ca8f9db 100644
--- a/sha1_name.c
+++ b/sha1_name.c
@@ -804,7 +804,96 @@ int get_sha1(const char *name, unsigned char *sha1)
return get_sha1_with_mode(name, sha1, &unused);
}
-int get_sha1_with_mode(const char *name, unsigned char *sha1, unsigned *mode)
+/* Must be called only when object_name:filename doesn't exist. */
+static void diagnose_invalid_sha1_path(const char *prefix,
+ const char *filename,
+ const unsigned char *tree_sha1,
+ const char *object_name)
+{
+ struct stat st;
+ unsigned char sha1[20];
+ unsigned mode;
+
+ if (!prefix)
+ prefix = "";
+
+ if (!lstat(filename, &st))
+ die("Path '%s' exists on disk, but not in '%s'.",
+ filename, object_name);
+ if (errno == ENOENT || errno == ENOTDIR) {
+ char *fullname = xmalloc(strlen(filename)
+ + strlen(prefix) + 1);
+ strcpy(fullname, prefix);
+ strcat(fullname, filename);
+
+ if (!get_tree_entry(tree_sha1, fullname,
+ sha1, &mode)) {
+ die("Path '%s' exists, but not '%s'.\n"
+ "Did you mean '%s:%s'?",
+ fullname,
+ filename,
+ object_name,
+ fullname);
+ }
+ die("Path '%s' does not exist in '%s'",
+ filename, object_name);
+ }
+}
+
+/* Must be called only when :stage:filename doesn't exist. */
+static void diagnose_invalid_index_path(int stage,
+ const char *prefix,
+ const char *filename)
+{
+ struct stat st;
+ struct cache_entry *ce;
+ int pos;
+ unsigned namelen = strlen(filename);
+ unsigned fullnamelen;
+ char *fullname;
+
+ if (!prefix)
+ prefix = "";
+
+ /* Wrong stage number? */
+ pos = cache_name_pos(filename, namelen);
+ if (pos < 0)
+ pos = -pos - 1;
+ ce = active_cache[pos];
+ if (ce_namelen(ce) == namelen &&
+ !memcmp(ce->name, filename, namelen))
+ die("Path '%s' is in the index, but not at stage %d.\n"
+ "Did you mean ':%d:%s'?",
+ filename, stage,
+ ce_stage(ce), filename);
+
+ /* Confusion between relative and absolute filenames? */
+ fullnamelen = namelen + strlen(prefix);
+ fullname = xmalloc(fullnamelen + 1);
+ strcpy(fullname, prefix);
+ strcat(fullname, filename);
+ pos = cache_name_pos(fullname, fullnamelen);
+ if (pos < 0)
+ pos = -pos - 1;
+ ce = active_cache[pos];
+ if (ce_namelen(ce) == fullnamelen &&
+ !memcmp(ce->name, fullname, fullnamelen))
+ die("Path '%s' is in the index, but not '%s'.\n"
+ "Did you mean ':%d:%s'?",
+ fullname, filename,
+ ce_stage(ce), fullname);
+
+ if (!lstat(filename, &st))
+ die("Path '%s' exists on disk, but not in the index.", filename);
+ if (errno == ENOENT || errno == ENOTDIR)
+ die("Path '%s' does not exist (neither on disk nor in the index).",
+ filename);
+
+ free(fullname);
+}
+
+
+int get_sha1_with_mode_1(const char *name, unsigned char *sha1, unsigned *mode, int gently, const char *prefix)
{
int ret, bracket_depth;
int namelen = strlen(name);
@@ -850,6 +939,8 @@ int get_sha1_with_mode(const char *name, unsigned char *sha1, unsigned *mode)
}
pos++;
}
+ if (!gently)
+ diagnose_invalid_index_path(stage, prefix, cp);
return -1;
}
for (cp = name, bracket_depth = 0; *cp; cp++) {
@@ -862,9 +953,25 @@ int get_sha1_with_mode(const char *name, unsigned char *sha1, unsigned *mode)
}
if (*cp == ':') {
unsigned char tree_sha1[20];
- if (!get_sha1_1(name, cp-name, tree_sha1))
- return get_tree_entry(tree_sha1, cp+1, sha1,
- mode);
+ char *object_name = NULL;
+ if (!gently) {
+ object_name = xmalloc(cp-name+1);
+ strncpy(object_name, name, cp-name);
+ object_name[cp-name] = '\0';
+ }
+ if (!get_sha1_1(name, cp-name, tree_sha1)) {
+ const char *filename = cp+1;
+ ret = get_tree_entry(tree_sha1, filename, sha1, mode);
+ if (!gently) {
+ diagnose_invalid_sha1_path(prefix, filename,
+ tree_sha1, object_name);
+ free(object_name);
+ }
+ return ret;
+ } else {
+ if (!gently)
+ die("Invalid object name '%s'.", object_name);
+ }
}
return ret;
}
diff --git a/t/t1506-rev-parse-diagnosis.sh b/t/t1506-rev-parse-diagnosis.sh
new file mode 100755
index 0000000..af721f9
--- /dev/null
+++ b/t/t1506-rev-parse-diagnosis.sh
@@ -0,0 +1,69 @@
+#!/bin/sh
+
+test_description='test git rev-parse diagnosis for invalid argument'
+
+exec </dev/null
+
+. ./test-lib.sh
+
+HASH_file=
+
+test_expect_success 'set up basic repo' '
+ echo one > file.txt &&
+ mkdir subdir &&
+ echo two > subdir/file.txt &&
+ echo three > subdir/file2.txt &&
+ git add . &&
+ git commit -m init &&
+ echo four > index-only.txt &&
+ git add index-only.txt &&
+ echo five > disk-only.txt
+'
+
+test_expect_success 'correct file objects' '
+ HASH_file=$(git rev-parse HEAD:file.txt) &&
+ git rev-parse HEAD:subdir/file.txt &&
+ git rev-parse :index-only.txt &&
+ (cd subdir &&
+ git rev-parse HEAD:subdir/file2.txt &&
+ test $HASH_file = $(git rev-parse HEAD:file.txt) &&
+ test $HASH_file = $(git rev-parse :file.txt) &&
+ test $HASH_file = $(git rev-parse :0:file.txt) )
+'
+
+test_expect_success 'incorrect revision id' '
+ test_must_fail git rev-parse foobar:file.txt 2>error &&
+ grep "Invalid object name '"'"'foobar'"'"'." error &&
+ test_must_fail git rev-parse foobar 2> error &&
+ grep "unknown revision or path not in the working tree." error
+'
+
+test_expect_success 'incorrect file in sha1:path' '
+ test_must_fail git rev-parse HEAD:nothing.txt 2> error &&
+ grep "fatal: Path '"'"'nothing.txt'"'"' does not exist in '"'"'HEAD'"'"'" error &&
+ test_must_fail git rev-parse HEAD:index-only.txt 2> error &&
+ grep "fatal: Path '"'"'index-only.txt'"'"' exists on disk, but not in '"'"'HEAD'"'"'." error &&
+ (cd subdir &&
+ test_must_fail git rev-parse HEAD:file2.txt 2> error &&
+ grep "Did you mean '"'"'HEAD:subdir/file2.txt'"'"'?" error )
+'
+
+test_expect_success 'incorrect file in :path and :N:path' '
+ test_must_fail git rev-parse :nothing.txt 2> error &&
+ grep "fatal: Path '"'"'nothing.txt'"'"' does not exist (neither on disk nor in the index)." error &&
+ test_must_fail git rev-parse :1:nothing.txt 2> error &&
+ grep "Path '"'"'nothing.txt'"'"' does not exist (neither on disk nor in the index)." error &&
+ test_must_fail git rev-parse :1:file.txt 2> error &&
+ grep "Did you mean '"'"':0:file.txt'"'"'?" error &&
+ (cd subdir &&
+ test_must_fail git rev-parse :1:file.txt 2> error &&
+ grep "Did you mean '"'"':0:file.txt'"'"'?" error &&
+ test_must_fail git rev-parse :file2.txt 2> error &&
+ grep "Did you mean '"'"':0:subdir/file2.txt'"'"'?" error &&
+ test_must_fail git rev-parse :2:file2.txt 2> error &&
+ grep "Did you mean '"'"':0:subdir/file2.txt'"'"'?" error) &&
+ test_must_fail git rev-parse :disk-only.txt 2> error &&
+ grep "fatal: Path '"'"'disk-only.txt'"'"' exists on disk, but not in the index." error
+'
+
+test_done
--
1.6.6.rc0.355.gcb53a.dirty
^ permalink raw reply related
* core.worktree bug
From: Robin Rosenberg @ 2009-12-07 10:15 UTC (permalink / raw)
To: git
According to git-config(1)
core.worktree
Set the path to the working tree. The value will not be used in combination with repositories found automatically in a
.git directory (i.e. $GIT_DIR is not set). This can be overridden by the GIT_WORK_TREE environment variable and the
--work-tree command line option. It can be a absolute path or relative path to the directory specified by --git-dir or
GIT_DIR. Note: If --git-dir or GIT_DIR are specified but none of --work-tree, GIT_WORK_TREE and core.worktree is
specified, the current working directory is regarded as the top directory of your working tree.
this setting is not used if GIT_DIR is set. But when I try it out
$ mkdir r1
$ mkdir r2
$ cd r2
$ git init
Initialized empty Git repository in /home/me/tmp/r2/.git/
$ date >f
$ git add f
$ git commit -m "f"
f
1 files changed, 1 insertions(+), 0 deletions(-)
create mode 100644 f
$ git status
# On branch master
nothing to commit (working directory clean)
=> Nothing interesting here. It comes here:
$ git config core.worktree $(cd ../r1;pwd)
$ git status
# On branch master
# Changed but not updated:
# (use "git add/rm <file>..." to update what will be committed)
# (use "git checkout -- <file>..." to discard changes in working directory)
#
# deleted: f
#
no changes added to commit (use "git add" and/or "git commit -a")
=> Seems the config is actually honored even though GIT_DIR is not set.
Bisect tells me 4f38f6b5bafb1f7f85c7b54d0bb0a0e977cd947c broke it. My main point is that I am
implementing this in JGit so I want the same behaviour. Question: Should we try to fix this
in git so it matches the documentation or fix the documentation to match behaviour.
The breakage appeared over a year ago and no one has complained.
-- robin
My bisection script:
#!/bin/bash
test_description="CEILING"
. ./test-lib.sh
test_expect_success \
"ceiling" \
"
rm -rf r1 r2 &&
mkdir r1 r2 &&
(cd r2 &&
git init &&
date >f &&
git add f &&
echo ADD &&
git commit -m f &&
echo COMMIT &&
git diff --exit-code f &&
echo DIFF &&
git config core.worktree \$(cd ../r1/..;pwd) &&
echo CONFIG &&
(unset GIT_DIR;git diff --exit-code -- f) &&
echo DIFF
)
"
test_don
^ permalink raw reply
* [PATCH v2] cvsserver: make the output of 'update' more compatible with cvs.
From: Sergei Organov @ 2009-12-07 11:11 UTC (permalink / raw)
To: git; +Cc: gitster
In-Reply-To: <87zl5z4y0w.fsf@osv.gnss.ru>
Native cvs update outputs the string "cvs update: Updating <DIR>" for
every directory it processes (to stderr) unless -q or -Q is given on
comman-line. This is used, e.g., by emacs pcl-cvs to split files by
directory. This commit implements this feature in cvsserver.
Signed-off-by: Sergei Organov <osv@javad.com>
---
git-cvsserver.perl | 16 ++++++++++++++++
1 files changed, 16 insertions(+), 0 deletions(-)
diff --git a/git-cvsserver.perl b/git-cvsserver.perl
index 6dc45f5..f4c75bb 100755
--- a/git-cvsserver.perl
+++ b/git-cvsserver.perl
@@ -981,6 +981,8 @@ sub req_update
#$log->debug("update state : " . Dumper($state));
+ my $last_dirname = "///";
+
# foreach file specified on the command line ...
foreach my $filename ( @{$state->{args}} )
{
@@ -988,6 +990,20 @@ sub req_update
$log->debug("Processing file $filename");
+ unless ( $state->{globaloptions}{-Q} || $state->{globaloptions}{-q} )
+ {
+ my $cur_dirname = dirname($filename);
+ if ( $cur_dirname ne $last_dirname )
+ {
+ $last_dirname = $cur_dirname;
+ if ( $cur_dirname eq "" )
+ {
+ $cur_dirname = ".";
+ }
+ print "E cvs update: Updating $cur_dirname\n";
+ }
+ }
+
# if we have a -C we should pretend we never saw modified stuff
if ( exists ( $state->{opt}{C} ) )
{
--
1.6.6.rc0.67.gc0456.dirty
^ permalink raw reply related
* Re: Speedlimit at "git clone"
From: Baz @ 2009-12-07 11:15 UTC (permalink / raw)
To: Daniel Stenberg; +Cc: Jeff King, git
In-Reply-To: <alpine.DEB.2.00.0912061912180.19656@tvnag.unkk.fr>
2009/12/6 Daniel Stenberg <daniel@haxx.se>:
> On Sun, 6 Dec 2009, Jeff King wrote:
>
>>>> how can i limit the download speed at "git clone"?
>>>>
>>> no one any idea?
>>
>> Git has no internal support for doing this.
>
> libcurl provides such a feature so if the clone is done over HTTP it would
> be easy to offer, but I figure it would also be weird to only provide it
> over a single particular transfer method...
There is always 'trickle'.
http://monkey.org/~marius/pages/?page=trickle
I think this is the preload-based tool Peff was thinking of. I've not
used it with git, but I have used it successfully limiting bandwidth
for other downloads.
-Baz
>
> --
>
> / daniel.haxx.se
> --
> 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: [PATCHv3 0/2] Add a "fixup" command to "rebase --interactive"
From: Johannes Schindelin @ 2009-12-07 11:21 UTC (permalink / raw)
To: Michael Haggerty; +Cc: git, gitster, git, bgustavsson
In-Reply-To: <cover.1260177312.git.mhagger@alum.mit.edu>
Hi,
On Mon, 7 Dec 2009, Michael Haggerty wrote:
> Junio C Hamano wrote:
> > Michael Haggerty <mhagger@alum.mit.edu> writes:
> >
> >> diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh
> >> index 0bd3bf7..a7de5ea 100755
> >> --- a/git-rebase--interactive.sh
> >> +++ b/git-rebase--interactive.sh
> >> @@ -302,7 +302,13 @@ nth_string () {
> >>
> >> make_squash_message () {
> >> if test -f "$SQUASH_MSG"; then
> >> - COUNT=$(($(sed -n "s/^# This is [^0-9]*\([1-9][0-9]*\).*/\1/p" \
> >> + # We want to be careful about matching only the commit
> >> + # message comment lines generated by this function.
> >
> >> + # But supposedly some sed versions don't handle "\|"
> >> + # correctly, so instead of "\(st\|nd\|rd\|th\)", use
> >> + # the less accurate "[snrt][tdh]" to match the
> >> + # nth_string endings.
> >
> > I'd drop this comment; blaming POSIX-compliant sed without GNU extension
> > is simply wrong.
>
> Fair enough. I hope you don't mind my leaving a line explaining the
> cryptic "[snrt][tdh]" to save Dscho a couple of seconds next time :-).
Thanks, very much appreciated here.
My ACK for the patches is still valid.
^ permalink raw reply
* Re: [PATCHv2 2/2] Add a command "fixup" to rebase --interactive
From: Sverre Rabbelier @ 2009-12-07 11:26 UTC (permalink / raw)
To: Michael Haggerty; +Cc: git, gitster, git, Johannes.Schindelin, bgustavsson
In-Reply-To: <ced6765cff6225a05f196a6896ab577850979ab1.1260099005.git.mhagger@alum.mit.edu>
Heya,
On Mon, Dec 7, 2009 at 05:22, Michael Haggerty <mhagger@alum.mit.edu> wrote:
> The command is like "squash", except that it discards the commit message
> of the corresponding commit.
No no, wait, wasn't "fixup" supposed to let you just edit the commit
message of the commit you're fixing up? :(
--
Cheers,
Sverre Rabbelier
^ permalink raw reply
* [RFC/PATCHv10 00/11] git notes
From: Johan Herland @ 2009-12-07 11:27 UTC (permalink / raw)
To: git; +Cc: gitster, johan, spearce
Hi,
Here is the 10th iteration of the git-notes series. Changes in this
iteration are as follows:
Changes to existing patches:
- Rebased onto 488bdf2... (Fix crasher on encountering SHA1-like non-note
in notes tree) (There are no conflicts resolved by this, but a test in
this series crashes without the crash fix in 488bdf2...).
- Yet another rewrite of the fast-import patch. After trying to implement
Shawn's suggestions, I found that hacking the mode bits of note entries
could not work, since they are stripped by a mktree()/load_tree()
round-trip. The new versions treats _all_ entries with note-compatible
paths (40 hex chars, not including directory separators) as note entries
(to be subjected to fanout adjustments) in branches where there are note
activity (one or more 'N' commands).
Branches without note activity are not touched, of course.
- Otherwise, Shawn's suggestions to the previous iteration have been
incorporated.
- Extended t9301 tests to verify that non-notes residing in a notes tree
are not clobbered by the fast-import patch.
- Fix t9301 test #12 to not "cheat" (by 'deleteall' followed by a few
additions). Instead, remove notes one-by-one to verify correct
fanout consolidation.
- Minor cleanups here and there
If Shawn is OK with the fast-import patch, I believe that at least
patches #1 - #3 (and possibly #4 - #5) are ready for 'next'.
Patches #6 - #11 drastically extend the notes API. Since there are
currently no users of that API, and it has not been discussed much
on the list (although these patches have already been present in a
few iterations), I would still consider them RFC quality.
TODO:
- Builtin-ify git-notes shell script to take advantage of notes API
- Garbage collect notes whose referenced object is unreachable (gc_notes())
- Handle note objects that are not blobs, but trees
Have fun! :)
...Johan
Johan Herland (11):
fast-import: Proper notes tree manipulation
Rename t9301 to t9350, to make room for more fast-import tests
Add more testcases to test fast-import of notes
Minor style fixes to notes.c
Notes API: get_commit_notes() -> format_note() + remove the commit restriction
Notes API: init_notes(): Initialize the notes tree from the given notes ref
Notes API: add_note(): Add note objects to the internal notes tree structure
Notes API: get_note(): Return the note annotating the given object
Notes API: for_each_note(): Traverse the entire notes tree with a callback
Notes API: Allow multiple concurrent notes trees with new struct notes_tree
Refactor notes concatenation into a flexible interface for combining notes
fast-import.c | 134 +++++-
notes.c | 345 +++++++++----
notes.h | 114 ++++-
pretty.c | 9 +-
t/t9300-fast-import.sh | 156 +++++-
t/t9301-fast-import-notes.sh | 623 ++++++++++++++++++++++
t/{t9301-fast-export.sh => t9350-fast-export.sh} | 0
7 files changed, 1259 insertions(+), 122 deletions(-)
create mode 100755 t/t9301-fast-import-notes.sh
rename t/{t9301-fast-export.sh => t9350-fast-export.sh} (100%)
^ permalink raw reply
* [RFC/PATCHv10 02/11] Rename t9301 to t9350, to make room for more fast-import tests
From: Johan Herland @ 2009-12-07 11:27 UTC (permalink / raw)
To: git; +Cc: gitster, johan, spearce
In-Reply-To: <1260185254-1523-1-git-send-email-johan@herland.net>
Signed-off-by: Johan Herland <johan@herland.net>
---
t/{t9301-fast-export.sh => t9350-fast-export.sh} | 0
1 files changed, 0 insertions(+), 0 deletions(-)
rename t/{t9301-fast-export.sh => t9350-fast-export.sh} (100%)
diff --git a/t/t9301-fast-export.sh b/t/t9350-fast-export.sh
similarity index 100%
rename from t/t9301-fast-export.sh
rename to t/t9350-fast-export.sh
--
1.6.5.3.433.g11067
^ permalink raw reply
* [RFC/PATCHv10 01/11] fast-import: Proper notes tree manipulation
From: Johan Herland @ 2009-12-07 11:27 UTC (permalink / raw)
To: git; +Cc: gitster, johan, spearce
In-Reply-To: <1260185254-1523-1-git-send-email-johan@herland.net>
This patch teaches 'git fast-import' to automatically organize note objects
in a fast-import stream into an appropriate fanout structure. The notes API
in notes.h is NOT used to accomplish this, because trying to keep the
fast-import and notes data structures in sync would yield a significantly
larger patch with higher complexity.
Note objects are added with the 'N' command, and accounted for with a
per-branch counter, which is used to trigger fanout restructuring when
needed. Note that when restructuring the branch tree, _any_ entry whose
path consists of 40 hex chars (not including directory separators) will
be recognized as a note object. It is therefore not advisable to
manipulate note entries with M/D/R/C commands.
Since note objects are stored in the same tree structure as other objects,
the unloading and reloading of a fast-import branches handle note objects
transparently.
This patch has been improved by the following contributions:
- Shawn O. Pearce: Several style- and logic-related improvements
Cc: Shawn O. Pearce <spearce@spearce.org>
Signed-off-by: Johan Herland <johan@herland.net>
---
As stated in the cover letter, I simply cannot store note information in
the tree_entry mode bits. So, I chose this somewhat more simple and crude
approach, which I still think solves the problems quite nicely.
Have fun! :)
...Johan
fast-import.c | 134 +++++++++++++++++++++++++++++++++++++++--
t/t9300-fast-import.sh | 156 ++++++++++++++++++++++++++++++++++++++++++++----
2 files changed, 272 insertions(+), 18 deletions(-)
diff --git a/fast-import.c b/fast-import.c
index dd3c99d..f04cd17 100644
--- a/fast-import.c
+++ b/fast-import.c
@@ -245,6 +245,7 @@ struct branch
const char *name;
struct tree_entry branch_tree;
uintmax_t last_commit;
+ uintmax_t num_notes;
unsigned active : 1;
unsigned pack_id : PACK_ID_BITS;
unsigned char sha1[20];
@@ -693,6 +694,7 @@ static struct branch *new_branch(const char *name)
b->table_next_branch = branch_table[hc];
b->branch_tree.versions[0].mode = S_IFDIR;
b->branch_tree.versions[1].mode = S_IFDIR;
+ b->num_notes = 0;
b->active = 0;
b->pack_id = MAX_PACK_ID;
branch_table[hc] = b;
@@ -1860,6 +1862,109 @@ static void load_branch(struct branch *b)
}
}
+static unsigned char convert_num_notes_to_fanout(uintmax_t num_notes)
+{
+ unsigned char fanout = 0;
+ while ((num_notes >>= 8))
+ fanout++;
+ return fanout;
+}
+
+static void construct_path_with_fanout(const char *hex_sha1,
+ unsigned char fanout, char *path)
+{
+ unsigned int i = 0, j = 0;
+ if (fanout >= 20)
+ die("Too large fanout (%u)", fanout);
+ while (fanout) {
+ path[i++] = hex_sha1[j++];
+ path[i++] = hex_sha1[j++];
+ path[i++] = '/';
+ fanout--;
+ }
+ memcpy(path + i, hex_sha1 + j, 40 - j);
+ path[i + 40 - j] = '\0';
+}
+
+static uintmax_t do_change_note_fanout(
+ struct tree_entry *orig_root, struct tree_entry *root,
+ char *hex_sha1, unsigned int hex_sha1_len,
+ char *fullpath, unsigned int fullpath_len,
+ unsigned char fanout)
+{
+ struct tree_content *t = root->tree;
+ struct tree_entry *e, leaf;
+ unsigned int i, tmp_hex_sha1_len, tmp_fullpath_len;
+ uintmax_t num_notes = 0;
+ unsigned char sha1[20];
+ char realpath[60];
+
+ for (i = 0; t && i < t->entry_count; i++) {
+ e = t->entries[i];
+ tmp_hex_sha1_len = hex_sha1_len + e->name->str_len;
+ tmp_fullpath_len = fullpath_len;
+
+ /*
+ * We're interested in EITHER existing note entries (entries
+ * with exactly 40 hex chars in path, not including directory
+ * separators), OR directory entries that may contain note
+ * entries (with < 40 hex chars in path).
+ * Also, each path component in a note entry must be a multiple
+ * of 2 chars.
+ */
+ if (!e->versions[1].mode ||
+ tmp_hex_sha1_len > 40 ||
+ e->name->str_len % 2)
+ continue;
+
+ /* This _may_ be a note entry, or a subdir containing notes */
+ memcpy(hex_sha1 + hex_sha1_len, e->name->str_dat,
+ e->name->str_len);
+ if (tmp_fullpath_len)
+ fullpath[tmp_fullpath_len++] = '/';
+ memcpy(fullpath + tmp_fullpath_len, e->name->str_dat,
+ e->name->str_len);
+ tmp_fullpath_len += e->name->str_len;
+ fullpath[tmp_fullpath_len] = '\0';
+
+ if (tmp_hex_sha1_len == 40 && !get_sha1_hex(hex_sha1, sha1)) {
+ /* This is a note entry */
+ construct_path_with_fanout(hex_sha1, fanout, realpath);
+ if (!strcmp(fullpath, realpath)) {
+ /* Note entry is in correct location */
+ num_notes++;
+ continue;
+ }
+
+ /* Rename fullpath to realpath */
+ if (!tree_content_remove(orig_root, fullpath, &leaf))
+ die("Failed to remove path %s", fullpath);
+ tree_content_set(orig_root, realpath,
+ leaf.versions[1].sha1,
+ leaf.versions[1].mode,
+ leaf.tree);
+ } else if (S_ISDIR(e->versions[1].mode)) {
+ /* This is a subdir that may contain note entries */
+ if (!e->tree)
+ load_tree(e);
+ num_notes += do_change_note_fanout(orig_root, e,
+ hex_sha1, tmp_hex_sha1_len,
+ fullpath, tmp_fullpath_len, fanout);
+ }
+
+ /* The above may have reallocated the current tree_content */
+ t = root->tree;
+ }
+ return num_notes;
+}
+
+static uintmax_t change_note_fanout(struct tree_entry *root,
+ unsigned char fanout)
+{
+ char hex_sha1[40], path[60];
+ return do_change_note_fanout(root, root, hex_sha1, 0, path, 0, fanout);
+}
+
static void file_change_m(struct branch *b)
{
const char *p = command_buf.buf + 2;
@@ -2010,14 +2115,16 @@ static void file_change_cr(struct branch *b, int rename)
leaf.tree);
}
-static void note_change_n(struct branch *b)
+static void note_change_n(struct branch *b, unsigned char old_fanout)
{
const char *p = command_buf.buf + 2;
static struct strbuf uq = STRBUF_INIT;
struct object_entry *oe = oe;
struct branch *s;
unsigned char sha1[20], commit_sha1[20];
+ char path[60];
uint16_t inline_data = 0;
+ unsigned char new_fanout;
/* <dataref> or 'inline' */
if (*p == ':') {
@@ -2071,7 +2178,7 @@ static void note_change_n(struct branch *b)
if (oe->type != OBJ_BLOB)
die("Not a blob (actually a %s): %s",
typename(oe->type), command_buf.buf);
- } else {
+ } else if (!is_null_sha1(sha1)) {
enum object_type type = sha1_object_info(sha1, NULL);
if (type < 0)
die("Blob not found: %s", command_buf.buf);
@@ -2080,8 +2187,17 @@ static void note_change_n(struct branch *b)
typename(type), command_buf.buf);
}
- tree_content_set(&b->branch_tree, sha1_to_hex(commit_sha1), sha1,
- S_IFREG | 0644, NULL);
+ construct_path_with_fanout(sha1_to_hex(commit_sha1), old_fanout, path);
+ if (tree_content_remove(&b->branch_tree, path, NULL))
+ b->num_notes--;
+
+ if (is_null_sha1(sha1))
+ return; /* nothing to insert */
+
+ b->num_notes++;
+ new_fanout = convert_num_notes_to_fanout(b->num_notes);
+ construct_path_with_fanout(sha1_to_hex(commit_sha1), new_fanout, path);
+ tree_content_set(&b->branch_tree, path, sha1, S_IFREG | 0644, NULL);
}
static void file_change_deleteall(struct branch *b)
@@ -2090,6 +2206,7 @@ static void file_change_deleteall(struct branch *b)
hashclr(b->branch_tree.versions[0].sha1);
hashclr(b->branch_tree.versions[1].sha1);
load_tree(&b->branch_tree);
+ b->num_notes = 0;
}
static void parse_from_commit(struct branch *b, char *buf, unsigned long size)
@@ -2213,6 +2330,7 @@ static void parse_new_commit(void)
char *committer = NULL;
struct hash_list *merge_list = NULL;
unsigned int merge_count;
+ unsigned char prev_fanout, new_fanout;
/* Obtain the branch name from the rest of our command */
sp = strchr(command_buf.buf, ' ') + 1;
@@ -2243,6 +2361,8 @@ static void parse_new_commit(void)
load_branch(b);
}
+ prev_fanout = convert_num_notes_to_fanout(b->num_notes);
+
/* file_change* */
while (command_buf.len > 0) {
if (!prefixcmp(command_buf.buf, "M "))
@@ -2254,7 +2374,7 @@ static void parse_new_commit(void)
else if (!prefixcmp(command_buf.buf, "C "))
file_change_cr(b, 0);
else if (!prefixcmp(command_buf.buf, "N "))
- note_change_n(b);
+ note_change_n(b, prev_fanout);
else if (!strcmp("deleteall", command_buf.buf))
file_change_deleteall(b);
else {
@@ -2265,6 +2385,10 @@ static void parse_new_commit(void)
break;
}
+ new_fanout = convert_num_notes_to_fanout(b->num_notes);
+ if (new_fanout != prev_fanout)
+ b->num_notes = change_note_fanout(&b->branch_tree, new_fanout);
+
/* build the tree and the commit */
store_tree(&b->branch_tree);
hashcpy(b->branch_tree.versions[0].sha1,
diff --git a/t/t9300-fast-import.sh b/t/t9300-fast-import.sh
index b49815d..bf8c509 100755
--- a/t/t9300-fast-import.sh
+++ b/t/t9300-fast-import.sh
@@ -1092,9 +1092,12 @@ test_expect_success 'P: fail on blob mark in gitlink' '
### series Q (notes)
###
-note1_data="Note for the first commit"
-note2_data="Note for the second commit"
-note3_data="Note for the third commit"
+note1_data="The first note for the first commit"
+note2_data="The first note for the second commit"
+note3_data="The first note for the third commit"
+note1b_data="The second note for the first commit"
+note1c_data="The third note for the first commit"
+note2b_data="The second note for the second commit"
test_tick
cat >input <<INPUT_END
@@ -1169,7 +1172,45 @@ data <<EOF
$note3_data
EOF
+commit refs/notes/foobar
+mark :10
+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+data <<COMMIT
+notes (:10)
+COMMIT
+
+N inline :3
+data <<EOF
+$note1b_data
+EOF
+
+commit refs/notes/foobar2
+mark :11
+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+data <<COMMIT
+notes (:11)
+COMMIT
+
+N inline :3
+data <<EOF
+$note1c_data
+EOF
+
+commit refs/notes/foobar
+mark :12
+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+data <<COMMIT
+notes (:12)
+COMMIT
+
+deleteall
+N inline :5
+data <<EOF
+$note2b_data
+EOF
+
INPUT_END
+
test_expect_success \
'Q: commit notes' \
'git fast-import <input &&
@@ -1224,8 +1265,8 @@ committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
notes (:9)
EOF
test_expect_success \
- 'Q: verify notes commit' \
- 'git cat-file commit refs/notes/foobar | sed 1d >actual &&
+ 'Q: verify first notes commit' \
+ 'git cat-file commit refs/notes/foobar~2 | sed 1d >actual &&
test_cmp expect actual'
cat >expect.unsorted <<EOF
@@ -1235,23 +1276,112 @@ cat >expect.unsorted <<EOF
EOF
cat expect.unsorted | sort >expect
test_expect_success \
- 'Q: verify notes tree' \
- 'git cat-file -p refs/notes/foobar^{tree} | sed "s/ [0-9a-f]* / /" >actual &&
+ 'Q: verify first notes tree' \
+ 'git cat-file -p refs/notes/foobar~2^{tree} | sed "s/ [0-9a-f]* / /" >actual &&
test_cmp expect actual'
echo "$note1_data" >expect
test_expect_success \
- 'Q: verify note for first commit' \
- 'git cat-file blob refs/notes/foobar:$commit1 >actual && test_cmp expect actual'
+ 'Q: verify first note for first commit' \
+ 'git cat-file blob refs/notes/foobar~2:$commit1 >actual && test_cmp expect actual'
echo "$note2_data" >expect
test_expect_success \
- 'Q: verify note for second commit' \
- 'git cat-file blob refs/notes/foobar:$commit2 >actual && test_cmp expect actual'
+ 'Q: verify first note for second commit' \
+ 'git cat-file blob refs/notes/foobar~2:$commit2 >actual && test_cmp expect actual'
+
+echo "$note3_data" >expect
+test_expect_success \
+ 'Q: verify first note for third commit' \
+ 'git cat-file blob refs/notes/foobar~2:$commit3 >actual && test_cmp expect actual'
+
+cat >expect <<EOF
+parent `git rev-parse --verify refs/notes/foobar~2`
+author $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+
+notes (:10)
+EOF
+test_expect_success \
+ 'Q: verify second notes commit' \
+ 'git cat-file commit refs/notes/foobar^ | sed 1d >actual &&
+ test_cmp expect actual'
+
+cat >expect.unsorted <<EOF
+100644 blob $commit1
+100644 blob $commit2
+100644 blob $commit3
+EOF
+cat expect.unsorted | sort >expect
+test_expect_success \
+ 'Q: verify second notes tree' \
+ 'git cat-file -p refs/notes/foobar^^{tree} | sed "s/ [0-9a-f]* / /" >actual &&
+ test_cmp expect actual'
+
+echo "$note1b_data" >expect
+test_expect_success \
+ 'Q: verify second note for first commit' \
+ 'git cat-file blob refs/notes/foobar^:$commit1 >actual && test_cmp expect actual'
+
+echo "$note2_data" >expect
+test_expect_success \
+ 'Q: verify first note for second commit' \
+ 'git cat-file blob refs/notes/foobar^:$commit2 >actual && test_cmp expect actual'
echo "$note3_data" >expect
test_expect_success \
- 'Q: verify note for third commit' \
- 'git cat-file blob refs/notes/foobar:$commit3 >actual && test_cmp expect actual'
+ 'Q: verify first note for third commit' \
+ 'git cat-file blob refs/notes/foobar^:$commit3 >actual && test_cmp expect actual'
+
+cat >expect <<EOF
+author $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+
+notes (:11)
+EOF
+test_expect_success \
+ 'Q: verify third notes commit' \
+ 'git cat-file commit refs/notes/foobar2 | sed 1d >actual &&
+ test_cmp expect actual'
+
+cat >expect.unsorted <<EOF
+100644 blob $commit1
+EOF
+cat expect.unsorted | sort >expect
+test_expect_success \
+ 'Q: verify third notes tree' \
+ 'git cat-file -p refs/notes/foobar2^{tree} | sed "s/ [0-9a-f]* / /" >actual &&
+ test_cmp expect actual'
+
+echo "$note1c_data" >expect
+test_expect_success \
+ 'Q: verify third note for first commit' \
+ 'git cat-file blob refs/notes/foobar2:$commit1 >actual && test_cmp expect actual'
+
+cat >expect <<EOF
+parent `git rev-parse --verify refs/notes/foobar^`
+author $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+
+notes (:12)
+EOF
+test_expect_success \
+ 'Q: verify fourth notes commit' \
+ 'git cat-file commit refs/notes/foobar | sed 1d >actual &&
+ test_cmp expect actual'
+
+cat >expect.unsorted <<EOF
+100644 blob $commit2
+EOF
+cat expect.unsorted | sort >expect
+test_expect_success \
+ 'Q: verify fourth notes tree' \
+ 'git cat-file -p refs/notes/foobar^{tree} | sed "s/ [0-9a-f]* / /" >actual &&
+ test_cmp expect actual'
+
+echo "$note2b_data" >expect
+test_expect_success \
+ 'Q: verify second note for second commit' \
+ 'git cat-file blob refs/notes/foobar:$commit2 >actual && test_cmp expect actual'
test_done
--
1.6.5.3.433.g11067
^ permalink raw reply related
* [RFC/PATCHv10 03/11] Add more testcases to test fast-import of notes
From: Johan Herland @ 2009-12-07 11:27 UTC (permalink / raw)
To: git; +Cc: gitster, johan, spearce
In-Reply-To: <1260185254-1523-1-git-send-email-johan@herland.net>
This patch adds testcases verifying correct behaviour in several scenarios
regarding fast-import of notes:
- using a mixture of 'N' and 'M' commands
- updating existing notes
- concatenation of notes
- 'deleteall' also removes notes
- fanout schemes is added/removed when needed
- git-fast-import's branch unload/reload preserves notes
- non-notes are not clobbered in the presence of notes
Signed-off-by: Johan Herland <johan@herland.net>
---
t/t9301-fast-import-notes.sh | 623 ++++++++++++++++++++++++++++++++++++++++++
1 files changed, 623 insertions(+), 0 deletions(-)
create mode 100755 t/t9301-fast-import-notes.sh
diff --git a/t/t9301-fast-import-notes.sh b/t/t9301-fast-import-notes.sh
new file mode 100755
index 0000000..a5c99d8
--- /dev/null
+++ b/t/t9301-fast-import-notes.sh
@@ -0,0 +1,623 @@
+#!/bin/sh
+#
+# Copyright (c) 2009 Johan Herland
+#
+
+test_description='test git fast-import of notes objects'
+. ./test-lib.sh
+
+
+test_tick
+cat >input <<INPUT_END
+commit refs/heads/master
+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+data <<COMMIT
+first commit
+COMMIT
+
+M 644 inline foo
+data <<EOF
+file foo in first commit
+EOF
+
+M 755 inline bar
+data <<EOF
+file bar in first commit
+EOF
+
+M 644 inline baz/xyzzy
+data <<EOF
+file baz/xyzzy in first commit
+EOF
+
+commit refs/heads/master
+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+data <<COMMIT
+second commit
+COMMIT
+
+M 644 inline foo
+data <<EOF
+file foo in second commit
+EOF
+
+M 755 inline baz/xyzzy
+data <<EOF
+file baz/xyzzy in second commit
+EOF
+
+commit refs/heads/master
+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+data <<COMMIT
+third commit
+COMMIT
+
+M 644 inline foo
+data <<EOF
+file foo in third commit
+EOF
+
+commit refs/heads/master
+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+data <<COMMIT
+fourth commit
+COMMIT
+
+M 755 inline bar
+data <<EOF
+file bar in fourth commit
+EOF
+
+INPUT_END
+
+test_expect_success 'set up master branch' '
+
+ git fast-import <input &&
+ git whatchanged master
+'
+
+commit4=$(git rev-parse refs/heads/master)
+commit3=$(git rev-parse "$commit4^")
+commit2=$(git rev-parse "$commit4~2")
+commit1=$(git rev-parse "$commit4~3")
+
+test_tick
+cat >input <<INPUT_END
+commit refs/notes/test
+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+data <<COMMIT
+first notes commit
+COMMIT
+
+M 644 inline $commit1
+data <<EOF
+first note for first commit
+EOF
+
+M 755 inline $commit2
+data <<EOF
+first note for second commit
+EOF
+
+INPUT_END
+
+cat >expect <<EXPECT_END
+ fourth commit
+ third commit
+ second commit
+ first note for second commit
+ first commit
+ first note for first commit
+EXPECT_END
+
+test_expect_success 'add notes with simple M command' '
+
+ git fast-import <input &&
+ GIT_NOTES_REF=refs/notes/test git log | grep "^ " > actual &&
+ test_cmp expect actual
+
+'
+
+test_tick
+cat >input <<INPUT_END
+commit refs/notes/test
+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+data <<COMMIT
+second notes commit
+COMMIT
+
+from refs/notes/test^0
+N inline $commit3
+data <<EOF
+first note for third commit
+EOF
+
+N inline $commit4
+data <<EOF
+first note for fourth commit
+EOF
+
+INPUT_END
+
+cat >expect <<EXPECT_END
+ fourth commit
+ first note for fourth commit
+ third commit
+ first note for third commit
+ second commit
+ first note for second commit
+ first commit
+ first note for first commit
+EXPECT_END
+
+test_expect_success 'add notes with simple N command' '
+
+ git fast-import <input &&
+ GIT_NOTES_REF=refs/notes/test git log | grep "^ " > actual &&
+ test_cmp expect actual
+
+'
+
+test_tick
+cat >input <<INPUT_END
+commit refs/notes/test
+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+data <<COMMIT
+third notes commit
+COMMIT
+
+from refs/notes/test^0
+N inline $commit1
+data <<EOF
+second note for first commit
+EOF
+
+N inline $commit2
+data <<EOF
+second note for second commit
+EOF
+
+N inline $commit3
+data <<EOF
+second note for third commit
+EOF
+
+N inline $commit4
+data <<EOF
+second note for fourth commit
+EOF
+
+INPUT_END
+
+cat >expect <<EXPECT_END
+ fourth commit
+ second note for fourth commit
+ third commit
+ second note for third commit
+ second commit
+ second note for second commit
+ first commit
+ second note for first commit
+EXPECT_END
+
+test_expect_success 'update existing notes with N command' '
+
+ git fast-import <input &&
+ GIT_NOTES_REF=refs/notes/test git log | grep "^ " > actual &&
+ test_cmp expect actual
+
+'
+
+test_tick
+cat >input <<INPUT_END
+commit refs/notes/test
+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+data <<COMMIT
+fourth notes commit
+COMMIT
+
+from refs/notes/test^0
+M 644 inline $(echo "$commit3" | sed "s|^..|&/|")
+data <<EOF
+prefix of note for third commit
+EOF
+
+M 644 inline $(echo "$commit4" | sed "s|^..|&/|")
+data <<EOF
+prefix of note for fourth commit
+EOF
+
+M 644 inline $(echo "$commit4" | sed "s|^\(..\)\(..\)|\1/\2/|")
+data <<EOF
+pre-prefix of note for fourth commit
+EOF
+
+N inline $commit1
+data <<EOF
+third note for first commit
+EOF
+
+N inline $commit2
+data <<EOF
+third note for second commit
+EOF
+
+N inline $commit3
+data <<EOF
+third note for third commit
+EOF
+
+N inline $commit4
+data <<EOF
+third note for fourth commit
+EOF
+
+
+INPUT_END
+
+cat >expect <<EXPECT_END
+ fourth commit
+ pre-prefix of note for fourth commit
+ prefix of note for fourth commit
+ third note for fourth commit
+ third commit
+ prefix of note for third commit
+ third note for third commit
+ second commit
+ third note for second commit
+ first commit
+ third note for first commit
+EXPECT_END
+
+test_expect_success 'add concatentation notes with M command' '
+
+ git fast-import <input &&
+ GIT_NOTES_REF=refs/notes/test git log | grep "^ " > actual &&
+ test_cmp expect actual
+
+'
+
+test_tick
+cat >input <<INPUT_END
+commit refs/notes/test
+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+data <<COMMIT
+fifth notes commit
+COMMIT
+
+from refs/notes/test^0
+deleteall
+
+INPUT_END
+
+cat >expect <<EXPECT_END
+ fourth commit
+ third commit
+ second commit
+ first commit
+EXPECT_END
+
+test_expect_success 'verify that deleteall also removes notes' '
+
+ git fast-import <input &&
+ GIT_NOTES_REF=refs/notes/test git log | grep "^ " > actual &&
+ test_cmp expect actual
+
+'
+
+test_tick
+cat >input <<INPUT_END
+commit refs/notes/test
+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+data <<COMMIT
+sixth notes commit
+COMMIT
+
+from refs/notes/test^0
+M 644 inline $commit1
+data <<EOF
+third note for first commit
+EOF
+
+M 644 inline $commit3
+data <<EOF
+third note for third commit
+EOF
+
+N inline $commit1
+data <<EOF
+fourth note for first commit
+EOF
+
+N inline $commit3
+data <<EOF
+fourth note for third commit
+EOF
+
+INPUT_END
+
+cat >expect <<EXPECT_END
+ fourth commit
+ third commit
+ fourth note for third commit
+ second commit
+ first commit
+ fourth note for first commit
+EXPECT_END
+
+test_expect_success 'verify that later N commands override earlier M commands' '
+
+ git fast-import <input &&
+ GIT_NOTES_REF=refs/notes/test git log | grep "^ " > actual &&
+ test_cmp expect actual
+
+'
+
+# Write fast-import commands to create the given number of commits
+fast_import_commits () {
+ my_ref=$1
+ my_num_commits=$2
+ my_append_to_file=$3
+ my_i=0
+ while test $my_i -lt $my_num_commits
+ do
+ my_i=$(($my_i + 1))
+ test_tick
+ cat >>"$my_append_to_file" <<INPUT_END
+commit $my_ref
+mark :$my_i
+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+data <<COMMIT
+commit #$my_i
+COMMIT
+
+M 644 inline file
+data <<EOF
+file contents in commit #$my_i
+EOF
+
+INPUT_END
+ done
+}
+
+# Write fast-import commands to create the given number of notes annotating
+# the commits created by fast_import_commits()
+fast_import_notes () {
+ my_notes_ref=$1
+ my_num_commits=$2
+ my_append_to_file=$3
+ my_note_append=$4
+ test_tick
+ cat >>"$my_append_to_file" <<INPUT_END
+commit $my_notes_ref
+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+data <<COMMIT
+committing $my_num_commits notes
+COMMIT
+
+INPUT_END
+
+ my_i=0
+ while test $my_i -lt $my_num_commits
+ do
+ my_i=$(($my_i + 1))
+ cat >>"$my_append_to_file" <<INPUT_END
+N inline :$my_i
+data <<EOF
+note for commit #$my_i$my_note_append
+EOF
+
+INPUT_END
+ done
+}
+
+
+rm input expect
+num_commits=400
+# Create lots of commits
+fast_import_commits "refs/heads/many_commits" $num_commits input
+# Create one note per above commit
+fast_import_notes "refs/notes/many_notes" $num_commits input
+# Add a couple of non-notes as well
+test_tick
+cat >>input <<INPUT_END
+commit refs/notes/many_notes
+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+data <<COMMIT
+committing some non-notes to the notes tree
+COMMIT
+
+M 755 inline foobar/non-note.txt
+data <<EOF
+This is not a note, but rather a regular file residing in a notes tree
+EOF
+
+M 644 inline deadbeef
+data <<EOF
+Non-note file
+EOF
+
+M 644 inline de/adbeef
+data <<EOF
+Another non-note file
+EOF
+
+INPUT_END
+# Finally create the expected output from all these notes and commits
+i=$num_commits
+while test $i -gt 0
+do
+ cat >>expect <<EXPECT_END
+ commit #$i
+ note for commit #$i
+EXPECT_END
+ i=$(($i - 1))
+done
+
+test_expect_success 'add lots of commits and notes' '
+
+ git fast-import <input &&
+ GIT_NOTES_REF=refs/notes/many_notes git log refs/heads/many_commits |
+ grep "^ " > actual &&
+ test_cmp expect actual
+
+'
+
+test_expect_success 'verify that lots of notes trigger a fanout scheme' '
+
+ # None of the entries in the top-level notes tree should be a full SHA1
+ git ls-tree --name-only refs/notes/many_notes |
+ while read path
+ do
+ if test $(expr length "$path") -ge 40
+ then
+ return 1
+ fi
+ done
+
+'
+
+cat >>expect_non-note1 << EOF
+This is not a note, but rather a regular file residing in a notes tree
+EOF
+
+cat >>expect_non-note2 << EOF
+Non-note file
+EOF
+
+cat >>expect_non-note3 << EOF
+Another non-note file
+EOF
+
+test_expect_success 'verify that non-notes are untouched by a fanout change' '
+
+ git cat-file -p refs/notes/many_notes:foobar/non-note.txt > actual &&
+ test_cmp expect_non-note1 actual &&
+ git cat-file -p refs/notes/many_notes:deadbeef > actual &&
+ test_cmp expect_non-note2 actual &&
+ git cat-file -p refs/notes/many_notes:de/adbeef > actual &&
+ test_cmp expect_non-note3 actual
+
+'
+remaining_notes=10
+test_tick
+cat >>input <<INPUT_END
+commit refs/notes/many_notes
+committer $GIT_COMMITTER_NAME <$GIT_COMMITTER_EMAIL> $GIT_COMMITTER_DATE
+data <<COMMIT
+removing all notes but $remaining_notes
+COMMIT
+from refs/notes/many_notes^0
+INPUT_END
+
+i=$remaining_notes
+while test $i -lt $num_commits
+do
+ i=$(($i + 1))
+ cat >>input <<INPUT_END
+N 0000000000000000000000000000000000000000 :$i
+INPUT_END
+done
+
+i=$num_commits
+rm expect
+while test $i -gt 0
+do
+ cat >>expect <<EXPECT_END
+ commit #$i
+EXPECT_END
+ if test $i -le $remaining_notes
+ then
+ cat >>expect <<EXPECT_END
+ note for commit #$i
+EXPECT_END
+ fi
+ i=$(($i - 1))
+done
+
+test_expect_success 'remove lots of notes' '
+
+ git fast-import <input &&
+ GIT_NOTES_REF=refs/notes/many_notes git log refs/heads/many_commits |
+ grep "^ " > actual &&
+ test_cmp expect actual
+
+'
+
+test_expect_success 'verify that removing notes trigger fanout consolidation' '
+
+ # All entries in the top-level notes tree should be a full SHA1
+ git ls-tree --name-only -r refs/notes/many_notes |
+ while read path
+ do
+ # Explicitly ignore the non-note paths
+ test "$path" = "foobar/non-note.txt" && continue
+ test "$path" = "deadbeef" && continue
+ test "$path" = "de/adbeef" && continue
+
+ if test $(expr length "$path") -ne 40
+ then
+ return 1
+ fi
+ done
+
+'
+
+test_expect_success 'verify that non-notes are untouched by a fanout change' '
+
+ git cat-file -p refs/notes/many_notes:foobar/non-note.txt > actual &&
+ test_cmp expect_non-note1 actual &&
+ git cat-file -p refs/notes/many_notes:deadbeef > actual &&
+ test_cmp expect_non-note2 actual &&
+ git cat-file -p refs/notes/many_notes:de/adbeef > actual &&
+ test_cmp expect_non-note3 actual
+
+'
+
+
+rm input expect
+num_notes_refs=10
+num_commits=16
+some_commits=8
+# Create commits
+fast_import_commits "refs/heads/more_commits" $num_commits input
+# Create one note per above commit per notes ref
+i=0
+while test $i -lt $num_notes_refs
+do
+ i=$(($i + 1))
+ fast_import_notes "refs/notes/more_notes_$i" $num_commits input
+done
+# Trigger branch reloading in git-fast-import by repeating the note creation
+i=0
+while test $i -lt $num_notes_refs
+do
+ i=$(($i + 1))
+ fast_import_notes "refs/notes/more_notes_$i" $some_commits input " (2)"
+done
+# Finally create the expected output from the notes in refs/notes/more_notes_1
+i=$num_commits
+while test $i -gt 0
+do
+ note_data="note for commit #$i"
+ if test $i -le $some_commits
+ then
+ note_data="$note_data (2)"
+ fi
+ cat >>expect <<EXPECT_END
+ commit #$i
+ $note_data
+EXPECT_END
+ i=$(($i - 1))
+done
+
+test_expect_success "add notes to $num_commits commits in each of $num_notes_refs refs" '
+
+ git fast-import --active-branches=5 <input &&
+ GIT_NOTES_REF=refs/notes/more_notes_1 git log refs/heads/more_commits |
+ grep "^ " > actual &&
+ test_cmp expect actual
+
+'
+
+test_done
--
1.6.5.3.433.g11067
^ permalink raw reply related
* [RFC/PATCHv10 04/11] Minor style fixes to notes.c
From: Johan Herland @ 2009-12-07 11:27 UTC (permalink / raw)
To: git; +Cc: gitster, johan, spearce
In-Reply-To: <1260185254-1523-1-git-send-email-johan@herland.net>
Signed-off-by: Johan Herland <johan@herland.net>
---
notes.c | 6 +++---
1 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/notes.c b/notes.c
index 023adce..57d5cdc 100644
--- a/notes.c
+++ b/notes.c
@@ -93,7 +93,7 @@ static void **note_tree_search(struct int_node **tree,
i = GET_NIBBLE(*n, key_sha1);
p = (*tree)->a[i];
- switch(GET_PTR_TYPE(p)) {
+ switch (GET_PTR_TYPE(p)) {
case PTR_TYPE_INTERNAL:
*tree = CLR_PTR_TYPE(p);
(*n)++;
@@ -195,7 +195,7 @@ static void note_tree_insert(struct int_node *tree, unsigned char n,
assert(GET_PTR_TYPE(entry) == 0); /* no type bits set */
l = (struct leaf_node *) CLR_PTR_TYPE(*p);
- switch(GET_PTR_TYPE(*p)) {
+ switch (GET_PTR_TYPE(*p)) {
case PTR_TYPE_NULL:
assert(!*p);
*p = SET_PTR_TYPE(entry, type);
@@ -257,7 +257,7 @@ static void note_tree_free(struct int_node *tree)
unsigned int i;
for (i = 0; i < 16; i++) {
void *p = tree->a[i];
- switch(GET_PTR_TYPE(p)) {
+ switch (GET_PTR_TYPE(p)) {
case PTR_TYPE_INTERNAL:
note_tree_free(CLR_PTR_TYPE(p));
/* fall through */
--
1.6.5.3.433.g11067
^ 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