Re: Subtree: My Status

2013-04-22 Thread Jeremy Rosen
- Mail original -
 Hi folks,
 
 I apologize for being off the grid for a while.  We had a baby and
 unexpectedly ended up in the NICU.  We just got him home a week ago.
 Everyone is doing fine but I had to pretty much drop all
 non-essential
 work for a month or so.
 

Good to here that everything is well on your side and congratulation for the 
baby,



 Rest assured that I have all of the git-subtree-related mail sitting
 in
 my inbox.  It will take me some time to process it all -- looks ike
 there has been a lot of good work!
 

no worries, there is no emergency here...


 Please remember that I don't consider myself a gatekeeper to git
 subtree.  In fact I could use some help reviewing and approving
 patches.
 If anyone thinks a patch looks good, let Junio know.  It's my
 responsibility to object to things, not your responsibility to wait
 for

I guess it's more or less everybody's responsability to review patches, but
it seems to me that for the actual gate-keeping, Junio considers you 
in charge of git-subtree... Maybe there is an organisational quirk to sort-
out here... Junio ?


--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 6.5/7] builtin/log.c: make usage string consistent with doc

2013-04-22 Thread Ramkumar Ramachandra
Replace 'since..until' with 'revision range', in accordance with
the documentation.

Signed-off-by: Ramkumar Ramachandra artag...@gmail.com
---
 Junio: sorry I missed this detail.  Can you squeeze this patch
 between [6/7] and [7/7] so that the commit message in [7/7] makes
 sense?

 Thanks.

 builtin/log.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/builtin/log.c b/builtin/log.c
index ad46f72..6e56a50 100644
--- a/builtin/log.c
+++ b/builtin/log.c
@@ -37,7 +37,7 @@ static const char *fmt_patch_subject_prefix = PATCH;
 static const char *fmt_pretty;
 
 static const char * const builtin_log_usage[] = {
-   N_(git log [options] [since..until] [[--] path...]\n)
+   N_(git log [options] [revision range] [[--] path...]\n)
N_(   or: git show [options] object...),
NULL
 };
-- 
1.8.2.1.423.g9a53c75.dirty

--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2 1/8] Add new git-cc-cmd helper to contrib

2013-04-22 Thread Jeremy Rosen
 
  Would it make sense to integrate this in git shortlog, which
  already
  does something similar?
 
 Conceptually, yes, but the end result will be much larger in scope.
 I am not sure if shortlog is still a good label for it.
 

since we are throwing ideas around...

The first place where I would logically look for such a feature would be
in git-blame --cc-list or something like that.

git-blame seems to me as a logical place for all look at history and give
me a list of names type commands
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[ITCH] Mixed-case aliases

2013-04-22 Thread Ramkumar Ramachandra
Hi,

My .gitconfig has aliases like the following:

[alias]
bD = branch -D
bM = branch -M

Unfortunately, since the current config-parsing code unconditionally
runs tolower() on all keys, these aliases don't work.  My proposal is
to modify alias.c::alias_lookup() to call a
git_config_DONTMANGLECASE() variant, and modify the various functions
in config.c appropriately.

On a related note, it might be useful to warn the user that we are an
ignoring alias.builtin-name key when executing the corresponding
builtin.  It's not really my itch, but I suspect a lot of beginners
get tripped up by this.

What do you think?

Ram
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: Premerging topics (was: [RFD] annnotating a pair of commit objects?)

2013-04-22 Thread Antoine Pelisse
Any comment on that ? I think anyone using a Topic Workflow could
use that feature and that it would be a nice addition to the project.
Maybe I'm totally wrong in the proposal below (please tell me !), but
there are some unanswered question that prevents me from starting (and
I'd really like this to be discussed before actually starting).

On Wed, Apr 10, 2013 at 10:35 PM, Antoine Pelisse apeli...@gmail.com wrote:

 The goal is to propose a structure for storing and pre-merging pairs of 
 commits.

 Data-structure
 ==

 We could use a note ref to store the pre-merge information. Each commit
 would be annotated with a blob containing the list of pre-merges (one
 sha1 per line with sha1 pointing to a merge commit). The commit on the
 other side of a merge would also be annotated.

 The choice of the refname could be done like we do with notes:
 - Have a default value
 - Have a default value configured in config
 - Use a specific value when merging/creating the pre-merges

 Here are my concerns:

 Pros
 
 1. Notes allow dynamic annotation a commit
 2. If we manage to fix 4, we can easily download all pre-merges from a
 remote host by fetching the ref (or clean by deleting the ref).
 3. Conflicts on pre-merge notes could probably be resolved by concatenation.

 Cons
 
 4. Checking connectivity means opening the blob and parsing it
 5. Regular notes and pre-merge notes have to be handled separately
 because of 4.

 I'm hoping we can keep the pros and avoid the cons, but I'm kind of
 stuck here. Help would be really appreciated (or maybe this is a totally
 wrong direction, and I would also like to know ;)

 Merging (Using what we saved)
 =
 The goal is to merge branches J and B using existing pre-merges.

 E0. Create an empty stack S
 E1. Create set of commits 'J..B' and 'B..J' (that is probably already done)
 E2. For each commit C in smallest(J..B, B..J), execute E3
 E3. For each premerge P in notes-premerge(C), execute E4
 E4. If one of both parents of P belongs to biggest(J..B, B..J), stack P in S
 E5. Merge J and B using all pre-merges from S

 Let's consider that |J..B| is smaller than |B..J|.
 E0 is executed only once
 E1 is O(|J..B| + |B..J|)
 E2 is O(|J..B|)
 E3 is O(|J..B| x the average number of pre-merge per commits P_avg)
 E4 is executed for each parent (let's say it's two/constant, after all
 the topic is pair of commits), so still O(|J..B| x P_avg)
 E5 I don't know (how it can be done, and what would be the resulting
 time complexity)

 So the time cost for steps E0 to E4 is O(|J..B| + |B..J| x P_avg)

 Tools (Save the pre-merges)
 ===

 Of course we need several tools to maintain the list of premerges, and
 to easily compute them. For example, it would be nice to be able to do
 something like:

 $ git pre-merge topicA topicB topicC

 to find, resolve and store all interactions between the topics. We could
 then easily derive to something that would allow to pre-merge a new
 topic with all topics already merged in master..pu (for example).

 Anyway, this task is left for latter.
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[BUG] Silent data loss on merge with uncommited changes + renames

2013-04-22 Thread Matthieu Moy
Hi,

Following the discussion on merge with uncommited changes inside the
git pull --autostash thread, I did a bit of testing, and encountered a
case with silent data loss. In short: merge a branch introducing changes
to a file. If the file has been renamed in the current branch, then git
merge follows the rename and brings changes to the renamed file, but
uncommited changes in this file are overriden silently.

I could have expected git merge --abort to fail, but the problem is
really more serious here: data loss is done silently before giving me an
opportunity to do or abort anything.

Reproduction script below:

#! /bin/sh

# Create repo
git init git.$$
cd git.$$
echo init  test.txt
git add test.txt
git commit -m init

# Make a branch changing test.txt
git checkout -b branch
echo new  test.txt
git commit -am new

# Move test.txt on master
git checkout master
git mv test.txt moved.txt
git commit -m move

# Make uncommited changes to moved.txt
echo precious  moved.txt

# Merge loses uncommited content precious in moved.txt silently
git merge --no-edit branch
ls # lists just moved.txt
git status # nothing to commit, working directory clean
cat moved.txt # Says new.

-- 
Matthieu Moy
http://www-verimag.imag.fr/~moy/
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 4/5] git-log.txt: rewrite note on why -- may be required

2013-04-22 Thread Thomas Rast
Junio C Hamano gits...@pobox.com writes:

 This is a minimalistic patch to fix the formatting.  I removed the
 extra sentence after the enumeration and moved it to the end of the
 main text, but somebody may have a better idea to persuade AsciiDoc
 to format it in a more reasonable way while keeping the sentence
 there.

 -- 8 --
 Subject: line-log: fix documentation formatting

 The second paragraph of the added description for the -L option
 start and end can take one of these forms:, and the list of
 forms that follow the headline, were indented one level too short,
 due to the missing + to signal that the next paragraph continues
 the previous one.

 Also You can specify this option more than once is about the -L
 option, not about its various forms of starting and ending points.
 Move it to the end of the main text.

 Signed-off-by: Junio C Hamano gits...@pobox.com
 ---
  Documentation/git-log.txt | 5 ++---
  1 file changed, 2 insertions(+), 3 deletions(-)

 diff --git a/Documentation/git-log.txt b/Documentation/git-log.txt
 index 4850226..0959f9d 100644
 --- a/Documentation/git-log.txt
 +++ b/Documentation/git-log.txt
 @@ -76,12 +76,11 @@ produced by --stat etc.
   not give any pathspec limiters.  This is currently limited to
   a walk starting from a single revision, i.e., you may only
   give zero or one positive revision arguments.
 -
 + You can specify this option more than once.
 ++
  start and end can take one of these forms:
  
  include::line-range-format.txt[]
 -You can specify this option more than once.
 -
  

Sorry for being a bit late to this.  I think it's a good solution;
putting You can specify this option more than once after all the other
text was probably worse because it gets lost down there.

As for

  --full-line-diff::
   Always print the interesting range even if the current commit

That's just stale and not currently implemented.  Sigh.  We should
remove it.

-- 8 --
Subject: [PATCH] git-log(1): remove --full-line-diff description

This option is a remnant of an earlier log -L version, and not
currently implemented.  Remove it until (if at all) it is implemented
again.

Signed-off-by: Thomas Rast tr...@inf.ethz.ch
---
 Documentation/git-log.txt | 4 
 1 file changed, 4 deletions(-)

diff --git a/Documentation/git-log.txt b/Documentation/git-log.txt
index 0959f9d..65707ce 100644
--- a/Documentation/git-log.txt
+++ b/Documentation/git-log.txt
@@ -82,10 +82,6 @@ produced by --stat etc.
 
 include::line-range-format.txt[]
 
---full-line-diff::
-   Always print the interesting range even if the current commit
-   does not change any line of the range.
-
 [\--] path...::
Show only commits that are enough to explain how the files
that match the specified paths came to be.  See History
-- 
1.8.2.1.844.g59e84de.dirty
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Patch-to-mail notes resurrected

2013-04-22 Thread Thomas Rast
Hi,

As some might remember, I made a script that writes notes (as in
git-notes) linking patches to emails back in 2009:

  http://thread.gmane.org/gmane.comp.version-control.git/109074

I resurrected this idea the other week, using a faster implementation
(the N command in fast-import is great!) and generating better links.
I am regularly pushing the results to

  git://github.com/trast/git.git
  git://repo.or.cz/git/trast.git

branches

  notes/gmanea link to the gmane thread view, focused on this patch
  notes/message-id   the raw message-id

Point your notes.displayRef at one or both to use them.

It still fails to match some commits, so consider this WIP, but I think
it's quite useful already.

-- 
Thomas Rast
trast@{inf,student}.ethz.ch
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 2/6] show: obey --textconv for blobs

2013-04-22 Thread Michael J Gruber
Jeff King venit, vidit, dixit 21.04.2013 05:37:
 On Sat, Apr 20, 2013 at 03:38:53PM +0200, Michael J Gruber wrote:
 
 Wait, this does the opposite of the last patch. If we do want to do
 this, shouldn't the last one have been an expect_failure?

 The last patch just documents the status quo, which is not a bug per se.
 Therefore, no failure, but change in the definition of success.
 
 IMHO, the series is easier to review if you it does not go back and
 forth. If you have one patch that says X is the right behavior, and
 then another patch that flips it to say Y is the right behavior, the
 reviewer would read each in sequence and want to be convinced by your
 arguments for X and Y. But you probably cannot make a good argument for
 X if you are trying to end up at Y. :)
 
 So I'd much rather see the test introduced with the desired end
 behavior, marked as expect_failure, and the commit message contain an
 argument about why Y is a good thing (and squashing the tests in with
 the actual fix is often even better, because the fix itself would want
 to contain the same argument).
 
 Just my two cents as a reviewer.
 
 My reasoning is twofold:

 - consistency between git show commit and git show blob
 
 I'm not sure I agree with this line of reasoning. git show commit is
 showing a diff, not the file contents; textconv has always been about
 munging the contents to produce a textual diff. It may be reasonable to
 extend its definition to this is the preferred human view of this
 content, and that happens to be what you would want to produce a diff.
 But I do not think it is necessarily inconsistent not to apply it for
 the blob case.
 
 - git show is a user facing command, and as such should produce output
 consumable by humans; whereas git cat-file is plumbing and should
 produce raw data unless told otherwise (-p, --textconv).
 
 That holds if the textconv is the only (or best) human-readable version
 of the file. And maybe that is reasonable. But is it possible that
 somebody uses textconv to produce a better diff of some already
 human-readable format? For example, imagine I define a textconv for XML
 files that normalizes the formatting to make diffs less noisy. When I am
 not looking at a diff, what is the best human-readable version? The
 original, or the normalized one? I'm not sure.
 
 Note that I'm somewhat playing devil's advocate here. For the cases
 where I have used textconv in the real world, I think I would probably
 prefer seeing the converted contents, and I am happy to call it user
 error if I use git show HEAD:foo.jpg bar.jpg accidentally. But I also
 want to make sure we are not regressing somebody else unnecessarily.

Yes, the thing is that textconv helps diff by converting content (to
text) before the (textual) diff. So it's somehow a double-faced beast.

It's clearly activated by a diff attribute; so that would be a strong
argument against my patch, at least against defaulting to --textconv for
blobs.

OTOH, textconv does have this aspect of converting text to a form
digestable by humans (pre-diff, granted), which is the argument for
defaulting to --textconv in porcellain.

We could use a separate attribute show in addition to diff, but I
don't think it's worth going there, unless there is a strong use case
for diff-specific textconv which one would not want to apply when
showing just the content.

Michael
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] t4202 (log): add failing test for log with subtree

2013-04-22 Thread Matthieu Moy
Ramkumar Ramachandra artag...@gmail.com writes:

  was checking it out: a 'git log pathspec', when referring to a file
  inside the subtree, doesn't work as expected: it only displays the
  HEAD commit.

This is somehow expected: the subtree merge changed the filename during
merge (it is subtree/file.txt after the merge, and just file.txt
before), so git log without --follow just considers the file appeared.

OTOH, I think this is a known limitation of git log --follow that it
does not follow renames done by subtree merges.

-- 
Matthieu Moy
http://www-verimag.imag.fr/~moy/
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] t4202 (log): add failing test for log with subtree

2013-04-22 Thread Ramkumar Ramachandra
Matthieu Moy wrote:
 This is somehow expected: the subtree merge changed the filename during
 merge (it is subtree/file.txt after the merge, and just file.txt
 before), so git log without --follow just considers the file appeared.

No, a merge does not change any filenames.  The history of the file
is very much present: run a git log HEAD^2 to see the entire history
of the subtree.  Even a git blame (without -M or -C) works just fine.

 OTOH, I think this is a known limitation of git log --follow that it
 does not follow renames done by subtree merges.

Um, no.  I think --follow is entirely orthogonal to the issue: unless
I'm mistaken, it looks for other blobs in history with heuristically
similar content.

The real issue has nothing to do with log itself: it has to do with
how rev-parse handles pathspecs.  A 'git rev-parse
HEAD:subproject/README' works fine, but 'git rev-parse
HEAD^2:subproject/README' fails.  However, 'git rev-parse
HEAD^2:README' works, but it is assuming that the path README is
present in /, when it is actually present in subproject/.  Now, I'm
not sure rev-parse is doing something unexpected, which is why I filed
the bug in log.
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] t4202 (log): add failing test for log with subtree

2013-04-22 Thread Matthieu Moy
Ramkumar Ramachandra artag...@gmail.com writes:

 Matthieu Moy wrote:
 This is somehow expected: the subtree merge changed the filename during
 merge (it is subtree/file.txt after the merge, and just file.txt
 before), so git log without --follow just considers the file appeared.

 No, a merge does not change any filenames.

Read again my message, especially the it is subtree/file.txt after the
merge, and just file.txt before part. Replace subtree with bar and
file.txt with ichi.

-- 
Matthieu Moy
http://www-verimag.imag.fr/~moy/
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] t4202 (log): add failing test for log with subtree

2013-04-22 Thread Ramkumar Ramachandra
Thomas Rast wrote:
 Umm, it should follow the rename.

There is no rename.  Unless there is a commit with the following diff
(with heuristically similar content), I don't see how --follow can
work:

diff --git a/README b/README
deleted file mode 100644

diff --git a/subproject/README b/subproject/README
new file mode 100644

Here, we just created one tiny merge commit after reading a tree into
a non-/ prefix.  There is no diff associated.
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] t4202 (log): add failing test for log with subtree

2013-04-22 Thread Ramkumar Ramachandra
Ramkumar Ramachandra wrote:
 Unless there is a commit with the following diff
 (with heuristically similar content), I don't see how --follow can
 work:

 diff --git a/README b/README
 deleted file mode 100644

 diff --git a/subproject/README b/subproject/README
 new file mode 100644

In other words, git diff-tree HEAD^2 HEAD is absolute nonsense in the
subtree case.

Let me outline how I think --follow works:
A 'git log --follow foo' executes a diff-tree with historical trees
until it finds one that removes (or adds, depending on which way you
look at it) the 'foo' entry.  It then inspects all the trees in the
corresponding commit for a blob that is heuristically similar to the
HEAD:foo blob, and follows it.

How can you logically extend this concept to handle my case?
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] t4202 (log): add failing test for log with subtree

2013-04-22 Thread Thomas Rast
Ramkumar Ramachandra artag...@gmail.com writes:


So after a long IRC discussion trying to hash out what you *want* it to
do, here's the summary for everyone else.  This test is wrong on several
counts.  For simplicity I'll denote by M the subtree merge, called
$new_h in the actual test.

 +test_expect_failure 'log pathspec in tree read into prefix' '
 + git checkout --orphan subtree 
 + git rm -rf . 
 + echo foodle ichi 

'ichi' also exists in M^1 because you reused a name from another test.
So rename detection will never pair the eventual 'bar/ichi' with this
'ichi', because the 'ichi' path was *modified*, not deleted, w.r.t. M^1.

Just to clarify, rename detection is based on seeing

  A foo
  D bar

and changing that to

  R bar - foo

assuming the blobs were reasonably similar.  And indeed, *copy*
detection (-C) is able to figure it out, because it considers all paths
that were modified as possible candidates for a copy source.

But --follow only uses rename detection.

 + git add ichi 
 + test_tick 
 + git commit -m foom 
 + echo moodle unrelated 
 + git add unrelated 
 + test_tick 
 + git commit -m quux 
 + subtree_h=$(git rev-parse HEAD) 
 + git checkout master 
 + orig_h=$(git rev-parse HEAD) 
 + git read-tree --prefix=bar $subtree_h 

You need to supply a trailing / for the prefix, it's not implied.

 + new_t=$(git write-tree) 
 + new_h=$(echo new subtree |
 + git commit-tree $new_t -p $orig_h -p $subtree_h) 
 + git reset --hard $new_h 
 + (
 + cd bar 
 + git log --oneline ichi ../actual

You need to use --follow, as otherwise the pathspec filtering is
considered fixed.

Note that as discussed in the rest of the thread, --follow is fairly
limited and doesn't *really* solve the problem.  But it does work
assuming the filenames are different and you only have one subtree
merge, like in this case.

-- 
Thomas Rast
trast@{inf,student}.ethz.ch
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] t4202 (log): add failing test for log with subtree

2013-04-22 Thread Thomas Rast
Thomas Rast tr...@inf.ethz.ch writes:

 +test_expect_failure 'log pathspec in tree read into prefix' '
 +git checkout --orphan subtree 
 +git rm -rf . 
 +echo foodle ichi 

 'ichi' also exists in M^1 because you reused a name from another test.
 So rename detection will never pair the eventual 'bar/ichi' with this
 'ichi', because the 'ichi' path was *modified*, not deleted, w.r.t. M^1.

Argh, that should read 'w.r.t. M^2', i.e. the subtree side.

The subtree side brings its own 'ichi', but it is moved to bar/ichi, so
there is a large difference between M:ichi (which came from M^1) and
M^2:ichi.


PS: As mentioned on IRC, even if you fix all that, a one-line file is
probably too small to pass the rename detection heuristics.

-- 
Thomas Rast
trast@{inf,student}.ethz.ch
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [BUG] Silent data loss on merge with uncommited changes + renames

2013-04-22 Thread Johannes Sixt
Am 4/22/2013 11:24, schrieb Matthieu Moy:
 Following the discussion on merge with uncommited changes inside the
 git pull --autostash thread, I did a bit of testing, and encountered a
 case with silent data loss. In short: merge a branch introducing changes
 to a file. If the file has been renamed in the current branch, then git
 merge follows the rename and brings changes to the renamed file, but
 uncommited changes in this file are overriden silently.

Can you check whether your case is already covered by one of:

  git grep expect_failure t/*merge*

and if not, contribute a test case?

-- Hannes
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] t4202 (log): add failing test for log with subtree

2013-04-22 Thread Ramkumar Ramachandra
Thomas Rast wrote:
 [...]

I think you've misunderstood the whole thing.  The histories of M^1
and M^2 are completely unrelated: they're from different projects
altogether.  Considering the /ichi in M^2 a rename of the /ichi in
M^1 is completely wrong.  They have nothing to do with each other.  I
intentionally named it ichi in my orphan branch just to drive my
point.  I suspect you've got confused because I used an orphan branch
to emulate a different project's history.  If you want an end-user
understanding of the problem, use git subtree:

$ cd /tmp
$ git clone gh:artagnon/varlog
$ cd varlog
$ git subtree add --prefix=clayoven \
   gh:artagnon/clayoven master
$ cd clayoven
$ git log README.md

What do you expect?  The same output you would get if you cloned
gh:artagnon/clayoven separately and executed 'git log README.md' on
it.

Now, clayoven's README.md (the one in HEAD^2) has nothing to do with
varlog's README.md (the one in HEAD^1).  It's just incidental that
both projects have a README.md.  I repeat: clayoven and varlog have
_nothing_ to do with each other.  If I say git log --follow README.md
in the above example, I don't even get the HEAD commit.  And I
wouldn't expect to either.

I will repeat this: --follow has nothing to do with the problem I've
specified.  And it is not tied to renaming (ie. changing the
name/path of a file) as you've made it look.  If you're still not
convinced, I've included a testcase for --follow following over a
merge commit (include it after the --follow test in the t4202).  Try
it without the --follow and you'll see what I mean.  Neither the
filename nor the filepath of ichi has changed in this example.

-- 8 --
test_expect_success '--follow over merge' '
git checkout -b featurebranch
echo foodle ichi 
git add ichi 
test_tick 
git commit -m add a line to the end of ichi 
echo moodle unrelated 
git add unrelated 
test_tick 
git commit -m quux 
git checkout master 
mv ichi ichi.bak 
echo gooble ichi 
cat ichi.bak ichi 
git add ichi 
test_tick 
git commit -m add a line to the beginning of ichi 
git merge featurebranch 
git log --follow --oneline ichi actual 
cat expect -\EOF 
df26551 add a line to the beginning of ichi
882d8d9 add a line to the end of ichi
2fbe8c0 third
f7dab8e second
3a2fdcb initial
EOF
test_cmp expect actual
'
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: Staging Individual Lines

2013-04-22 Thread Joshua Jensen

- Original Message -
From: ode
Date: 4/21/2013 4:22 PM

I went looking on Google and found git-cola gui client which works for
staging individual lines to the commit.
The 'git gui' that ships with Git also stages individual lines and 
groups of lines, FWIW.


-Josh
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [BUG] Silent data loss on merge with uncommited changes + renames

2013-04-22 Thread Matthieu Moy
Johannes Sixt j.s...@viscovery.net writes:

 Am 4/22/2013 11:24, schrieb Matthieu Moy:
 Following the discussion on merge with uncommited changes inside the
 git pull --autostash thread, I did a bit of testing, and encountered a
 case with silent data loss. In short: merge a branch introducing changes
 to a file. If the file has been renamed in the current branch, then git
 merge follows the rename and brings changes to the renamed file, but
 uncommited changes in this file are overriden silently.

 Can you check whether your case is already covered by one of:

   git grep expect_failure t/*merge*

Indeed, it's already here:

test_expect_failure 'will not overwrite unstaged changes in renamed file' '
git reset --hard c1 
git mv c1.c other.c 
git commit -m rename 
cp important other.c 
git merge c1a 
test_cmp important other.c
'

-- 
Matthieu Moy
http://www-verimag.imag.fr/~moy/
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 4/5] git-log.txt: rewrite note on why -- may be required

2013-04-22 Thread Junio C Hamano
Thomas Rast tr...@inf.ethz.ch writes:

 Thomas Rast tr...@inf.ethz.ch writes:

 -- 8 --
 Subject: [PATCH] git-log(1): remove --full-line-diff description

 BTW, I generated this with your jc/format-patch, but it stopped working
 after fc/send-email-annotate made it into next; I need this on top.  Am
 I missing something?

No, the topic has been stalled and left behind and needs to be
rebased on top of that other topic with your patch.  Thanks.

It also needs a lot more work to de-mime its output to be eligible
for 'next', though.

 -- 8 --
 Subject: [PATCH] FIXUP jc/format-patch: adapt for fc/send-email-annotate

 2a4c260 (format-patch: add format.coverLetter configuration variable,
 2013-04-07) changed the coverletter variable to -1 by default, so the
 die(... incompatible) always triggers.  Test if it is 0 instead.
 ---
  builtin/log.c | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)

 diff --git a/builtin/log.c b/builtin/log.c
 index 4804229..c972e62 100644
 --- a/builtin/log.c
 +++ b/builtin/log.c
 @@ -1247,7 +1247,7 @@ int cmd_format_patch(int argc, const char **argv, const 
 char *prefix)
   /* Set defaults and check incompatible options */
   if (rev.inline_single) {
   use_stdout = 1;
 - if (cover_letter)
 + if (cover_letter  0)
   die(_(inline-single and cover-letter are 
 incompatible.));
   if (thread)
   die(_(inline-single and thread are incompatible.));
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] t4202 (log): add failing test for log with subtree

2013-04-22 Thread Ramkumar Ramachandra
Ramkumar Ramachandra wrote:
 $ git log README.md

 What do you expect?  The same output you would get if you cloned
 gh:artagnon/clayoven separately and executed 'git log README.md' on
 it.

And the reason I brought up rev-parse in the first place is because
this problem is not unique to log.  Try a 'git shortlog README.md' if
you're not convinced.  The entire revision-walking-pathspec-filtering
mechanism in the log-like-family is broken on trees that are read
into a non-/ prefix.

And no, it doesn't have anything to do with renames or rename
detection.  If it did, 'git shortlog README.md' should atleast give
me the commit that was responsible for the rename.  And if you're
still wondering about --follow, 'git shortlog --follow' (undocumented)
is completely broken.
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] t4202 (log): add test for --follow over a merge

2013-04-22 Thread Ramkumar Ramachandra
The --follow feature can be used to follow the history of a file over
a merge commit, and is useful even when the file hasn't been
copied/renamed.  Add a test to show off this feature.

Signed-off-by: Ramkumar Ramachandra artag...@gmail.com
---
 I haven't updated the documentation, because I can't claim to
 understand --follow fully without reading the code (doing that now).
 In the meantime, I'm contributing a patch I wrote out originally as
 an example for Thomas Rast to prove a point.

 Where should this go?  What is t4206-log-follow-harder-copies (it
 just has one test which isn't even that special)?  Should we move all
 the --follow tests out of this file and put it in a separate file?

 t/t4202-log.sh | 29 +
 1 file changed, 29 insertions(+)

diff --git a/t/t4202-log.sh b/t/t4202-log.sh
index 523c1be..5b041fd 100755
--- a/t/t4202-log.sh
+++ b/t/t4202-log.sh
@@ -168,6 +168,35 @@ test_expect_success 'git log --follow' '
 
 '
 
+test_expect_success '--follow over merge' '
+   git checkout -b featurebranch
+   echo foodle ichi 
+   git add ichi 
+   test_tick 
+   git commit -m add a line to the end of ichi 
+   echo moodle unrelated 
+   git add unrelated 
+   test_tick 
+   git commit -m quux 
+   git checkout master 
+   mv ichi ichi.bak 
+   echo gooble ichi 
+   cat ichi.bak ichi 
+   git add ichi 
+   test_tick 
+   git commit -m add a line to the beginning of ichi 
+   git merge featurebranch 
+   git log --follow --oneline ichi actual 
+   cat expect -\EOF 
+   df26551 add a line to the beginning of ichi
+   882d8d9 add a line to the end of ichi
+   2fbe8c0 third
+   f7dab8e second
+   3a2fdcb initial
+   EOF
+   test_cmp expect actual
+'
+
 test_expect_failure 'log pathspec in tree read into prefix' '
git checkout --orphan subtree 
git rm -rf . 
-- 
1.8.2.1.546.gea3475a

--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [BUG] Silent data loss on merge with uncommited changes + renames

2013-04-22 Thread Junio C Hamano
Matthieu Moy matthieu@grenoble-inp.fr writes:

 I could have expected git merge --abort to fail, but the problem is
 really more serious here: data loss is done silently before giving me an
 opportunity to do or abort anything.

I think this is a well known and longstanding failure case in the
recursive merge.  As it does not perform its internal operation
while handling renames in clean and distinct steps (i.e. figure out
what goes to where before touching any index entry or working tree,
then check if a proposed change to the index or the working tree
conflicts with local changes, and finally carry out the proposed
change), it is somewhat hard to fix it correctly in the current
implementation, even though you probably could patch these up case
by case basis.
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: Patch-to-mail notes resurrected

2013-04-22 Thread Junio C Hamano
Thomas Rast tr...@student.ethz.ch writes:

 As some might remember, I made a script that writes notes (as in
 git-notes) linking patches to emails back in 2009:

   http://thread.gmane.org/gmane.comp.version-control.git/109074

 I resurrected this idea the other week, using a faster implementation
 (the N command in fast-import is great!) and generating better links.
 I am regularly pushing the results to

   git://github.com/trast/git.git
   git://repo.or.cz/git/trast.git

 branches

   notes/gmanea link to the gmane thread view, focused on this patch
   notes/message-id   the raw message-id

 Point your notes.displayRef at one or both to use them.

 It still fails to match some commits, so consider this WIP, but I think
 it's quite useful already.

Thanks ;-)
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] t4202 (log): add failing test for log with subtree

2013-04-22 Thread Thomas Rast
Ramkumar Ramachandra artag...@gmail.com writes:

 Thomas Rast wrote:
 [...]

 I think you've misunderstood the whole thing.  The histories of M^1
 and M^2 are completely unrelated: they're from different projects
 altogether.  Considering the /ichi in M^2 a rename of the /ichi in
 M^1 is completely wrong.  They have nothing to do with each other.  I
 intentionally named it ichi in my orphan branch just to drive my
 point.  I suspect you've got confused because I used an orphan branch
 to emulate a different project's history.  If you want an end-user
 understanding of the problem, use git subtree:

 $ cd /tmp
 $ git clone gh:artagnon/varlog
 $ cd varlog
 $ git subtree add --prefix=clayoven \
gh:artagnon/clayoven master
 $ cd clayoven
 $ git log README.md

 What do you expect?  The same output you would get if you cloned
 gh:artagnon/clayoven separately and executed 'git log README.md' on
 it.

No, I don't.  But that's probably because I know a few things about how
git-log works that your hypothetical $USER doesn't.

At the risk of restating what everyone agrees on: It's a design
principle of git that it only stores tree states, and anything about
diffs, files, renames, etc. is purely in the imagination of the user.

We support that imagination by having analysis tools with which some
things can be found out, but others can't.

So (I think?) in the above you claim that $USER interprets

  git log -- README.md

as

  Show me the history of README.md.

But there's no such thing as the history of a file!  The command instead
says

  If I filter all history for only changes affecting a path 'README.md'
  in the root of the repository[1], then what does it look like?


So please don't write tests that go contrary to that definition, because
they're *wrong*.  The current implementation precisely matches the
current definition of pathspec filtering.

You can try arguing for changing the definition, but unless you find one
that can be implemented fast enough to be generally usable, I will
oppose that change.


The only thing that's broken in any of this is that I think, as
explained on IRC, that a hypothetical fixed --follow -C should be able
to figure out this case.  By spending extra cycles on analysis,
naturally.


[1]  and also skipping lines of history that seem uninteresting at this
point already, compare --simplify-merges

-- 
Thomas Rast
trast@{inf,student}.ethz.ch
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 2/6] show: obey --textconv for blobs

2013-04-22 Thread Junio C Hamano
Jeff King p...@peff.net writes:

 Just my two cents as a reviewer.

 My reasoning is twofold:
 
 - consistency between git show commit and git show blob

 I'm not sure I agree with this line of reasoning. git show commit is
 showing a diff, not the file contents; textconv has always been about
 munging the contents to produce a textual diff. It may be reasonable to
 extend its definition to this is the preferred human view of this
 content, and that happens to be what you would want to produce a diff.
 But I do not think it is necessarily inconsistent not to apply it for
 the blob case.

True.  Applying textconv to otherwise unreadable blobs is often
useful, but I agree that it is unexpected if it is done by default,
especially given that many people have learned to do:

git show HEAD~4:binary-gob old-binary-gob

to recover old version of binary contents to a temporary file when
checking the sanity of or restoring the breakage in the new one.

It of course does _not_ forbid

git show --textconv HEAD~4:binary-gob | less

but I doubt it is a good idea to turn it on by default this late in
the game.
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 2/6] show: obey --textconv for blobs

2013-04-22 Thread Jeff King
On Mon, Apr 22, 2013 at 08:25:41AM -0700, Junio C Hamano wrote:

 True.  Applying textconv to otherwise unreadable blobs is often
 useful, but I agree that it is unexpected if it is done by default,
 especially given that many people have learned to do:
 
   git show HEAD~4:binary-gob old-binary-gob
 
 to recover old version of binary contents to a temporary file when
 checking the sanity of or restoring the breakage in the new one.
 
 It of course does _not_ forbid
 
   git show --textconv HEAD~4:binary-gob | less
 
 but I doubt it is a good idea to turn it on by default this late in
 the game.

Exactly. I certainly do not mind it as an option, and I am on the fence
regarding it as a default (I think it might have been a sane thing to do
from the start, but at this point the change-of-behavior makes me
hesitate). So I am perfectly willing to go either way, depending on what
others think.

I'm going to be out of email contact the rest of the week, so I'll let
you two talk it out. :)

-Peff
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [BUG] Filenames with single colon being treated as remote repository

2013-04-22 Thread Jeff King
On Sun, Apr 21, 2013 at 11:01:58AM -0700, Junio C Hamano wrote:

  I think the rule could be something like:
 
1. If it looks like a URL (^scheme://), it is.
 
2. Otherwise, if it is a path in the filesystem, it is.
 
3. Otherwise, if it has a colon, it's host:path
 
4. Otherwise, barf.
 
  where the interesting bit is the ordering of 2 and 3.  It seems like
  git clone follows the order above with get_repo_path. But we do not
  seem to follow it in git_connect, where we prefer 3 over 2.
 
 At least for a string whose host part does not have any slash,
 switching the rules 2 and 3 in git_connect() would be a regression,
 no?  frotz:/srv/git/git.git has been the way to talk to host frotz
 for a long time, and if you want to talk to a local directory that
 is a subdirectory of frotz:/ directory you have in your $cwd, you
 can disambiguate by saying ./frotz:/srv/git/git.git or something.

Yeah, it would be a regression for fetch, though git clone frotz:/srv
is already broken if that file exists; it turns into `realpath
frotz:/srv` before we even feed it into the fetch machinery.

So I think one reasonable path would be:

  1. Do not treat host:path as ssh if host has a slash, which should
 not regress anybody. It does not allow unadorned relative paths
 with colons, but it lets you use absolute paths or ./ to
 disambiguate.

  2. Teach git-clone to ask the transport code to parse the source repo
 spec, and decide from that whether it is local or not. That would
 harmonize the implementations and avoid errors when you _did_ mean
 to use ssh, but host:path happens to exist in your filesystem. I
 also would not be surprised if there are problems with
 URL-encoding, but maybe clone handles that properly (I didn't
 check).

And the host contains slash rule is pretty easy to explain in the
documentation, which is good.

-Peff
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 2/6] show: obey --textconv for blobs

2013-04-22 Thread Jeremy Rosen
  git show --textconv HEAD~4:binary-gob | less
  
  but I doubt it is a good idea to turn it on by default this late in
  the game.
 
 Exactly. I certainly do not mind it as an option, and I am on the
 fence
 regarding it as a default (I think it might have been a sane thing to
 do
 from the start, but at this point the change-of-behavior makes me
 hesitate). So I am perfectly willing to go either way, depending on
 what
 others think.
 


some features detect if they are piping to a terminal... couldn't we do
something like that ?
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] t4202 (log): add failing test for log with subtree

2013-04-22 Thread Ramkumar Ramachandra
Thomas Rast wrote:
 So (I think?) in the above you claim that $USER interprets

   git log -- README.md

 as

   Show me the history of README.md.

 But there's no such thing as the history of a file!

I made no such claims.  I might not know as much as you or the others
on the list about git, but I can certainly grok how git stores
history.

There needs to be some amount of mutual respect for a healthy
conversation: if you start assuming midway that I don't understand
what history is, we have a problem.

 So please don't write tests that go contrary to that definition, because
 they're *wrong*.  The current implementation precisely matches the
 current definition of pathspec filtering.

Who said anything about changing any definitions?  Where are you
getting all this from?

How does git log HEAD~3 -- README work?  It sets up a revision walk
to start from HEAD~3 going all the way down to the root commit.  In
each of these commits, it looks for the entry README in the
corresponding tree.  It then runs diff-tree with the previous commit's
tree to see if the object (blob) corresponding to the README entry
is different: if so, it selects the commit and displays it.

Now, what am I saying?  I'm saying that this approach assumes that all
trees are read into /.  A pathspec subproject/README is _only_
present in the subtree-merge commit^{tree} and nowhere else.  The
current log algorithm might try to look for the entry
subproject/README (your pathspec) in all the commit^{tree}s of the
commits leading up to M^2.  That is _not_ the problem, as I have
already illustrated that --follow follows over merges.  The problem is
looking for the pathspec subproject/README in the first place: those
commit^{trees}s have the entry stored as README.

Am I making any sense, or are you going to accuse me of not
understanding trees now?
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] t4202 (log): add failing test for log with subtree

2013-04-22 Thread Ramkumar Ramachandra
Thomas Rast wrote:
 The only thing that's broken in any of this is that I think, as
 explained on IRC, that a hypothetical fixed --follow -C should be able
 to figure out this case.  By spending extra cycles on analysis,
 naturally.

For the 100th time, nothing has been copied.  There is no need to
spend time on any analysis.  It's a very straightforward problem that
requires no computation or heuristics: it just requires you to strip
the leading subproject/ when looking for pathspecs in the M^2
commit^{tree}s.  Done.
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] t4202 (log): add failing test for log with subtree

2013-04-22 Thread Ramkumar Ramachandra
Ramkumar Ramachandra wrote:
 For the 100th time, nothing has been copied.  There is no need to
 spend time on any analysis.  It's a very straightforward problem that
 requires no computation or heuristics: it just requires you to strip
 the leading subproject/ when looking for pathspecs in the M^2
 commit^{tree}s.  Done.

And if you're still not convinced, run 'git log HEAD^2 -- README.md'
from the toplevel directory.  You'll get the log of README.md from the
subproject.
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 2/6] show: obey --textconv for blobs

2013-04-22 Thread Matthieu Moy
Jeremy Rosen jeremy.ro...@openwide.fr writes:

 some features detect if they are piping to a terminal... couldn't we do
 something like that ?

That's OK for convenience features like colors or so, but that would be
really, really unexpected to have

$ git show HEAD:file
foo
$ git show HEAD:file  tmp
$ cat tmp
bar

IMHO.

-- 
Matthieu Moy
http://www-verimag.imag.fr/~moy/
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [BUG] Filenames with single colon being treated as remote repository

2013-04-22 Thread Junio C Hamano
Jeff King p...@peff.net writes:

 So I think one reasonable path would be:

   1. Do not treat host:path as ssh if host has a slash, which should
  not regress anybody. It does not allow unadorned relative paths
  with colons, but it lets you use absolute paths or ./ to
  disambiguate.

   2. Teach git-clone to ask the transport code to parse the source repo
  spec, and decide from that whether it is local or not. That would
  harmonize the implementations and avoid errors when you _did_ mean
  to use ssh, but host:path happens to exist in your filesystem. I
  also would not be surprised if there are problems with
  URL-encoding, but maybe clone handles that properly (I didn't
  check).

 And the host contains slash rule is pretty easy to explain in the
 documentation, which is good.

Sounds like a good direction to take us.
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] cherry-pick/revert: make usage say 'commit-ish...'

2013-04-22 Thread Kevin Bracey
The usage string for cherry-pick and revert has never been updated to
reflect their ability to handle multiple commits. Other documentation is
already correct.

Signed-off-by: Kevin Bracey ke...@bracey.fi
---
 builtin/revert.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/builtin/revert.c b/builtin/revert.c
index c5e36b9..0401fdb 100644
--- a/builtin/revert.c
+++ b/builtin/revert.c
@@ -19,13 +19,13 @@
  */
 
 static const char * const revert_usage[] = {
-   N_(git revert [options] commit-ish),
+   N_(git revert [options] commit-ish...),
N_(git revert subcommand),
NULL
 };
 
 static const char * const cherry_pick_usage[] = {
-   N_(git cherry-pick [options] commit-ish),
+   N_(git cherry-pick [options] commit-ish...),
N_(git cherry-pick subcommand),
NULL
 };
-- 
1.8.2.255.g39c5835

--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] zlib: fix compilation failures with Sun C Compilaer

2013-04-22 Thread Stefano Lattarini
Do this by removing a couple of useless return statements.  Without this
change, compilation with Sun C Compiler 5.9 (SunOS_i386 Patch 124868-15
2010/08/11) fails with the following message:

  zlib.c, line 192: void function cannot return value
  zlib.c, line 201: void function cannot return value
  cc: acomp failed for zlib.c

Signed-off-by: Stefano Lattarini stefano.lattar...@gmail.com
---
 zlib.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/zlib.c b/zlib.c
index bbaa081..61e6df0 100644
--- a/zlib.c
+++ b/zlib.c
@@ -189,7 +189,7 @@ void git_deflate_init_gzip(git_zstream *strm, int level)
 * Use default 15 bits, +16 is to generate gzip header/trailer
 * instead of the zlib wrapper.
 */
-   return do_git_deflate_init(strm, level, 15 + 16);
+   do_git_deflate_init(strm, level, 15 + 16);
 }
 
 void git_deflate_init_raw(git_zstream *strm, int level)
@@ -198,7 +198,7 @@ void git_deflate_init_raw(git_zstream *strm, int level)
 * Use default 15 bits, negate the value to get raw compressed
 * data without zlib header and trailer.
 */
-   return do_git_deflate_init(strm, level, -15);
+   do_git_deflate_init(strm, level, -15);
 }
 
 int git_deflate_abort(git_zstream *strm)
-- 
1.8.1.rc3.897.gb3600c3

--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] t4202 (log): add failing test for log with subtree

2013-04-22 Thread Junio C Hamano
Thomas Rast tr...@inf.ethz.ch writes:

 So (I think?) in the above you claim that $USER interprets

   git log -- README.md

 as

   Show me the history of README.md.

 But there's no such thing as the history of a file!  The command instead
 says

   If I filter all history for only changes affecting a path 'README.md'
   in the root of the repository[1], then what does it look like?

Correct.  The design principle I did not quote from your message
comes from one of the most important messages in the list archive
($gmane/217).

Three issues with --follow are:

 (1) It uses the given pathname as single pathspec and drill down
 the same way without --follow until it notices the path
 disappears and until then there is no attempt to detect renames
 is made.  And it only does -M variant of rename detection

 (2) The same way in (1) includes the merge simplification to cull
 side branches if one parent matches the end result.  In a
 history where the first parent of a merge M, i.e. M^1, did not
 have path F, its second parent M^2 had path F, and the merge
 result M deposited the contents of M^2:F at M:D/F, then running
 log --follow F starting from M would notice that the end
 result M did not have F in it, which is shared with its first
 parent M^1, and culls the side branch M^2.  The --full-history
 option may let you keep the history leading to M^2, though.

 (3) When (1) notices that the path being followed did not exist in
 any of the parents (be it a merge or a non-merge) and finds a
 different path with a similar looking content, it _switches_
 the pathspec to it, but the single pathspec it uses is a global
 state and affects traversals of other ancestry paths at the
 same time.  Because of this, --follow will not work correctly
 in a history that contains merges.  It often _appears_ to work
 only by accident.

The first two are relatively minor (the second is not even an
issue).

To solve the last one, you would need to keep track of which path it
is following per traversal path.
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] zlib: fix compilation failures with Sun C Compilaer

2013-04-22 Thread Junio C Hamano
Stefano Lattarini stefano.lattar...@gmail.com writes:

 Do this by removing a couple of useless return statements.  Without this
 change, compilation with Sun C Compiler 5.9 (SunOS_i386 Patch 124868-15
 2010/08/11) fails with the following message:

   zlib.c, line 192: void function cannot return value
   zlib.c, line 201: void function cannot return value
   cc: acomp failed for zlib.c

Thanks for catching a recent regression in the mainline before any
tagged release is made out of it.  Very much appreciated.


 Signed-off-by: Stefano Lattarini stefano.lattar...@gmail.com
 ---
  zlib.c | 4 ++--
  1 file changed, 2 insertions(+), 2 deletions(-)

 diff --git a/zlib.c b/zlib.c
 index bbaa081..61e6df0 100644
 --- a/zlib.c
 +++ b/zlib.c
 @@ -189,7 +189,7 @@ void git_deflate_init_gzip(git_zstream *strm, int level)
* Use default 15 bits, +16 is to generate gzip header/trailer
* instead of the zlib wrapper.
*/
 - return do_git_deflate_init(strm, level, 15 + 16);
 + do_git_deflate_init(strm, level, 15 + 16);
  }
  
  void git_deflate_init_raw(git_zstream *strm, int level)
 @@ -198,7 +198,7 @@ void git_deflate_init_raw(git_zstream *strm, int level)
* Use default 15 bits, negate the value to get raw compressed
* data without zlib header and trailer.
*/
 - return do_git_deflate_init(strm, level, -15);
 + do_git_deflate_init(strm, level, -15);
  }
  
  int git_deflate_abort(git_zstream *strm)
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] zlib: fix compilation failures with Sun C Compilaer

2013-04-22 Thread René Scharfe

Am 22.04.2013 18:18, schrieb Stefano Lattarini:

Do this by removing a couple of useless return statements.  Without this
change, compilation with Sun C Compiler 5.9 (SunOS_i386 Patch 124868-15
2010/08/11) fails with the following message:

   zlib.c, line 192: void function cannot return value
   zlib.c, line 201: void function cannot return value
   cc: acomp failed for zlib.c


Hmm, what was I thinking when I introduced these returns in c3c2e1a0? 
:-/ Thanks for catching!


René

--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] t4202 (log): add failing test for log with subtree

2013-04-22 Thread Ramkumar Ramachandra
Ramkumar Ramachandra wrote:
 And if you're still not convinced, run 'git log HEAD^2 -- README.md'
 from the toplevel directory.  You'll get the log of README.md from the
 subproject.

On IRC, Thomas explained to me that mixing in changes from various
branches into the pathspec will break this so-called determinism.  To
try it out for yourself, do:

$ cd /tmp
$ git clone gh:trast/subtree-mainline-example
$ cd subtree-mainline-example
$ git log HEAD^2 -- sub # only lists the side changes
$ git log -- dir/sub # only lists the mainline changes

What we should really expect is a mix of the two.
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] zlib: fix compilation failures with Sun C Compilaer

2013-04-22 Thread Stefano Lattarini
On 04/22/2013 06:48 PM, Junio C Hamano wrote:
 Stefano Lattarini stefano.lattar...@gmail.com writes:
 
 Do this by removing a couple of useless return statements.  Without this
 change, compilation with Sun C Compiler 5.9 (SunOS_i386 Patch 124868-15
 2010/08/11) fails with the following message:

   zlib.c, line 192: void function cannot return value
   zlib.c, line 201: void function cannot return value
   cc: acomp failed for zlib.c
 
 Thanks for catching a recent regression in the mainline before any
 tagged release is made out of it.  Very much appreciated.

Actually, I tried to build the bleeding-edge git on Solaris to use it
myself, rather than to test it ;-)  So, thanks to you and all the git
contributors for continuously improving the package, thus making it
worth to try to build and use the bleeding-edge version.

Best regards,
  Stefano
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] t4202 (log): add failing test for log with subtree

2013-04-22 Thread Ramkumar Ramachandra
Junio C Hamano wrote:
 [...]
  (3) When (1) notices that the path being followed did not exist in
  any of the parents (be it a merge or a non-merge) and finds a
  different path with a similar looking content, it _switches_
  the pathspec to it, but the single pathspec it uses is a global
  state and affects traversals of other ancestry paths at the
  same time.  Because of this, --follow will not work correctly
  in a history that contains merges.  It often _appears_ to work
  only by accident.

This explanation is all very nice, but isn't it completely tangential
to the issue at hand?

Let's say I have a subtree merge M located at HEAD~4.  I ask for the
log of 'HEAD~4 -- README' with --follow.  It follows until it gets to
M: at M, M^1:README is missing, but M^2:README is present.  Should it
follow down and show the history of M^2:README?

You can reserve the discussion about --follow working in the general
case for another thread.  Meanwhile, you're evading the issue of
assuming that all trees are read into /, and are really representing
the same project's history, while this is not the case.
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2 4/5] check-ignore: allow incremental streaming of queries via --stdin

2013-04-22 Thread Junio C Hamano
Adam Spiers g...@adamspiers.org writes:

 On Thu, Apr 11, 2013 at 03:11:32PM -0400, Jeff King wrote:
 I always get a little nervous with sleeps in the test suite, as they are
 indicative that we are trying to avoid some race condition, which means
 that the test can fail when the system is under load, or when a tool
 like valgrind is used which drastically alters the timing (e.g., if
 check-ignore takes longer than 1 second to produce its answer, we may
 fail here).

 Agreed, especially here where my btrfs filesystems see fit to kindly
 freeze my system for a few seconds many times each day :-/
 
 Is there a simpler way to test this?
 
 Like:
 ...
 I'll re-roll using your approach.

I think I missed this one and it already is in 'next'.

I'll hold it back so please make your re-roll into an incremental
update.

Thanks.
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] t4202 (log): add failing test for log with subtree

2013-04-22 Thread Matthieu Moy
Ramkumar Ramachandra artag...@gmail.com writes:

 Meanwhile, you're evading the issue of assuming that all trees are
 read into /, and are really representing the same project's history,
 while this is not the case.

This is fundamenally how Git works. Git works with commit objects, each
commit object points to a tree object that represent / at this commit.

When you do a subtree merge, you include the tree that was in / in a
subtree of the master project. Files used to exist as /file, and now
exist as /subtree/file. There is nothing recording that the new
/subtree/file comes from /file in its second parent. Call this a
renaming or not, but git log subtree/file won't show you changes
touching /file by default, and this is the case for the history of the
subproject you are merging.

A subtree merge is really a rename of the subproject's file plus a
merge, done in the same commit. Try doing something like

mkdir -p subproject
git mv * subproject/
git commit

in your subproject before doing a merge, you'll get the same result,
except there will be one more commit.

-- 
Matthieu Moy
http://www-verimag.imag.fr/~moy/
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] t4202 (log): add failing test for log with subtree

2013-04-22 Thread Junio C Hamano
Ramkumar Ramachandra artag...@gmail.com writes:

 Junio C Hamano wrote:
 [...]
  (3) When (1) notices that the path being followed did not exist in
  any of the parents (be it a merge or a non-merge) and finds a
  different path with a similar looking content, it _switches_
  the pathspec to it, but the single pathspec it uses is a global
  state and affects traversals of other ancestry paths at the
  same time.  Because of this, --follow will not work correctly
  in a history that contains merges.  It often _appears_ to work
  only by accident.

 This explanation is all very nice, but isn't it completely tangential
 to the issue at hand?

I think you are talking mostly about (2), but the primary purpose of
my message was not about your specific issue.

It was to give a larger picture to people who may be inclined to
tackle, and may be capable of tackling, the real issues in the
--follow codepath.  Anybody who wants to update it needs to be
aware of all three.

--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] t4202 (log): add failing test for log with subtree

2013-04-22 Thread Thomas Rast
Ramkumar Ramachandra artag...@gmail.com writes:

 Ramkumar Ramachandra wrote:
 And if you're still not convinced, run 'git log HEAD^2 -- README.md'
 from the toplevel directory.  You'll get the log of README.md from the
 subproject.

 On IRC, Thomas explained to me that mixing in changes from various
 branches into the pathspec will break this so-called determinism.  To
 try it out for yourself, do:

 $ cd /tmp
 $ git clone gh:trast/subtree-mainline-example
 $ cd subtree-mainline-example
 $ git log HEAD^2 -- sub # only lists the side changes
 $ git log -- dir/sub # only lists the mainline changes

 What we should really expect is a mix of the two.

So after lots of confusing misunderstandings across the entire thread,
and a long IRC discussion, I do have one take-away that I think is worth
writing down:

There is a market for a rename detection that works at the tree level.

Bear with me while I explain.

The average subtree merge (after the initial one) looks like this,
focusing on the subtree:

  Mnew state in sub/
  | \
  |  * new state in /
  |
  * old state in sub/

(The example in the quote above additionally complicates the issue by
changing sub/ in the mainline.)

Ideally we'd like our hypothetical fixed --follow to accurately track a
pathspec 'sub/foo' so that in the mainline it remains the same, but in
the side it becomes 'foo'.  Because of reasons already explained in
earlier mails, -M does not suffice for all cases (in particular, it
fails if there is a /foo in the mainline too).  -C works, but is slow.

So how can we fix that?  We could try to somehow figure out that M:sub/
refers to the same thing as M^2:/, by looking at them at the tree level.
Let's provisionally call this --follow-tree-rename.

I don't quite know how to heuristically[1] detect such a rename, but
since 'merge -ssubtree' does it (if you don't specify a tree prefix
explicitly), it can't be That Hard(tm).  If we're extra lucky it's fast
enough to be enabled by default.

In the special case where the subtree was not modified in the mainline
since the last merge, the problem is pretty trivial: simply check if any
subtree of M agrees with the root tree of each merge parent; if so, diff
those trees instead of the root trees.

That should then help subtree users to get better logs.


[1]  the quoted example shows that you can't just go looking for
identical trees in the general case, so it is really a heuristic

-- 
Thomas Rast
trast@{inf,student}.ethz.ch
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] git-imap-send.txt: remove the use of sslverify=false

2013-04-22 Thread Barbu Paul - Gheorghe
Since SSL provides no protection if the certificates aren't verified it's
better not to include sslverify=false in the examples.
Also in the post 1.8.2.1 era git is able to properly verify the validity of a
certificate as well it's origin.

Signed-off-by: Barbu Paul - Gheorghe barbu.paul.gheor...@gmail.com
---
 Documentation/git-imap-send.txt | 2 --
 1 file changed, 2 deletions(-)

diff --git a/Documentation/git-imap-send.txt b/Documentation/git-imap-send.txt
index 875d283..0d72977 100644
--- a/Documentation/git-imap-send.txt
+++ b/Documentation/git-imap-send.txt
@@ -108,7 +108,6 @@ Using direct mode with SSL:
 user = bob
 pass = p4ssw0rd
 port = 123
-sslverify = false
 ..
  @@ -123,7 +122,6 @@ to specify your account settings:
host = imaps://imap.gmail.com
user = u...@gmail.com
port = 993
-   sslverify = false
 -
  You might need to instead use: folder = [Google Mail]/Drafts if you get an 
error
-- 
Barbu Paul - Gheorghe
Common sense is not so common - Voltaire
Visit My GitHub profile to see my open-source projects - 
https://github.com/paullik

--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[RFC/PATCH] Make --full-history consider more merges

2013-04-22 Thread Kevin Bracey
History simplification previously always treated merges as TREESAME
if they were TREESAME to any parent.

While the desired default behaviour, this could be extremely unhelpful
when searching detailed history, and could not be overridden. For
example, if a merge had ignored a change, as if by -s ours, then:

  git log -m -p --full-history -Schange file

would successfully locate change's addition but would not locate the
merge that resolved against it.

This patch changes the simplification so that when --full-history is
specified, a merge is treated as TREESAME only if it is TREESAME to
_all_ parents. This means the command above locates a merge that dropped
change.

Signed-off-by: Kevin Bracey ke...@bracey.fi
---
This would address my problem case - it passes existing tests, and covers
my (all-too-common) problem. But it would also need documentation changes and
a new test.

 revision.c | 10 --
 1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/revision.c b/revision.c
index eb98128..96fe3f5 100644
--- a/revision.c
+++ b/revision.c
@@ -516,8 +516,14 @@ static void try_to_simplify_commit(struct rev_info *revs, 
struct commit *commit)
}
die(bad tree compare for commit %s, 
sha1_to_hex(commit-object.sha1));
}
-   if (tree_changed  !tree_same)
-   return;
+
+   if (tree_changed) {
+   if (!tree_same)
+   return;
+
+   if (!revs-simplify_history  !revs-simplify_merges)
+   return;
+   }
commit-object.flags |= TREESAME;
 }
 
-- 
1.8.2.255.g39c5835

--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [RFC/PATCH] Make --full-history consider more merges

2013-04-22 Thread Junio C Hamano
Kevin Bracey ke...@bracey.fi writes:

 diff --git a/revision.c b/revision.c
 index eb98128..96fe3f5 100644
 --- a/revision.c
 +++ b/revision.c
 @@ -516,8 +516,14 @@ static void try_to_simplify_commit(struct rev_info 
 *revs, struct commit *commit)
   }
   die(bad tree compare for commit %s, 
 sha1_to_hex(commit-object.sha1));
   }
 - if (tree_changed  !tree_same)
 - return;
 +
 + if (tree_changed) {
 + if (!tree_same)
 + return;
 +
 + if (!revs-simplify_history  !revs-simplify_merges)
 + return;

So in addition to have some change and there is no same parent
case, under _some_ condition we avoid marking a merge not worth
showing (i.e. TREESAME) if there is any change.

And the condition is !simplify_history and !simplify_merges, which
would cover --full-history, but I am not sure if requiring
!simplify_merges is correct.

Do you need it and if so why?  The --simplify-merges option is
defined as a post-processing operation over what full-history
produces in the list limiting code (which involves the logic the
patch is touching).  The --ancestry-path option works the same way
but its post-processing is done inside the limit_list() function.

So it feels more natural if the patch were ignoring simplify_merges
and paid attention only to simplify_history.

 + }
   commit-object.flags |= TREESAME;
  }
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 00/33] Various cleanups around reference packing and peeling

2013-04-22 Thread Michael Haggerty
Thanks for the feedback; here is a re-roll.  A number of points
discussed on the mailing list were fixed.  The main change, in patch
17, is how repack_without_ref() deals with references that cannot be
peeled when re-writing the packed-refs file:

if ISBROKEN:
emit an error and omit reference from the output
else if !has_sha1_file(...):
if there is an overriding loose reference:
silently omit reference from the output
else:
emit an error and omit reference from the output

Please note that this creates a relatively harmless race condition
very similar to the ones discussed for pack-refs; see the commit
message for patch 17 for a long explanation.  I would like to fix all
of the races as part of a separate patch series.

For now I left the sleeps in t3210.  Given that the problem will be
solved by topic jc/prune-all, building a fancier workaround into this
test for the old broken --expire behavior seems like a waste of time.
I propose that the sleeps be removed when this patch series is merged
with jc/prune-all.  (In fact, when jc/prune-all is landed, other tests
can also be simplified.)  If this suggestion is not ok, then the
easiest thing would probably be to remove the sleeps immediately and
declare jc/prune-all a prerequisite of this series.

I also removed the trailing comma from the enum peel_status
definition, because a recent email on the mailing list claimed that
some compilers don't like them.

Michael Haggerty (33):
  refs: document flags constants REF_*
  refs: document the fields of struct ref_value
  refs: document do_for_each_ref() and do_one_ref()
  refs: document how current_ref is used
  refs: define constant PEELED_LINE_LENGTH
  do_for_each_ref_in_dirs(): remove dead code
  get_packed_ref(): return a ref_entry
  peel_ref(): use function get_packed_ref()
  repack_without_ref(): use function get_packed_ref()
  refs: extract a function ref_resolves_to_object()
  refs: extract function peel_object()
  peel_object(): give more specific information in return value
  peel_ref(): fix return value for non-peelable, not-current reference
  refs: extract a function peel_entry()
  refs: change the internal reference-iteration API
  t3210: test for spurious error messages for dangling packed refs
  repack_without_ref(): silence errors for dangling packed refs
  search_ref_dir(): return an index rather than a pointer
  refs: change how packed refs are deleted
  t3211: demonstrate loss of peeled refs if a packed ref is deleted
  repack_without_ref(): write peeled refs in the rewritten file
  refs: extract a function write_packed_entry()
  pack-refs: rename handle_one_ref() to pack_one_ref()
  pack-refs: merge code from pack-refs.{c,h} into refs.{c,h}
  pack_one_ref(): rename path parameter to refname
  refs: use same lock_file object for both ref-packing functions
  pack_refs(): change to use do_for_each_entry()
  refs: inline function do_not_prune()
  pack_one_ref(): use function peel_entry()
  pack_one_ref(): use write_packed_entry() to do the writing
  pack_one_ref(): do some cheap tests before a more expensive one
  refs: change do_for_each_*() functions to take ref_cache arguments
  refs: handle the main ref_cache specially

 Makefile |   2 -
 builtin/clone.c  |   1 -
 builtin/pack-refs.c  |   2 +-
 pack-refs.c  | 148 ---
 pack-refs.h  |  18 --
 refs.c   | 733 +++
 refs.h   |  35 +++
 t/t3210-pack-refs.sh |  36 +++
 t/t3211-peel-ref.sh  |   9 +
 9 files changed, 643 insertions(+), 341 deletions(-)
 delete mode 100644 pack-refs.c
 delete mode 100644 pack-refs.h

-- 
1.8.2.1

--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 01/33] refs: document flags constants REF_*

2013-04-22 Thread Michael Haggerty
Document the bits that can appear in the flags parameter passed to
an each_ref_function and/or in the ref_entry::flag field.

Signed-off-by: Michael Haggerty mhag...@alum.mit.edu
---
 refs.c | 12 +++-
 refs.h | 13 +
 2 files changed, 24 insertions(+), 1 deletion(-)

diff --git a/refs.c b/refs.c
index de2d8eb..30b4bf7 100644
--- a/refs.c
+++ b/refs.c
@@ -158,7 +158,17 @@ struct ref_dir {
struct ref_entry **entries;
 };
 
-/* ISSYMREF=0x01, ISPACKED=0x02, and ISBROKEN=0x04 are public interfaces */
+/*
+ * Bit values for ref_entry::flag.  REF_ISSYMREF=0x01,
+ * REF_ISPACKED=0x02, and REF_ISBROKEN=0x04 are public values; see
+ * refs.h.
+ */
+
+/*
+ * The field ref_entry-u.value.peeled of this value entry contains
+ * the correct peeled value for the reference, which might be
+ * null_sha1 if the reference is not a tag or if it is broken.
+ */
 #define REF_KNOWS_PEELED 0x08
 
 /* ref_entry represents a directory of references */
diff --git a/refs.h b/refs.h
index a35eafc..17bc1c1 100644
--- a/refs.h
+++ b/refs.h
@@ -10,8 +10,21 @@ struct ref_lock {
int force_write;
 };
 
+/*
+ * Bit values set in the flags argument passed to each_ref_fn():
+ */
+
+/* Reference is a symbolic reference. */
 #define REF_ISSYMREF 0x01
+
+/* Reference is a packed reference. */
 #define REF_ISPACKED 0x02
+
+/*
+ * Reference cannot be resolved to an object name: dangling symbolic
+ * reference (directly or indirectly), corrupt reference file, or
+ * symbolic reference refers to ill-formatted reference name.
+ */
 #define REF_ISBROKEN 0x04
 
 /*
-- 
1.8.2.1

--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 03/33] refs: document do_for_each_ref() and do_one_ref()

2013-04-22 Thread Michael Haggerty

Signed-off-by: Michael Haggerty mhag...@alum.mit.edu
---
 refs.c | 15 ++-
 1 file changed, 14 insertions(+), 1 deletion(-)

diff --git a/refs.c b/refs.c
index 1df1ccd..44cc2fc 100644
--- a/refs.c
+++ b/refs.c
@@ -525,10 +525,14 @@ static void sort_ref_dir(struct ref_dir *dir)
dir-sorted = dir-nr = i;
 }
 
-#define DO_FOR_EACH_INCLUDE_BROKEN 01
+/* Include broken references in a do_for_each_ref*() iteration: */
+#define DO_FOR_EACH_INCLUDE_BROKEN 0x01
 
 static struct ref_entry *current_ref;
 
+/*
+ * Handle one reference in a do_for_each_ref*()-style iteration.
+ */
 static int do_one_ref(const char *base, each_ref_fn fn, int trim,
  int flags, void *cb_data, struct ref_entry *entry)
 {
@@ -1338,6 +1342,15 @@ void warn_dangling_symref(FILE *fp, const char *msg_fmt, 
const char *refname)
for_each_rawref(warn_if_dangling_symref, data);
 }
 
+/*
+ * Call fn for each reference in the specified submodule for which the
+ * refname begins with base.  If trim is non-zero, then trim that many
+ * characters off the beginning of each refname before passing the
+ * refname to fn.  flags can be DO_FOR_EACH_INCLUDE_BROKEN to include
+ * broken references in the iteration.  If fn ever returns a non-zero
+ * value, stop the iteration and return that value; otherwise, return
+ * 0.
+ */
 static int do_for_each_ref(const char *submodule, const char *base, 
each_ref_fn fn,
   int trim, int flags, void *cb_data)
 {
-- 
1.8.2.1

--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 02/33] refs: document the fields of struct ref_value

2013-04-22 Thread Michael Haggerty

Signed-off-by: Michael Haggerty mhag...@alum.mit.edu
---
 refs.c | 12 
 1 file changed, 12 insertions(+)

diff --git a/refs.c b/refs.c
index 30b4bf7..1df1ccd 100644
--- a/refs.c
+++ b/refs.c
@@ -109,7 +109,19 @@ struct ref_entry;
  * (ref_entry-flag  REF_DIR) is zero.
  */
 struct ref_value {
+   /*
+* The name of the object to which this reference resolves
+* (which may be a tag object).  If REF_ISBROKEN, this is
+* null.  If REF_ISSYMREF, then this is the name of the object
+* referred to by the last reference in the symlink chain.
+*/
unsigned char sha1[20];
+
+   /*
+* If REF_KNOWS_PEELED, then this field holds the peeled value
+* of this reference, or null if the reference is known not to
+* be peelable.
+*/
unsigned char peeled[20];
 };
 
-- 
1.8.2.1

--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 04/33] refs: document how current_ref is used

2013-04-22 Thread Michael Haggerty

Signed-off-by: Michael Haggerty mhag...@alum.mit.edu
---
 refs.c | 9 +
 1 file changed, 9 insertions(+)

diff --git a/refs.c b/refs.c
index 44cc2fc..efad658 100644
--- a/refs.c
+++ b/refs.c
@@ -528,6 +528,15 @@ static void sort_ref_dir(struct ref_dir *dir)
 /* Include broken references in a do_for_each_ref*() iteration: */
 #define DO_FOR_EACH_INCLUDE_BROKEN 0x01
 
+/*
+ * current_ref is a performance hack: when iterating over references
+ * using the for_each_ref*() functions, current_ref is set to the
+ * current reference's entry before calling the callback function.  If
+ * the callback function calls peel_ref(), then peel_ref() first
+ * checks whether the reference to be peeled is the current reference
+ * (it usually is) and if so, returns that reference's peeled version
+ * if it is available.  This avoids a refname lookup in a common case.
+ */
 static struct ref_entry *current_ref;
 
 /*
-- 
1.8.2.1

--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 07/33] get_packed_ref(): return a ref_entry

2013-04-22 Thread Michael Haggerty
Instead of copying the reference's SHA1 into a caller-supplied
variable, just return the ref_entry itself (or NULL if there is no
such entry).  This change will allow the function to be used from
elsewhere.

Signed-off-by: Michael Haggerty mhag...@alum.mit.edu
---
 refs.c | 20 +---
 1 file changed, 9 insertions(+), 11 deletions(-)

diff --git a/refs.c b/refs.c
index 7260768..91a2940 100644
--- a/refs.c
+++ b/refs.c
@@ -1100,18 +1100,12 @@ int resolve_gitlink_ref(const char *path, const char 
*refname, unsigned char *sh
 }
 
 /*
- * Try to read ref from the packed references.  On success, set sha1
- * and return 0; otherwise, return -1.
+ * Return the ref_entry for the given refname from the packed
+ * references.  If it does not exist, return NULL.
  */
-static int get_packed_ref(const char *refname, unsigned char *sha1)
+static struct ref_entry *get_packed_ref(const char *refname)
 {
-   struct ref_dir *packed = get_packed_refs(get_ref_cache(NULL));
-   struct ref_entry *entry = find_ref(packed, refname);
-   if (entry) {
-   hashcpy(sha1, entry-u.value.sha1);
-   return 0;
-   }
-   return -1;
+   return find_ref(get_packed_refs(get_ref_cache(NULL)), refname);
 }
 
 const char *resolve_ref_unsafe(const char *refname, unsigned char *sha1, int 
reading, int *flag)
@@ -1139,13 +1133,17 @@ const char *resolve_ref_unsafe(const char *refname, 
unsigned char *sha1, int rea
git_snpath(path, sizeof(path), %s, refname);
 
if (lstat(path, st)  0) {
+   struct ref_entry *entry;
+
if (errno != ENOENT)
return NULL;
/*
 * The loose reference file does not exist;
 * check for a packed reference.
 */
-   if (!get_packed_ref(refname, sha1)) {
+   entry = get_packed_ref(refname);
+   if (entry) {
+   hashcpy(sha1, entry-u.value.sha1);
if (flag)
*flag |= REF_ISPACKED;
return refname;
-- 
1.8.2.1

--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 08/33] peel_ref(): use function get_packed_ref()

2013-04-22 Thread Michael Haggerty

Signed-off-by: Michael Haggerty mhag...@alum.mit.edu
---
 refs.c | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/refs.c b/refs.c
index 91a2940..09b68e4 100644
--- a/refs.c
+++ b/refs.c
@@ -1282,10 +1282,9 @@ int peel_ref(const char *refname, unsigned char *sha1)
return -1;
 
if ((flag  REF_ISPACKED)) {
-   struct ref_dir *dir = get_packed_refs(get_ref_cache(NULL));
-   struct ref_entry *r = find_ref(dir, refname);
+   struct ref_entry *r = get_packed_ref(refname);
 
-   if (r != NULL  r-flag  REF_KNOWS_PEELED) {
+   if (r  (r-flag  REF_KNOWS_PEELED)) {
hashcpy(sha1, r-u.value.peeled);
return 0;
}
-- 
1.8.2.1

--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 11/33] refs: extract function peel_object()

2013-04-22 Thread Michael Haggerty
It is a nice, logical unit of work, and putting it in a function
removes the need to use a goto in peel_ref().  Soon it will also have
other uses.

The algorithm is unchanged.

Signed-off-by: Michael Haggerty mhag...@alum.mit.edu
---
 refs.c | 50 ++
 1 file changed, 30 insertions(+), 20 deletions(-)

diff --git a/refs.c b/refs.c
index 8b554d8..b0ef129 100644
--- a/refs.c
+++ b/refs.c
@@ -1272,11 +1272,38 @@ static int filter_refs(const char *refname, const 
unsigned char *sha1, int flags
return filter-fn(refname, sha1, flags, filter-cb_data);
 }
 
+/*
+ * Peel the named object; i.e., if the object is a tag, resolve the
+ * tag recursively until a non-tag is found.  Store the result to sha1
+ * and return 0 iff successful.  If the object is not a tag or is not
+ * valid, return -1 and leave sha1 unchanged.
+ */
+static int peel_object(const unsigned char *name, unsigned char *sha1)
+{
+   struct object *o = lookup_unknown_object(name);
+
+   if (o-type == OBJ_NONE) {
+   int type = sha1_object_info(name, NULL);
+   if (type  0)
+   return -1;
+   o-type = type;
+   }
+
+   if (o-type != OBJ_TAG)
+   return -1;
+
+   o = deref_tag_noverify(o);
+   if (!o)
+   return -1;
+
+   hashcpy(sha1, o-sha1);
+   return 0;
+}
+
 int peel_ref(const char *refname, unsigned char *sha1)
 {
int flag;
unsigned char base[20];
-   struct object *o;
 
if (current_ref  (current_ref-name == refname
|| !strcmp(current_ref-name, refname))) {
@@ -1286,8 +1313,7 @@ int peel_ref(const char *refname, unsigned char *sha1)
hashcpy(sha1, current_ref-u.value.peeled);
return 0;
}
-   hashcpy(base, current_ref-u.value.sha1);
-   goto fallback;
+   return peel_object(current_ref-u.value.sha1, sha1);
}
 
if (read_ref_full(refname, base, 1, flag))
@@ -1302,23 +1328,7 @@ int peel_ref(const char *refname, unsigned char *sha1)
}
}
 
-fallback:
-   o = lookup_unknown_object(base);
-   if (o-type == OBJ_NONE) {
-   int type = sha1_object_info(base, NULL);
-   if (type  0)
-   return -1;
-   o-type = type;
-   }
-
-   if (o-type == OBJ_TAG) {
-   o = deref_tag_noverify(o);
-   if (o) {
-   hashcpy(sha1, o-sha1);
-   return 0;
-   }
-   }
-   return -1;
+   return peel_object(base, sha1);
 }
 
 struct warn_if_dangling_data {
-- 
1.8.2.1

--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 12/33] peel_object(): give more specific information in return value

2013-04-22 Thread Michael Haggerty
Instead of just returning a success/failure bit, return an enumeration
value that explains the reason for any failure.  This will come in
handy shortly.

Signed-off-by: Michael Haggerty mhag...@alum.mit.edu
---
 refs.c | 32 
 1 file changed, 24 insertions(+), 8 deletions(-)

diff --git a/refs.c b/refs.c
index b0ef129..d26e847 100644
--- a/refs.c
+++ b/refs.c
@@ -1272,32 +1272,48 @@ static int filter_refs(const char *refname, const 
unsigned char *sha1, int flags
return filter-fn(refname, sha1, flags, filter-cb_data);
 }
 
+enum peel_status {
+   /* object was peeled successfully: */
+   PEEL_PEELED = 0,
+
+   /*
+* object cannot be peeled because the named object (or an
+* object referred to by a tag in the peel chain), does not
+* exist.
+*/
+   PEEL_INVALID = -1,
+
+   /* object cannot be peeled because it is not a tag: */
+   PEEL_NON_TAG = -2
+};
+
 /*
  * Peel the named object; i.e., if the object is a tag, resolve the
- * tag recursively until a non-tag is found.  Store the result to sha1
- * and return 0 iff successful.  If the object is not a tag or is not
- * valid, return -1 and leave sha1 unchanged.
+ * tag recursively until a non-tag is found.  If successful, store the
+ * result to sha1 and return PEEL_PEELED.  If the object is not a tag
+ * or is not valid, return PEEL_NON_TAG or PEEL_INVALID, respectively,
+ * and leave sha1 unchanged.
  */
-static int peel_object(const unsigned char *name, unsigned char *sha1)
+static enum peel_status peel_object(const unsigned char *name, unsigned char 
*sha1)
 {
struct object *o = lookup_unknown_object(name);
 
if (o-type == OBJ_NONE) {
int type = sha1_object_info(name, NULL);
if (type  0)
-   return -1;
+   return PEEL_INVALID;
o-type = type;
}
 
if (o-type != OBJ_TAG)
-   return -1;
+   return PEEL_NON_TAG;
 
o = deref_tag_noverify(o);
if (!o)
-   return -1;
+   return PEEL_INVALID;
 
hashcpy(sha1, o-sha1);
-   return 0;
+   return PEEL_PEELED;
 }
 
 int peel_ref(const char *refname, unsigned char *sha1)
-- 
1.8.2.1

--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 13/33] peel_ref(): fix return value for non-peelable, not-current reference

2013-04-22 Thread Michael Haggerty
The old version was inconsistent: when a reference was
REF_KNOWS_PEELED but with a null peeled value, it returned non-zero
for the current reference but zero for other references.  Change the
behavior for non-current references to match that of current_ref,
which is what callers expect.  Document the behavior.

Current callers only call peel_ref() from within a for_each_ref-style
iteration and only for the current ref; therefore, the buggy code path
was never reached.

Signed-off-by: Michael Haggerty mhag...@alum.mit.edu
---
 refs.c | 5 -
 refs.h | 8 
 2 files changed, 12 insertions(+), 1 deletion(-)

diff --git a/refs.c b/refs.c
index d26e847..2f73189 100644
--- a/refs.c
+++ b/refs.c
@@ -120,7 +120,8 @@ struct ref_value {
/*
 * If REF_KNOWS_PEELED, then this field holds the peeled value
 * of this reference, or null if the reference is known not to
-* be peelable.
+* be peelable.  See the documentation for peel_ref() for an
+* exact definition of peelable.
 */
unsigned char peeled[20];
 };
@@ -1339,6 +1340,8 @@ int peel_ref(const char *refname, unsigned char *sha1)
struct ref_entry *r = get_packed_ref(refname);
 
if (r  (r-flag  REF_KNOWS_PEELED)) {
+   if (is_null_sha1(r-u.value.peeled))
+   return -1;
hashcpy(sha1, r-u.value.peeled);
return 0;
}
diff --git a/refs.h b/refs.h
index 17bc1c1..ac0ff92 100644
--- a/refs.h
+++ b/refs.h
@@ -74,6 +74,14 @@ extern void add_packed_ref(const char *refname, const 
unsigned char *sha1);
 
 extern int ref_exists(const char *);
 
+/*
+ * If refname is a non-symbolic reference that refers to a tag object,
+ * and the tag can be (recursively) dereferenced to a non-tag object,
+ * store the SHA1 of the referred-to object to sha1 and return 0.  If
+ * any of these conditions are not met, return a non-zero value.
+ * Symbolic references are considered unpeelable, even if they
+ * ultimately resolve to a peelable tag.
+ */
 extern int peel_ref(const char *refname, unsigned char *sha1);
 
 /** Locks a refs/ ref returning the lock on success and NULL on failure. **/
-- 
1.8.2.1

--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 14/33] refs: extract a function peel_entry()

2013-04-22 Thread Michael Haggerty
Peel the entry, and as a side effect store the peeled value in the
entry.  Use this function from two places in peel_ref(); a third
caller will be added soon.

Please note that this change can lead to ref_entries for unpacked refs
being peeled.  This has no practical benefit but is harmless.

Signed-off-by: Michael Haggerty mhag...@alum.mit.edu
---
 refs.c | 63 +--
 1 file changed, 49 insertions(+), 14 deletions(-)

diff --git a/refs.c b/refs.c
index 2f73189..777a4b7 100644
--- a/refs.c
+++ b/refs.c
@@ -1285,7 +1285,17 @@ enum peel_status {
PEEL_INVALID = -1,
 
/* object cannot be peeled because it is not a tag: */
-   PEEL_NON_TAG = -2
+   PEEL_NON_TAG = -2,
+
+   /* ref_entry contains no peeled value because it is a symref: */
+   PEEL_IS_SYMREF = -3,
+
+   /*
+* ref_entry cannot be peeled because it is broken (i.e., the
+* symbolic reference cannot even be resolved to an object
+* name):
+*/
+   PEEL_BROKEN = -4
 };
 
 /*
@@ -1317,31 +1327,56 @@ static enum peel_status peel_object(const unsigned char 
*name, unsigned char *sh
return PEEL_PEELED;
 }
 
+/*
+ * Peel the entry (if possible) and return its new peel_status.
+ */
+static enum peel_status peel_entry(struct ref_entry *entry)
+{
+   enum peel_status status;
+
+   if (entry-flag  REF_KNOWS_PEELED)
+   return is_null_sha1(entry-u.value.peeled) ?
+   PEEL_NON_TAG : PEEL_PEELED;
+   if (entry-flag  REF_ISBROKEN)
+   return PEEL_BROKEN;
+   if (entry-flag  REF_ISSYMREF)
+   return PEEL_IS_SYMREF;
+
+   status = peel_object(entry-u.value.sha1, entry-u.value.peeled);
+   if (status == PEEL_PEELED || status == PEEL_NON_TAG)
+   entry-flag |= REF_KNOWS_PEELED;
+   return status;
+}
+
 int peel_ref(const char *refname, unsigned char *sha1)
 {
int flag;
unsigned char base[20];
 
if (current_ref  (current_ref-name == refname
-   || !strcmp(current_ref-name, refname))) {
-   if (current_ref-flag  REF_KNOWS_PEELED) {
-   if (is_null_sha1(current_ref-u.value.peeled))
-   return -1;
-   hashcpy(sha1, current_ref-u.value.peeled);
-   return 0;
-   }
-   return peel_object(current_ref-u.value.sha1, sha1);
+   || !strcmp(current_ref-name, refname))) {
+   if (peel_entry(current_ref))
+   return -1;
+   hashcpy(sha1, current_ref-u.value.peeled);
+   return 0;
}
 
if (read_ref_full(refname, base, 1, flag))
return -1;
 
-   if ((flag  REF_ISPACKED)) {
+   /*
+* If the reference is packed, read its ref_entry from the
+* cache in the hope that we already know its peeled value.
+* We only try this optimization on packed references because
+* (a) forcing the filling of the loose reference cache could
+* be expensive and (b) loose references anyway usually do not
+* have REF_KNOWS_PEELED.
+*/
+   if (flag  REF_ISPACKED) {
struct ref_entry *r = get_packed_ref(refname);
-
-   if (r  (r-flag  REF_KNOWS_PEELED)) {
-   if (is_null_sha1(r-u.value.peeled))
-   return -1;
+   if (r) {
+   if (peel_entry(r))
+   return -1;
hashcpy(sha1, r-u.value.peeled);
return 0;
}
-- 
1.8.2.1

--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 17/33] repack_without_ref(): silence errors for dangling packed refs

2013-04-22 Thread Michael Haggerty
Stop emitting an error message when deleting a packed reference if we
find another dangling packed reference that is overridden by a loose
reference.  See the previous commit for a longer explanation of the
issue.

We have to be careful to make sure that the invalid packed reference
really *is* overridden by a loose reference; otherwise what we have
found is repository corruption, which we *should* report.

Please note that this approach is vulnerable to a race condition
similar to the race conditions already known to affect packed
references [1]:

* Process 1 tries to peel packed reference X as part of deleting
  another packed reference.  It discovers that X does not refer to a
  valid object (because the object that it referred to has been
  garbage collected).

* Process 2 tries to delete reference X.  It starts by deleting the
  loose reference X.

* Process 1 checks whether there is a loose reference X.  There is not
  (it has just been deleted by process 2), so process 1 reports a
  spurious error X does not point to a valid object!

The worst case seems relatively harmless, and the fix is identical to
the fix that will be needed for the other race conditions (namely
holding a lock on the packed-refs file during *all* reference
deletions), so we leave the cleaning up of all of them as a future
project.

[1] http://thread.gmane.org/gmane.comp.version-control.git/211956

Signed-off-by: Michael Haggerty mhag...@alum.mit.edu
---
 refs.c   | 37 +++--
 t/t3210-pack-refs.sh |  2 +-
 2 files changed, 36 insertions(+), 3 deletions(-)

diff --git a/refs.c b/refs.c
index ed54ed4..2957f6d 100644
--- a/refs.c
+++ b/refs.c
@@ -1901,8 +1901,41 @@ static int repack_without_ref_fn(struct ref_entry 
*entry, void *cb_data)
 
if (!strcmp(data-refname, entry-name))
return 0;
-   if (!ref_resolves_to_object(entry))
-   return 0; /* Skip broken refs */
+   if (entry-flag  REF_ISBROKEN) {
+   /* This shouldn't happen to packed refs. */
+   error(%s is broken!, entry-name);
+   return 0;
+   }
+   if (!has_sha1_file(entry-u.value.sha1)) {
+   unsigned char sha1[20];
+   int flags;
+
+   if (read_ref_full(entry-name, sha1, 0, flags))
+   /* We should at least have found the packed ref. */
+   die(Internal error);
+   if ((flags  REF_ISSYMREF) || !(flags  REF_ISPACKED))
+   /*
+* This packed reference is overridden by a
+* loose reference, so it is OK that its value
+* is no longer valid; for example, it might
+* refer to an object that has been garbage
+* collected.  For this purpose we don't even
+* care whether the loose reference itself is
+* invalid, broken, symbolic, etc.  Silently
+* omit the packed reference from the output.
+*/
+   return 0;
+   /*
+* There is no overriding loose reference, so the fact
+* that this reference doesn't refer to a valid object
+* indicates some kind of repository corruption.
+* Report the problem, then omit the reference from
+* the output.
+*/
+   error(%s does not point to a valid object!, entry-name);
+   return 0;
+   }
+
len = snprintf(line, sizeof(line), %s %s\n,
   sha1_to_hex(entry-u.value.sha1), entry-name);
/* this should not happen but just being defensive */
diff --git a/t/t3210-pack-refs.sh b/t/t3210-pack-refs.sh
index c032d88..559f602 100755
--- a/t/t3210-pack-refs.sh
+++ b/t/t3210-pack-refs.sh
@@ -142,7 +142,7 @@ test_expect_success 'delete ref with dangling packed 
version' '
test_cmp /dev/null result
 '
 
-test_expect_failure 'delete ref while another dangling packed ref' '
+test_expect_success 'delete ref while another dangling packed ref' '
git branch lamb 
git commit --allow-empty -m future garbage 
git pack-refs --all 
-- 
1.8.2.1

--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 19/33] refs: change how packed refs are deleted

2013-04-22 Thread Michael Haggerty
Add a function remove_ref(), which removes a single entry from a
reference cache.

Use this function to reimplement repack_without_ref().  The old
version iterated over all refs, packing all of them except for the one
to be deleted, then discarded the entire packed reference cache.  The
new version deletes the doomed reference from the cache *before*
iterating.

This has two advantages:

* the code for writing packed-refs becomes simpler, because it doesn't
  have to exclude one of the references.

* it is no longer necessary to discard the packed refs cache after
  deleting a reference: symbolic refs cannot be packed, so packed
  references cannot depend on each other, so the rest of the packed
  refs cache remains valid after a reference is deleted.

Signed-off-by: Michael Haggerty mhag...@alum.mit.edu
---
 refs.c | 84 +-
 1 file changed, 68 insertions(+), 16 deletions(-)

diff --git a/refs.c b/refs.c
index 9fd49e8..51915a8 100644
--- a/refs.c
+++ b/refs.c
@@ -467,6 +467,57 @@ static struct ref_entry *find_ref(struct ref_dir *dir, 
const char *refname)
 }
 
 /*
+ * Remove the entry with the given name from dir, recursing into
+ * subdirectories as necessary.  If refname is the name of a directory
+ * (i.e., ends with '/'), then remove the directory and its contents.
+ * If the removal was successful, return the number of entries
+ * remaining in the directory entry that contained the deleted entry.
+ * If the name was not found, return -1.  Please note that this
+ * function only deletes the entry from the cache; it does not delete
+ * it from the filesystem or ensure that other cache entries (which
+ * might be symbolic references to the removed entry) are updated.
+ * Nor does it remove any containing dir entries that might be made
+ * empty by the removal.  dir must represent the top-level directory
+ * and must already be complete.
+ */
+static int remove_entry(struct ref_dir *dir, const char *refname)
+{
+   int refname_len = strlen(refname);
+   int entry_index;
+   struct ref_entry *entry;
+   int is_dir = refname[refname_len - 1] == '/';
+   if (is_dir) {
+   /*
+* refname represents a reference directory.  Remove
+* the trailing slash; otherwise we will get the
+* directory *representing* refname rather than the
+* one *containing* it.
+*/
+   char *dirname = xmemdupz(refname, refname_len - 1);
+   dir = find_containing_dir(dir, dirname, 0);
+   free(dirname);
+   } else {
+   dir = find_containing_dir(dir, refname, 0);
+   }
+   if (!dir)
+   return -1;
+   entry_index = search_ref_dir(dir, refname, refname_len);
+   if (entry_index == -1)
+   return -1;
+   entry = dir-entries[entry_index];
+
+   memmove(dir-entries[entry_index],
+   dir-entries[entry_index + 1],
+   (dir-nr - entry_index - 1) * sizeof(*dir-entries)
+   );
+   dir-nr--;
+   if (dir-sorted  entry_index)
+   dir-sorted--;
+   free_ref_entry(entry);
+   return dir-nr;
+}
+
+/*
  * Add a ref_entry to the ref_dir (unsorted), recursing into
  * subdirectories as necessary.  dir must represent the top-level
  * directory.  Return 0 on success.
@@ -1894,19 +1945,12 @@ struct ref_lock *lock_any_ref_for_update(const char 
*refname,
return lock_ref_sha1_basic(refname, old_sha1, flags, NULL);
 }
 
-struct repack_without_ref_sb {
-   const char *refname;
-   int fd;
-};
-
-static int repack_without_ref_fn(struct ref_entry *entry, void *cb_data)
+static int repack_ref_fn(struct ref_entry *entry, void *cb_data)
 {
-   struct repack_without_ref_sb *data = cb_data;
+   int *fd = cb_data;
char line[PATH_MAX + 100];
int len;
 
-   if (!strcmp(data-refname, entry-name))
-   return 0;
if (entry-flag  REF_ISBROKEN) {
/* This shouldn't happen to packed refs. */
error(%s is broken!, entry-name);
@@ -1947,7 +1991,7 @@ static int repack_without_ref_fn(struct ref_entry *entry, 
void *cb_data)
/* this should not happen but just being defensive */
if (len  sizeof(line))
die(too long a refname '%s', entry-name);
-   write_or_die(data-fd, line, len);
+   write_or_die(*fd, line, len);
return 0;
 }
 
@@ -1955,22 +1999,30 @@ static struct lock_file packlock;
 
 static int repack_without_ref(const char *refname)
 {
-   struct repack_without_ref_sb data;
+   int fd;
struct ref_cache *refs = get_ref_cache(NULL);
struct ref_dir *packed;
 
if (!get_packed_ref(refname))
return 0; /* refname does not exist in packed refs */
 
-   data.refname = refname;
-   data.fd = hold_lock_file_for_update(packlock, git_path(packed-refs), 
0);
-  

[PATCH v2 21/33] repack_without_ref(): write peeled refs in the rewritten file

2013-04-22 Thread Michael Haggerty
When a reference that existed in the packed-refs file is deleted, the
packed-refs file must be rewritten.  Previously, the file was
rewritten without any peeled refs, even if the file contained peeled
refs when it was read.  This was not a bug, because the packed-refs
file header didn't claim that the file contained peeled values.  But
it had a performance cost, because the repository would lose the
benefit of having precomputed peeled references until pack-refs was
run again.

Teach repack_without_ref() to write peeled refs to the packed-refs
file (regardless of whether they were present in the old version of
the file).

This means that if the old version of the packed-refs file was not
fully peeled, then repack_without_ref() will have to peel references.
To avoid the expense of reading lots of loose references, we take two
shortcuts relative to pack-refs:

* If the peeled value of a reference is already known (i.e., because
  it was read from the old version of the packed-refs file), then
  output that peeled value again without any checks.  This is the
  usual code path and should avoid any noticeable overhead.  (This is
  different than pack-refs, which always re-peels references.)

* We don't verify that the packed ref is still current.  It could be
  that a packed references is overridden by a loose reference, in
  which case the packed ref is no longer needed and might even refer
  to an object that has been garbage collected.  But we don't check;
  instead, we just try to peel all references.  If peeling is
  successful, the peeled value is written out (even though it might
  not be needed any more); if not, then the reference is silently
  omitted from the output.

The extra overhead of peeling references in repack_without_ref()
should only be incurred the first time the packed-refs file is written
by a version of Git that knows about the fully-peeled attribute.

Signed-off-by: Michael Haggerty mhag...@alum.mit.edu
---
 refs.c  | 23 +++
 t/t3211-peel-ref.sh |  2 +-
 2 files changed, 24 insertions(+), 1 deletion(-)

diff --git a/refs.c b/refs.c
index 51915a8..ff4c5f1 100644
--- a/refs.c
+++ b/refs.c
@@ -876,6 +876,13 @@ void invalidate_ref_cache(const char *submodule)
 #define PEELED_LINE_LENGTH 42
 
 /*
+ * The packed-refs header line that we write out.  Perhaps other
+ * traits will be added later.  The trailing space is required.
+ */
+static const char PACKED_REFS_HEADER[] =
+   # pack-refs with: peeled fully-peeled \n;
+
+/*
  * Parse one line from a packed-refs file.  Write the SHA1 to sha1.
  * Return a pointer to the refname within the line (null-terminated),
  * or NULL if there was a problem.
@@ -1390,6 +1397,12 @@ static enum peel_status peel_object(const unsigned char 
*name, unsigned char *sh
 
 /*
  * Peel the entry (if possible) and return its new peel_status.
+ *
+ * It is OK to call this function with a packed reference entry that
+ * might be stale and might even refer to an object that has since
+ * been garbage-collected.  In such a case, if the entry has
+ * REF_KNOWS_PEELED then leave the status unchanged and return
+ * PEEL_PEELED or PEEL_NON_TAG; otherwise, return PEEL_INVALID.
  */
 static enum peel_status peel_entry(struct ref_entry *entry)
 {
@@ -1992,6 +2005,15 @@ static int repack_ref_fn(struct ref_entry *entry, void 
*cb_data)
if (len  sizeof(line))
die(too long a refname '%s', entry-name);
write_or_die(*fd, line, len);
+   if (!peel_entry(entry)) {
+   /* This reference could be peeled; write the peeled value: */
+   if (snprintf(line, sizeof(line), ^%s\n,
+sha1_to_hex(entry-u.value.peeled)) !=
+   PEELED_LINE_LENGTH)
+   die(internal error);
+   write_or_die(*fd, line, PEELED_LINE_LENGTH);
+   }
+
return 0;
 }
 
@@ -2022,6 +2044,7 @@ static int repack_without_ref(const char *refname)
rollback_lock_file(packlock);
return 0;
}
+   write_or_die(fd, PACKED_REFS_HEADER, strlen(PACKED_REFS_HEADER));
do_for_each_entry_in_dir(packed, 0, repack_ref_fn, fd);
return commit_lock_file(packlock);
 }
diff --git a/t/t3211-peel-ref.sh b/t/t3211-peel-ref.sh
index cca1acb..3b7caca 100755
--- a/t/t3211-peel-ref.sh
+++ b/t/t3211-peel-ref.sh
@@ -61,7 +61,7 @@ test_expect_success 'refs are peeled outside of refs/tags 
(old packed)' '
test_cmp expect actual
 '
 
-test_expect_failure 'peeled refs survive deletion of packed ref' '
+test_expect_success 'peeled refs survive deletion of packed ref' '
git pack-refs --all 
cp .git/packed-refs fully-peeled 
git branch yadda 
-- 
1.8.2.1

--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 15/33] refs: change the internal reference-iteration API

2013-04-22 Thread Michael Haggerty
Establish an internal API for iterating over references, which gives
the callback functions direct access to the ref_entry structure
describing the reference.  (Do not change the iteration API that is
exposed outside of the module.)

Define a new internal callback signature

   int each_ref_entry_fn(struct ref_entry *entry, void *cb_data)

Change do_for_each_ref_in_dir() and do_for_each_ref_in_dirs() to
accept each_ref_entry_fn callbacks, and rename them to
do_for_each_entry_in_dir() and do_for_each_entry_in_dirs(),
respectively.  Adapt their callers accordingly.

Add a new function do_for_each_entry() analogous to do_for_each_ref()
but using the new callback style.

Change do_one_ref() into an each_ref_entry_fn that does some
bookkeeping and then calls a wrapped each_ref_fn.

Reimplement do_for_each_ref() in terms of do_for_each_entry(), using
do_one_ref() as an adapter.

Please note that the responsibility for setting current_ref remains in
do_one_ref(), which means that current_ref is *not* set when iterating
over references via the new internal API.  This is not a disadvantage,
because current_ref is not needed by callers of the internal API (they
receive a pointer to the current ref_entry anyway).  But more
importantly, this change prevents peel_ref() from returning invalid
results in the following scenario:

When iterating via the external API, the iteration always includes
both packed and loose references, and in particular never presents a
packed ref if there is a loose ref with the same name.  The internal
API, on the other hand, gives the option to iterate over only the
packed references.  During such an iteration, there is no check
whether the packed ref might be hidden by a loose ref of the same
name.  But until now the packed ref was recorded in current_ref during
the iteration.  So if peel_ref() were called with the reference name
corresponding to current ref, it would return the peeled version of
the packed ref even though there might be a loose ref that peels to a
different value.  This scenario doesn't currently occur in the code,
but fix it to prevent things from breaking in a very confusing way in
the future.

Signed-off-by: Michael Haggerty mhag...@alum.mit.edu
---
 refs.c | 144 +
 1 file changed, 83 insertions(+), 61 deletions(-)

diff --git a/refs.c b/refs.c
index 777a4b7..ed54ed4 100644
--- a/refs.c
+++ b/refs.c
@@ -556,22 +556,34 @@ static int ref_resolves_to_object(struct ref_entry *entry)
  */
 static struct ref_entry *current_ref;
 
+typedef int each_ref_entry_fn(struct ref_entry *entry, void *cb_data);
+
+struct ref_entry_cb {
+   const char *base;
+   int trim;
+   int flags;
+   each_ref_fn *fn;
+   void *cb_data;
+};
+
 /*
- * Handle one reference in a do_for_each_ref*()-style iteration.
+ * Handle one reference in a do_for_each_ref*()-style iteration,
+ * calling an each_ref_fn for each entry.
  */
-static int do_one_ref(const char *base, each_ref_fn fn, int trim,
- int flags, void *cb_data, struct ref_entry *entry)
+static int do_one_ref(struct ref_entry *entry, void *cb_data)
 {
+   struct ref_entry_cb *data = cb_data;
int retval;
-   if (prefixcmp(entry-name, base))
+   if (prefixcmp(entry-name, data-base))
return 0;
 
-   if (!(flags  DO_FOR_EACH_INCLUDE_BROKEN) 
+   if (!(data-flags  DO_FOR_EACH_INCLUDE_BROKEN) 
  !ref_resolves_to_object(entry))
return 0;
 
current_ref = entry;
-   retval = fn(entry-name + trim, entry-u.value.sha1, entry-flag, 
cb_data);
+   retval = data-fn(entry-name + data-trim, entry-u.value.sha1,
+ entry-flag, data-cb_data);
current_ref = NULL;
return retval;
 }
@@ -580,11 +592,11 @@ static int do_one_ref(const char *base, each_ref_fn fn, 
int trim,
  * Call fn for each reference in dir that has index in the range
  * offset = index  dir-nr.  Recurse into subdirectories that are in
  * that index range, sorting them before iterating.  This function
- * does not sort dir itself; it should be sorted beforehand.
+ * does not sort dir itself; it should be sorted beforehand.  fn is
+ * called for all references, including broken ones.
  */
-static int do_for_each_ref_in_dir(struct ref_dir *dir, int offset,
- const char *base,
- each_ref_fn fn, int trim, int flags, void 
*cb_data)
+static int do_for_each_entry_in_dir(struct ref_dir *dir, int offset,
+   each_ref_entry_fn fn, void *cb_data)
 {
int i;
assert(dir-sorted == dir-nr);
@@ -594,10 +606,9 @@ static int do_for_each_ref_in_dir(struct ref_dir *dir, int 
offset,
if (entry-flag  REF_DIR) {
struct ref_dir *subdir = get_ref_dir(entry);
sort_ref_dir(subdir);
-   retval = 

[PATCH v2 29/33] pack_one_ref(): use function peel_entry()

2013-04-22 Thread Michael Haggerty
Change pack_one_ref() to call peel_entry() rather than using its own
code for peeling references.  Aside from sharing code, this lets it
take advantage of the optimization introduced by 6c4a060d7d.

Please note that we *could* use any peeled values that happen to
already be stored in the ref_entries, which would avoid some object
lookups for references that were already packed.  But doing so would
also propagate any peeling errors across runs of git pack-refs and
give no way to recover from such errors.  And git pack-refs isn't
run often enough that the performance cost is a problem.  So instead,
add a new option to peel_entry() to force the entry to be re-peeled,
and call it with that option set.

Signed-off-by: Michael Haggerty mhag...@alum.mit.edu
---
 refs.c | 39 +++
 1 file changed, 23 insertions(+), 16 deletions(-)

diff --git a/refs.c b/refs.c
index f78e955..f2d83f3 100644
--- a/refs.c
+++ b/refs.c
@@ -1396,7 +1396,9 @@ static enum peel_status peel_object(const unsigned char 
*name, unsigned char *sh
 }
 
 /*
- * Peel the entry (if possible) and return its new peel_status.
+ * Peel the entry (if possible) and return its new peel_status.  If
+ * repeel is true, re-peel the entry even if there is an old peeled
+ * value that is already stored in it.
  *
  * It is OK to call this function with a packed reference entry that
  * might be stale and might even refer to an object that has since
@@ -1404,13 +1406,19 @@ static enum peel_status peel_object(const unsigned char 
*name, unsigned char *sh
  * REF_KNOWS_PEELED then leave the status unchanged and return
  * PEEL_PEELED or PEEL_NON_TAG; otherwise, return PEEL_INVALID.
  */
-static enum peel_status peel_entry(struct ref_entry *entry)
+static enum peel_status peel_entry(struct ref_entry *entry, int repeel)
 {
enum peel_status status;
 
-   if (entry-flag  REF_KNOWS_PEELED)
-   return is_null_sha1(entry-u.value.peeled) ?
-   PEEL_NON_TAG : PEEL_PEELED;
+   if (entry-flag  REF_KNOWS_PEELED) {
+   if (repeel) {
+   entry-flag = ~REF_KNOWS_PEELED;
+   hashclr(entry-u.value.peeled);
+   } else {
+   return is_null_sha1(entry-u.value.peeled) ?
+   PEEL_NON_TAG : PEEL_PEELED;
+   }
+   }
if (entry-flag  REF_ISBROKEN)
return PEEL_BROKEN;
if (entry-flag  REF_ISSYMREF)
@@ -1429,7 +1437,7 @@ int peel_ref(const char *refname, unsigned char *sha1)
 
if (current_ref  (current_ref-name == refname
|| !strcmp(current_ref-name, refname))) {
-   if (peel_entry(current_ref))
+   if (peel_entry(current_ref, 0))
return -1;
hashcpy(sha1, current_ref-u.value.peeled);
return 0;
@@ -1449,7 +1457,7 @@ int peel_ref(const char *refname, unsigned char *sha1)
if (flag  REF_ISPACKED) {
struct ref_entry *r = get_packed_ref(refname);
if (r) {
-   if (peel_entry(r))
+   if (peel_entry(r, 0))
return -1;
hashcpy(sha1, r-u.value.peeled);
return 0;
@@ -1998,7 +2006,7 @@ struct pack_refs_cb_data {
 static int pack_one_ref(struct ref_entry *entry, void *cb_data)
 {
struct pack_refs_cb_data *cb = cb_data;
-   struct object *o;
+   enum peel_status peel_status;
int is_tag_ref;
 
/* Do not pack symbolic or broken refs: */
@@ -2014,13 +2022,12 @@ static int pack_one_ref(struct ref_entry *entry, void 
*cb_data)
fprintf(cb-refs_file, %s %s\n, sha1_to_hex(entry-u.value.sha1),
entry-name);
 
-   o = parse_object_or_die(entry-u.value.sha1, entry-name);
-   if (o-type == OBJ_TAG) {
-   o = deref_tag(o, entry-name, 0);
-   if (o)
-   fprintf(cb-refs_file, ^%s\n,
-   sha1_to_hex(o-sha1));
-   }
+   peel_status = peel_entry(entry, 1);
+   if (peel_status == PEEL_PEELED)
+   fprintf(cb-refs_file, ^%s\n, 
sha1_to_hex(entry-u.value.peeled));
+   else if (peel_status != PEEL_NON_TAG)
+   die(internal error peeling reference %s (%s),
+   entry-name, sha1_to_hex(entry-u.value.sha1));
 
/* If the ref was already packed, there is no need to prune it. */
if ((cb-flags  PACK_REFS_PRUNE)  !(entry-flag  REF_ISPACKED)) {
@@ -2161,7 +2168,7 @@ static int repack_ref_fn(struct ref_entry *entry, void 
*cb_data)
return 0;
}
 
-   peel_status = peel_entry(entry);
+   peel_status = peel_entry(entry, 0);
write_packed_entry(*fd, entry-name, entry-u.value.sha1,
   peel_status == PEEL_PEELED ?
   entry-u.value.peeled : NULL);

[PATCH v2 30/33] pack_one_ref(): use write_packed_entry() to do the writing

2013-04-22 Thread Michael Haggerty
Change pack_refs() to work with a file descriptor instead of a FILE*
(making the file-locking code less awkward) and use
write_packed_entry() to do the writing.

Signed-off-by: Michael Haggerty mhag...@alum.mit.edu
---
 refs.c | 33 -
 1 file changed, 8 insertions(+), 25 deletions(-)

diff --git a/refs.c b/refs.c
index f2d83f3..df670cb 100644
--- a/refs.c
+++ b/refs.c
@@ -2000,7 +2000,7 @@ struct ref_to_prune {
 struct pack_refs_cb_data {
unsigned int flags;
struct ref_to_prune *ref_to_prune;
-   FILE *refs_file;
+   int fd;
 };
 
 static int pack_one_ref(struct ref_entry *entry, void *cb_data)
@@ -2019,15 +2019,13 @@ static int pack_one_ref(struct ref_entry *entry, void 
*cb_data)
!(entry-flag  REF_ISPACKED))
return 0;
 
-   fprintf(cb-refs_file, %s %s\n, sha1_to_hex(entry-u.value.sha1),
-   entry-name);
-
peel_status = peel_entry(entry, 1);
-   if (peel_status == PEEL_PEELED)
-   fprintf(cb-refs_file, ^%s\n, 
sha1_to_hex(entry-u.value.peeled));
-   else if (peel_status != PEEL_NON_TAG)
+   if (peel_status != PEEL_PEELED  peel_status != PEEL_NON_TAG)
die(internal error peeling reference %s (%s),
entry-name, sha1_to_hex(entry-u.value.sha1));
+   write_packed_entry(cb-fd, entry-name, entry-u.value.sha1,
+  peel_status == PEEL_PEELED ?
+  entry-u.value.peeled : NULL);
 
/* If the ref was already packed, there is no need to prune it. */
if ((cb-flags  PACK_REFS_PRUNE)  !(entry-flag  REF_ISPACKED)) {
@@ -2096,32 +2094,17 @@ static struct lock_file packlock;
 
 int pack_refs(unsigned int flags)
 {
-   int fd;
struct pack_refs_cb_data cbdata;
 
memset(cbdata, 0, sizeof(cbdata));
cbdata.flags = flags;
 
-   fd = hold_lock_file_for_update(packlock, git_path(packed-refs),
-  LOCK_DIE_ON_ERROR);
-   cbdata.refs_file = fdopen(fd, w);
-   if (!cbdata.refs_file)
-   die_errno(unable to create ref-pack file structure);
+   cbdata.fd = hold_lock_file_for_update(packlock, 
git_path(packed-refs),
+ LOCK_DIE_ON_ERROR);
 
-   /* perhaps other traits later as well */
-   fprintf(cbdata.refs_file, # pack-refs with: peeled fully-peeled \n);
+   write_or_die(cbdata.fd, PACKED_REFS_HEADER, strlen(PACKED_REFS_HEADER));
 
do_for_each_entry(NULL, , pack_one_ref, cbdata);
-   if (ferror(cbdata.refs_file))
-   die(failed to write ref-pack file);
-   if (fflush(cbdata.refs_file) || fsync(fd) || fclose(cbdata.refs_file))
-   die_errno(failed to write ref-pack file);
-   /*
-* Since the lock file was fdopen()'ed and then fclose()'ed above,
-* assign -1 to the lock file descriptor so that commit_lock_file()
-* won't try to close() it.
-*/
-   packlock.fd = -1;
if (commit_lock_file(packlock)  0)
die_errno(unable to overwrite old ref-pack file);
prune_refs(cbdata.ref_to_prune);
-- 
1.8.2.1

--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 06/33] do_for_each_ref_in_dirs(): remove dead code

2013-04-22 Thread Michael Haggerty
There is no way to drop out of the while loop.  This code has been
dead since 432ad41e.

Signed-off-by: Michael Haggerty mhag...@alum.mit.edu
---
 refs.c | 7 ---
 1 file changed, 7 deletions(-)

diff --git a/refs.c b/refs.c
index e1e9ddd..7260768 100644
--- a/refs.c
+++ b/refs.c
@@ -666,13 +666,6 @@ static int do_for_each_ref_in_dirs(struct ref_dir *dir1,
if (retval)
return retval;
}
-   if (i1  dir1-nr)
-   return do_for_each_ref_in_dir(dir1, i1,
- base, fn, trim, flags, cb_data);
-   if (i2  dir2-nr)
-   return do_for_each_ref_in_dir(dir2, i2,
- base, fn, trim, flags, cb_data);
-   return 0;
 }
 
 /*
-- 
1.8.2.1

--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] t4202 (log): add failing test for log with subtree

2013-04-22 Thread Ramkumar Ramachandra
Thomas Rast wrote:
 There is a market for a rename detection that works at the tree level.

Exactly.  And making it auto-follow with a low threshold would be a
great default.  We'll have to deal with D/F conflicts that Junio was
talking about in (2), every once in a while.  We'll have a lot more
incentive to build the D/F conflict resolution process a nice UI.

git-core will actually start working with trees the way it works with blobs.
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 05/33] refs: define constant PEELED_LINE_LENGTH

2013-04-22 Thread Michael Haggerty

Signed-off-by: Michael Haggerty mhag...@alum.mit.edu
---
 refs.c | 7 +--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/refs.c b/refs.c
index efad658..e1e9ddd 100644
--- a/refs.c
+++ b/refs.c
@@ -805,6 +805,9 @@ void invalidate_ref_cache(const char *submodule)
clear_loose_ref_cache(refs);
 }
 
+/* The length of a peeled reference line in packed-refs, including EOL: */
+#define PEELED_LINE_LENGTH 42
+
 /*
  * Parse one line from a packed-refs file.  Write the SHA1 to sha1.
  * Return a pointer to the refname within the line (null-terminated),
@@ -897,8 +900,8 @@ static void read_packed_refs(FILE *f, struct ref_dir *dir)
}
if (last 
refline[0] == '^' 
-   strlen(refline) == 42 
-   refline[41] == '\n' 
+   strlen(refline) == PEELED_LINE_LENGTH 
+   refline[PEELED_LINE_LENGTH - 1] == '\n' 
!get_sha1_hex(refline + 1, sha1)) {
hashcpy(last-u.value.peeled, sha1);
/*
-- 
1.8.2.1

--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 09/33] repack_without_ref(): use function get_packed_ref()

2013-04-22 Thread Michael Haggerty

Signed-off-by: Michael Haggerty mhag...@alum.mit.edu
---
 refs.c | 8 +---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/refs.c b/refs.c
index 09b68e4..1c8edb1 100644
--- a/refs.c
+++ b/refs.c
@@ -1820,9 +1820,11 @@ static int repack_without_ref(const char *refname)
 {
struct repack_without_ref_sb data;
struct ref_cache *refs = get_ref_cache(NULL);
-   struct ref_dir *packed = get_packed_refs(refs);
-   if (find_ref(packed, refname) == NULL)
-   return 0;
+   struct ref_dir *packed;
+
+   if (!get_packed_ref(refname))
+   return 0; /* refname does not exist in packed refs */
+
data.refname = refname;
data.fd = hold_lock_file_for_update(packlock, git_path(packed-refs), 
0);
if (data.fd  0) {
-- 
1.8.2.1

--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 10/33] refs: extract a function ref_resolves_to_object()

2013-04-22 Thread Michael Haggerty
It is a nice unit of work and soon will be needed from multiple
locations.

Signed-off-by: Michael Haggerty mhag...@alum.mit.edu
---
 refs.c | 28 
 1 file changed, 20 insertions(+), 8 deletions(-)

diff --git a/refs.c b/refs.c
index 1c8edb1..8b554d8 100644
--- a/refs.c
+++ b/refs.c
@@ -529,6 +529,22 @@ static void sort_ref_dir(struct ref_dir *dir)
 #define DO_FOR_EACH_INCLUDE_BROKEN 0x01
 
 /*
+ * Return true iff the reference described by entry can be resolved to
+ * an object in the database.  Emit a warning if the referred-to
+ * object does not exist.
+ */
+static int ref_resolves_to_object(struct ref_entry *entry)
+{
+   if (entry-flag  REF_ISBROKEN)
+   return 0;
+   if (!has_sha1_file(entry-u.value.sha1)) {
+   error(%s does not point to a valid object!, entry-name);
+   return 0;
+   }
+   return 1;
+}
+
+/*
  * current_ref is a performance hack: when iterating over references
  * using the for_each_ref*() functions, current_ref is set to the
  * current reference's entry before calling the callback function.  If
@@ -549,14 +565,10 @@ static int do_one_ref(const char *base, each_ref_fn fn, 
int trim,
if (prefixcmp(entry-name, base))
return 0;
 
-   if (!(flags  DO_FOR_EACH_INCLUDE_BROKEN)) {
-   if (entry-flag  REF_ISBROKEN)
-   return 0; /* ignore broken refs e.g. dangling symref */
-   if (!has_sha1_file(entry-u.value.sha1)) {
-   error(%s does not point to a valid object!, 
entry-name);
-   return 0;
-   }
-   }
+   if (!(flags  DO_FOR_EACH_INCLUDE_BROKEN) 
+ !ref_resolves_to_object(entry))
+   return 0;
+
current_ref = entry;
retval = fn(entry-name + trim, entry-u.value.sha1, entry-flag, 
cb_data);
current_ref = NULL;
-- 
1.8.2.1

--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 16/33] t3210: test for spurious error messages for dangling packed refs

2013-04-22 Thread Michael Haggerty
A packed reference can be overridden by a loose reference, in which
case the packed reference is obsolete and is never used.  The object
pointed to by such a reference can be garbage collected.  Since
d66da478f2, this could lead to the emission of a spurious error
message:

error: refs/heads/master does not point to a valid object!

The error is generated by repack_without_ref() if there is an obsolete
dangling packed reference in packed-refs when the packed-refs file has
to be rewritten due to the deletion of another packed reference.  Add
a failing test demonstrating this problem and some passing tests of
related scenarios.

Signed-off-by: Michael Haggerty mhag...@alum.mit.edu
---
 t/t3210-pack-refs.sh | 36 
 1 file changed, 36 insertions(+)

diff --git a/t/t3210-pack-refs.sh b/t/t3210-pack-refs.sh
index cd04361..c032d88 100755
--- a/t/t3210-pack-refs.sh
+++ b/t/t3210-pack-refs.sh
@@ -118,4 +118,40 @@ test_expect_success 'pack, prune and repack' '
test_cmp all-of-them again
 '
 
+test_expect_success 'explicit pack-refs with dangling packed reference' '
+   git commit --allow-empty -m soon to be garbage-collected 
+   git pack-refs --all 
+   git reset --hard HEAD^ 
+   sleep 1 
+   git reflog expire --expire=now --all 
+   git prune --expire=now 
+   git pack-refs --all 2result 
+   test_cmp /dev/null result
+'
+
+test_expect_success 'delete ref with dangling packed version' '
+   git checkout -b lamb 
+   git commit --allow-empty -m future garbage 
+   git pack-refs --all 
+   git reset --hard HEAD^ 
+   git checkout master 
+   sleep 1 
+   git reflog expire --expire=now --all 
+   git prune --expire=now 
+   git branch -d lamb 2result 
+   test_cmp /dev/null result
+'
+
+test_expect_failure 'delete ref while another dangling packed ref' '
+   git branch lamb 
+   git commit --allow-empty -m future garbage 
+   git pack-refs --all 
+   git reset --hard HEAD^ 
+   sleep 1 
+   git reflog expire --expire=now --all 
+   git prune --expire=now 
+   git branch -d lamb 2result 
+   test_cmp /dev/null result
+'
+
 test_done
-- 
1.8.2.1

--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 18/33] search_ref_dir(): return an index rather than a pointer

2013-04-22 Thread Michael Haggerty
Change search_ref_dir() to return the index of the sought entry (or -1
on error) rather than a pointer to the entry.  This will make it more
natural to use the function for removing an entry from the list.

Signed-off-by: Michael Haggerty mhag...@alum.mit.edu
---
 refs.c | 30 ++
 1 file changed, 18 insertions(+), 12 deletions(-)

diff --git a/refs.c b/refs.c
index 2957f6d..9fd49e8 100644
--- a/refs.c
+++ b/refs.c
@@ -366,18 +366,17 @@ static int ref_entry_cmp_sslice(const void *key_, const 
void *ent_)
 }
 
 /*
- * Return the entry with the given refname from the ref_dir
- * (non-recursively), sorting dir if necessary.  Return NULL if no
- * such entry is found.  dir must already be complete.
+ * Return the index of the entry with the given refname from the
+ * ref_dir (non-recursively), sorting dir if necessary.  Return -1 if
+ * no such entry is found.  dir must already be complete.
  */
-static struct ref_entry *search_ref_dir(struct ref_dir *dir,
-   const char *refname, size_t len)
+static int search_ref_dir(struct ref_dir *dir, const char *refname, size_t len)
 {
struct ref_entry **r;
struct string_slice key;
 
if (refname == NULL || !dir-nr)
-   return NULL;
+   return -1;
 
sort_ref_dir(dir);
key.len = len;
@@ -386,9 +385,9 @@ static struct ref_entry *search_ref_dir(struct ref_dir *dir,
ref_entry_cmp_sslice);
 
if (r == NULL)
-   return NULL;
+   return -1;
 
-   return *r;
+   return r - dir-entries;
 }
 
 /*
@@ -402,8 +401,9 @@ static struct ref_dir *search_for_subdir(struct ref_dir 
*dir,
 const char *subdirname, size_t len,
 int mkdir)
 {
-   struct ref_entry *entry = search_ref_dir(dir, subdirname, len);
-   if (!entry) {
+   int entry_index = search_ref_dir(dir, subdirname, len);
+   struct ref_entry *entry;
+   if (entry_index == -1) {
if (!mkdir)
return NULL;
/*
@@ -414,6 +414,8 @@ static struct ref_dir *search_for_subdir(struct ref_dir 
*dir,
 */
entry = create_dir_entry(dir-ref_cache, subdirname, len, 0);
add_entry_to_dir(dir, entry);
+   } else {
+   entry = dir-entries[entry_index];
}
return get_ref_dir(entry);
 }
@@ -452,12 +454,16 @@ static struct ref_dir *find_containing_dir(struct ref_dir 
*dir,
  */
 static struct ref_entry *find_ref(struct ref_dir *dir, const char *refname)
 {
+   int entry_index;
struct ref_entry *entry;
dir = find_containing_dir(dir, refname, 0);
if (!dir)
return NULL;
-   entry = search_ref_dir(dir, refname, strlen(refname));
-   return (entry  !(entry-flag  REF_DIR)) ? entry : NULL;
+   entry_index = search_ref_dir(dir, refname, strlen(refname));
+   if (entry_index == -1)
+   return NULL;
+   entry = dir-entries[entry_index];
+   return (entry-flag  REF_DIR) ? NULL : entry;
 }
 
 /*
-- 
1.8.2.1

--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 26/33] refs: use same lock_file object for both ref-packing functions

2013-04-22 Thread Michael Haggerty
Use a single struct lock_file for both pack_refs() and
repack_without_ref().

Signed-off-by: Michael Haggerty mhag...@alum.mit.edu
---
 refs.c | 10 --
 1 file changed, 4 insertions(+), 6 deletions(-)

diff --git a/refs.c b/refs.c
index b41dd5e..850df8e 100644
--- a/refs.c
+++ b/refs.c
@@ -2091,7 +2091,7 @@ static void prune_refs(struct ref_to_prune *r)
}
 }
 
-static struct lock_file packed;
+static struct lock_file packlock;
 
 int pack_refs(unsigned int flags)
 {
@@ -2101,7 +2101,7 @@ int pack_refs(unsigned int flags)
memset(cbdata, 0, sizeof(cbdata));
cbdata.flags = flags;
 
-   fd = hold_lock_file_for_update(packed, git_path(packed-refs),
+   fd = hold_lock_file_for_update(packlock, git_path(packed-refs),
   LOCK_DIE_ON_ERROR);
cbdata.refs_file = fdopen(fd, w);
if (!cbdata.refs_file)
@@ -2120,8 +2120,8 @@ int pack_refs(unsigned int flags)
 * assign -1 to the lock file descriptor so that commit_lock_file()
 * won't try to close() it.
 */
-   packed.fd = -1;
-   if (commit_lock_file(packed)  0)
+   packlock.fd = -1;
+   if (commit_lock_file(packlock)  0)
die_errno(unable to overwrite old ref-pack file);
prune_refs(cbdata.ref_to_prune);
return 0;
@@ -2175,8 +2175,6 @@ static int repack_ref_fn(struct ref_entry *entry, void 
*cb_data)
return 0;
 }
 
-static struct lock_file packlock;
-
 static int repack_without_ref(const char *refname)
 {
int fd;
-- 
1.8.2.1

--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 24/33] pack-refs: merge code from pack-refs.{c,h} into refs.{c,h}

2013-04-22 Thread Michael Haggerty
pack-refs.c doesn't contain much code, and the code it does contain is
closely related to reference handling.  Moreover, there is some
duplication between pack_refs() and repack_without_ref().  Therefore,
merge pack-refs.c into refs.c and pack-refs.h into refs.h.

The code duplication will be addressed in future commits.

Signed-off-by: Michael Haggerty mhag...@alum.mit.edu
---
 Makefile|   2 -
 builtin/clone.c |   1 -
 builtin/pack-refs.c |   2 +-
 pack-refs.c | 148 
 pack-refs.h |  18 ---
 refs.c  | 144 ++
 refs.h  |  14 +
 7 files changed, 159 insertions(+), 170 deletions(-)
 delete mode 100644 pack-refs.c
 delete mode 100644 pack-refs.h

diff --git a/Makefile b/Makefile
index 0f931a2..de38539 100644
--- a/Makefile
+++ b/Makefile
@@ -684,7 +684,6 @@ LIB_H += notes-cache.h
 LIB_H += notes-merge.h
 LIB_H += notes.h
 LIB_H += object.h
-LIB_H += pack-refs.h
 LIB_H += pack-revindex.h
 LIB_H += pack.h
 LIB_H += parse-options.h
@@ -817,7 +816,6 @@ LIB_OBJS += notes-cache.o
 LIB_OBJS += notes-merge.o
 LIB_OBJS += object.o
 LIB_OBJS += pack-check.o
-LIB_OBJS += pack-refs.o
 LIB_OBJS += pack-revindex.o
 LIB_OBJS += pack-write.o
 LIB_OBJS += pager.o
diff --git a/builtin/clone.c b/builtin/clone.c
index f9c380e..883cf2a 100644
--- a/builtin/clone.c
+++ b/builtin/clone.c
@@ -18,7 +18,6 @@
 #include transport.h
 #include strbuf.h
 #include dir.h
-#include pack-refs.h
 #include sigchain.h
 #include branch.h
 #include remote.h
diff --git a/builtin/pack-refs.c b/builtin/pack-refs.c
index b5a0f88..b20b1ec 100644
--- a/builtin/pack-refs.c
+++ b/builtin/pack-refs.c
@@ -1,6 +1,6 @@
 #include builtin.h
 #include parse-options.h
-#include pack-refs.h
+#include refs.h
 
 static char const * const pack_refs_usage[] = {
N_(git pack-refs [options]),
diff --git a/pack-refs.c b/pack-refs.c
deleted file mode 100644
index d840055..000
--- a/pack-refs.c
+++ /dev/null
@@ -1,148 +0,0 @@
-#include cache.h
-#include refs.h
-#include tag.h
-#include pack-refs.h
-
-struct ref_to_prune {
-   struct ref_to_prune *next;
-   unsigned char sha1[20];
-   char name[FLEX_ARRAY];
-};
-
-struct pack_refs_cb_data {
-   unsigned int flags;
-   struct ref_to_prune *ref_to_prune;
-   FILE *refs_file;
-};
-
-static int do_not_prune(int flags)
-{
-   /* If it is already packed or if it is a symref,
-* do not prune it.
-*/
-   return (flags  (REF_ISSYMREF|REF_ISPACKED));
-}
-
-static int pack_one_ref(const char *path, const unsigned char *sha1,
- int flags, void *cb_data)
-{
-   struct pack_refs_cb_data *cb = cb_data;
-   struct object *o;
-   int is_tag_ref;
-
-   /* Do not pack the symbolic refs */
-   if ((flags  REF_ISSYMREF))
-   return 0;
-   is_tag_ref = !prefixcmp(path, refs/tags/);
-
-   /* ALWAYS pack refs that were already packed or are tags */
-   if (!(cb-flags  PACK_REFS_ALL)  !is_tag_ref  !(flags  
REF_ISPACKED))
-   return 0;
-
-   fprintf(cb-refs_file, %s %s\n, sha1_to_hex(sha1), path);
-
-   o = parse_object_or_die(sha1, path);
-   if (o-type == OBJ_TAG) {
-   o = deref_tag(o, path, 0);
-   if (o)
-   fprintf(cb-refs_file, ^%s\n,
-   sha1_to_hex(o-sha1));
-   }
-
-   if ((cb-flags  PACK_REFS_PRUNE)  !do_not_prune(flags)) {
-   int namelen = strlen(path) + 1;
-   struct ref_to_prune *n = xcalloc(1, sizeof(*n) + namelen);
-   hashcpy(n-sha1, sha1);
-   strcpy(n-name, path);
-   n-next = cb-ref_to_prune;
-   cb-ref_to_prune = n;
-   }
-   return 0;
-}
-
-/*
- * Remove empty parents, but spare refs/ and immediate subdirs.
- * Note: munges *name.
- */
-static void try_remove_empty_parents(char *name)
-{
-   char *p, *q;
-   int i;
-   p = name;
-   for (i = 0; i  2; i++) { /* refs/{heads,tags,...}/ */
-   while (*p  *p != '/')
-   p++;
-   /* tolerate duplicate slashes; see check_refname_format() */
-   while (*p == '/')
-   p++;
-   }
-   for (q = p; *q; q++)
-   ;
-   while (1) {
-   while (q  p  *q != '/')
-   q--;
-   while (q  p  *(q-1) == '/')
-   q--;
-   if (q == p)
-   break;
-   *q = '\0';
-   if (rmdir(git_path(%s, name)))
-   break;
-   }
-}
-
-/* make sure nobody touched the ref, and unlink */
-static void prune_ref(struct ref_to_prune *r)
-{
-   struct ref_lock *lock = lock_ref_sha1(r-name + 5, r-sha1);
-
-   if (lock) {
-   unlink_or_warn(git_path(%s, r-name));
-   

[PATCH v2 31/33] pack_one_ref(): do some cheap tests before a more expensive one

2013-04-22 Thread Michael Haggerty

Signed-off-by: Michael Haggerty mhag...@alum.mit.edu
---
 refs.c | 11 +--
 1 file changed, 5 insertions(+), 6 deletions(-)

diff --git a/refs.c b/refs.c
index df670cb..b1cda1b 100644
--- a/refs.c
+++ b/refs.c
@@ -2007,18 +2007,17 @@ static int pack_one_ref(struct ref_entry *entry, void 
*cb_data)
 {
struct pack_refs_cb_data *cb = cb_data;
enum peel_status peel_status;
-   int is_tag_ref;
-
-   /* Do not pack symbolic or broken refs: */
-   if ((entry-flag  REF_ISSYMREF) || !ref_resolves_to_object(entry))
-   return 0;
-   is_tag_ref = !prefixcmp(entry-name, refs/tags/);
+   int is_tag_ref = !prefixcmp(entry-name, refs/tags/);
 
/* ALWAYS pack refs that were already packed or are tags */
if (!(cb-flags  PACK_REFS_ALL)  !is_tag_ref 
!(entry-flag  REF_ISPACKED))
return 0;
 
+   /* Do not pack symbolic or broken refs: */
+   if ((entry-flag  REF_ISSYMREF) || !ref_resolves_to_object(entry))
+   return 0;
+
peel_status = peel_entry(entry, 1);
if (peel_status != PEEL_PEELED  peel_status != PEEL_NON_TAG)
die(internal error peeling reference %s (%s),
-- 
1.8.2.1

--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 28/33] refs: inline function do_not_prune()

2013-04-22 Thread Michael Haggerty
Function do_not_prune() was redundantly checking REF_ISSYMREF, which
was already tested at the top of pack_one_ref(), so remove that check.
And the rest was trivial, so inline the function.

Signed-off-by: Michael Haggerty mhag...@alum.mit.edu
---
 refs.c | 11 ++-
 1 file changed, 2 insertions(+), 9 deletions(-)

diff --git a/refs.c b/refs.c
index 88875d1..f78e955 100644
--- a/refs.c
+++ b/refs.c
@@ -1995,14 +1995,6 @@ struct pack_refs_cb_data {
FILE *refs_file;
 };
 
-static int do_not_prune(int flags)
-{
-   /* If it is already packed or if it is a symref,
-* do not prune it.
-*/
-   return (flags  (REF_ISSYMREF|REF_ISPACKED));
-}
-
 static int pack_one_ref(struct ref_entry *entry, void *cb_data)
 {
struct pack_refs_cb_data *cb = cb_data;
@@ -2030,7 +2022,8 @@ static int pack_one_ref(struct ref_entry *entry, void 
*cb_data)
sha1_to_hex(o-sha1));
}
 
-   if ((cb-flags  PACK_REFS_PRUNE)  !do_not_prune(entry-flag)) {
+   /* If the ref was already packed, there is no need to prune it. */
+   if ((cb-flags  PACK_REFS_PRUNE)  !(entry-flag  REF_ISPACKED)) {
int namelen = strlen(entry-name) + 1;
struct ref_to_prune *n = xcalloc(1, sizeof(*n) + namelen);
hashcpy(n-sha1, entry-u.value.sha1);
-- 
1.8.2.1

--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 23/33] pack-refs: rename handle_one_ref() to pack_one_ref()

2013-04-22 Thread Michael Haggerty
This code is about to be moved, so name the function more
distinctively.

Signed-off-by: Michael Haggerty mhag...@alum.mit.edu
---
 pack-refs.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/pack-refs.c b/pack-refs.c
index 4461f71..d840055 100644
--- a/pack-refs.c
+++ b/pack-refs.c
@@ -23,7 +23,7 @@ static int do_not_prune(int flags)
return (flags  (REF_ISSYMREF|REF_ISPACKED));
 }
 
-static int handle_one_ref(const char *path, const unsigned char *sha1,
+static int pack_one_ref(const char *path, const unsigned char *sha1,
  int flags, void *cb_data)
 {
struct pack_refs_cb_data *cb = cb_data;
@@ -130,7 +130,7 @@ int pack_refs(unsigned int flags)
/* perhaps other traits later as well */
fprintf(cbdata.refs_file, # pack-refs with: peeled fully-peeled \n);
 
-   for_each_ref(handle_one_ref, cbdata);
+   for_each_ref(pack_one_ref, cbdata);
if (ferror(cbdata.refs_file))
die(failed to write ref-pack file);
if (fflush(cbdata.refs_file) || fsync(fd) || fclose(cbdata.refs_file))
-- 
1.8.2.1

--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 27/33] pack_refs(): change to use do_for_each_entry()

2013-04-22 Thread Michael Haggerty
pack_refs() was not using any of the extra features of for_each_ref(),
so change it to use do_for_each_entry().  This also gives it access to
the ref_entry and in particular its peeled field, which will be taken
advantage of in the next commit.

Signed-off-by: Michael Haggerty mhag...@alum.mit.edu
---
 refs.c | 29 +++--
 1 file changed, 15 insertions(+), 14 deletions(-)

diff --git a/refs.c b/refs.c
index 850df8e..88875d1 100644
--- a/refs.c
+++ b/refs.c
@@ -2003,37 +2003,38 @@ static int do_not_prune(int flags)
return (flags  (REF_ISSYMREF|REF_ISPACKED));
 }
 
-static int pack_one_ref(const char *refname, const unsigned char *sha1,
- int flags, void *cb_data)
+static int pack_one_ref(struct ref_entry *entry, void *cb_data)
 {
struct pack_refs_cb_data *cb = cb_data;
struct object *o;
int is_tag_ref;
 
-   /* Do not pack the symbolic refs */
-   if ((flags  REF_ISSYMREF))
+   /* Do not pack symbolic or broken refs: */
+   if ((entry-flag  REF_ISSYMREF) || !ref_resolves_to_object(entry))
return 0;
-   is_tag_ref = !prefixcmp(refname, refs/tags/);
+   is_tag_ref = !prefixcmp(entry-name, refs/tags/);
 
/* ALWAYS pack refs that were already packed or are tags */
-   if (!(cb-flags  PACK_REFS_ALL)  !is_tag_ref  !(flags  
REF_ISPACKED))
+   if (!(cb-flags  PACK_REFS_ALL)  !is_tag_ref 
+   !(entry-flag  REF_ISPACKED))
return 0;
 
-   fprintf(cb-refs_file, %s %s\n, sha1_to_hex(sha1), refname);
+   fprintf(cb-refs_file, %s %s\n, sha1_to_hex(entry-u.value.sha1),
+   entry-name);
 
-   o = parse_object_or_die(sha1, refname);
+   o = parse_object_or_die(entry-u.value.sha1, entry-name);
if (o-type == OBJ_TAG) {
-   o = deref_tag(o, refname, 0);
+   o = deref_tag(o, entry-name, 0);
if (o)
fprintf(cb-refs_file, ^%s\n,
sha1_to_hex(o-sha1));
}
 
-   if ((cb-flags  PACK_REFS_PRUNE)  !do_not_prune(flags)) {
-   int namelen = strlen(refname) + 1;
+   if ((cb-flags  PACK_REFS_PRUNE)  !do_not_prune(entry-flag)) {
+   int namelen = strlen(entry-name) + 1;
struct ref_to_prune *n = xcalloc(1, sizeof(*n) + namelen);
-   hashcpy(n-sha1, sha1);
-   strcpy(n-name, refname);
+   hashcpy(n-sha1, entry-u.value.sha1);
+   strcpy(n-name, entry-name);
n-next = cb-ref_to_prune;
cb-ref_to_prune = n;
}
@@ -2110,7 +2111,7 @@ int pack_refs(unsigned int flags)
/* perhaps other traits later as well */
fprintf(cbdata.refs_file, # pack-refs with: peeled fully-peeled \n);
 
-   for_each_ref(pack_one_ref, cbdata);
+   do_for_each_entry(NULL, , pack_one_ref, cbdata);
if (ferror(cbdata.refs_file))
die(failed to write ref-pack file);
if (fflush(cbdata.refs_file) || fsync(fd) || fclose(cbdata.refs_file))
-- 
1.8.2.1

--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 20/33] t3211: demonstrate loss of peeled refs if a packed ref is deleted

2013-04-22 Thread Michael Haggerty
Add a test that demonstrates that the peeled values recorded in
packed-refs are lost if a packed ref is deleted.  (The code in
repack_without_ref() doesn't even attempt to write peeled refs.)  This
will be fixed in a moment.

Signed-off-by: Michael Haggerty mhag...@alum.mit.edu
---
 t/t3211-peel-ref.sh | 9 +
 1 file changed, 9 insertions(+)

diff --git a/t/t3211-peel-ref.sh b/t/t3211-peel-ref.sh
index d4d7792..cca1acb 100755
--- a/t/t3211-peel-ref.sh
+++ b/t/t3211-peel-ref.sh
@@ -61,4 +61,13 @@ test_expect_success 'refs are peeled outside of refs/tags 
(old packed)' '
test_cmp expect actual
 '
 
+test_expect_failure 'peeled refs survive deletion of packed ref' '
+   git pack-refs --all 
+   cp .git/packed-refs fully-peeled 
+   git branch yadda 
+   git pack-refs --all 
+   git branch -d yadda 
+   test_cmp fully-peeled .git/packed-refs
+'
+
 test_done
-- 
1.8.2.1

--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 25/33] pack_one_ref(): rename path parameter to refname

2013-04-22 Thread Michael Haggerty
Make this function conform to the naming convention established in
65385ef7d4 for the rest of the refs.c file.

Signed-off-by: Michael Haggerty mhag...@alum.mit.edu
---
 refs.c | 14 +++---
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/refs.c b/refs.c
index 268c1a0..b41dd5e 100644
--- a/refs.c
+++ b/refs.c
@@ -2003,7 +2003,7 @@ static int do_not_prune(int flags)
return (flags  (REF_ISSYMREF|REF_ISPACKED));
 }
 
-static int pack_one_ref(const char *path, const unsigned char *sha1,
+static int pack_one_ref(const char *refname, const unsigned char *sha1,
  int flags, void *cb_data)
 {
struct pack_refs_cb_data *cb = cb_data;
@@ -2013,27 +2013,27 @@ static int pack_one_ref(const char *path, const 
unsigned char *sha1,
/* Do not pack the symbolic refs */
if ((flags  REF_ISSYMREF))
return 0;
-   is_tag_ref = !prefixcmp(path, refs/tags/);
+   is_tag_ref = !prefixcmp(refname, refs/tags/);
 
/* ALWAYS pack refs that were already packed or are tags */
if (!(cb-flags  PACK_REFS_ALL)  !is_tag_ref  !(flags  
REF_ISPACKED))
return 0;
 
-   fprintf(cb-refs_file, %s %s\n, sha1_to_hex(sha1), path);
+   fprintf(cb-refs_file, %s %s\n, sha1_to_hex(sha1), refname);
 
-   o = parse_object_or_die(sha1, path);
+   o = parse_object_or_die(sha1, refname);
if (o-type == OBJ_TAG) {
-   o = deref_tag(o, path, 0);
+   o = deref_tag(o, refname, 0);
if (o)
fprintf(cb-refs_file, ^%s\n,
sha1_to_hex(o-sha1));
}
 
if ((cb-flags  PACK_REFS_PRUNE)  !do_not_prune(flags)) {
-   int namelen = strlen(path) + 1;
+   int namelen = strlen(refname) + 1;
struct ref_to_prune *n = xcalloc(1, sizeof(*n) + namelen);
hashcpy(n-sha1, sha1);
-   strcpy(n-name, path);
+   strcpy(n-name, refname);
n-next = cb-ref_to_prune;
cb-ref_to_prune = n;
}
-- 
1.8.2.1

--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v2 33/33] refs: handle the main ref_cache specially

2013-04-22 Thread Michael Haggerty
Hold the ref_cache instance for the main repository in a dedicated,
statically-allocated instance to avoid the need for a function call
and a linked-list traversal when it is needed.

Suggested by: Heiko Voigt hvo...@hvoigt.net

Signed-off-by: Michael Haggerty mhag...@alum.mit.edu
---
 refs.c | 60 +++-
 1 file changed, 31 insertions(+), 29 deletions(-)

diff --git a/refs.c b/refs.c
index f246b77..d17931a 100644
--- a/refs.c
+++ b/refs.c
@@ -810,9 +810,13 @@ static struct ref_cache {
struct ref_cache *next;
struct ref_entry *loose;
struct ref_entry *packed;
-   /* The submodule name, or  for the main repo. */
-   char name[FLEX_ARRAY];
-} *ref_cache;
+   /*
+* The submodule name, or  for the main repo.  We allocate
+* length 1 rather than FLEX_ARRAY so that the main ref_cache
+* is initialized correctly.
+*/
+   char name[1];
+} ref_cache, *submodule_ref_caches;
 
 static void clear_packed_ref_cache(struct ref_cache *refs)
 {
@@ -850,18 +854,18 @@ static struct ref_cache *create_ref_cache(const char 
*submodule)
  */
 static struct ref_cache *get_ref_cache(const char *submodule)
 {
-   struct ref_cache *refs = ref_cache;
-   if (!submodule)
-   submodule = ;
-   while (refs) {
+   struct ref_cache *refs;
+
+   if (!submodule || !*submodule)
+   return ref_cache;
+
+   for (refs = submodule_ref_caches; refs; refs = refs-next)
if (!strcmp(submodule, refs-name))
return refs;
-   refs = refs-next;
-   }
 
refs = create_ref_cache(submodule);
-   refs-next = ref_cache;
-   ref_cache = refs;
+   refs-next = submodule_ref_caches;
+   submodule_ref_caches = refs;
return refs;
 }
 
@@ -1010,8 +1014,8 @@ static struct ref_dir *get_packed_refs(struct ref_cache 
*refs)
 
 void add_packed_ref(const char *refname, const unsigned char *sha1)
 {
-   add_ref(get_packed_refs(get_ref_cache(NULL)),
-   create_ref_entry(refname, sha1, REF_ISPACKED, 1));
+   add_ref(get_packed_refs(ref_cache),
+   create_ref_entry(refname, sha1, REF_ISPACKED, 1));
 }
 
 /*
@@ -1186,7 +1190,7 @@ int resolve_gitlink_ref(const char *path, const char 
*refname, unsigned char *sh
  */
 static struct ref_entry *get_packed_ref(const char *refname)
 {
-   return find_ref(get_packed_refs(get_ref_cache(NULL)), refname);
+   return find_ref(get_packed_refs(ref_cache), refname);
 }
 
 const char *resolve_ref_unsafe(const char *refname, unsigned char *sha1, int 
reading, int *flag)
@@ -1591,7 +1595,7 @@ int head_ref_submodule(const char *submodule, each_ref_fn 
fn, void *cb_data)
 
 int for_each_ref(each_ref_fn fn, void *cb_data)
 {
-   return do_for_each_ref(get_ref_cache(NULL), , fn, 0, 0, cb_data);
+   return do_for_each_ref(ref_cache, , fn, 0, 0, cb_data);
 }
 
 int for_each_ref_submodule(const char *submodule, each_ref_fn fn, void 
*cb_data)
@@ -1601,7 +1605,7 @@ int for_each_ref_submodule(const char *submodule, 
each_ref_fn fn, void *cb_data)
 
 int for_each_ref_in(const char *prefix, each_ref_fn fn, void *cb_data)
 {
-   return do_for_each_ref(get_ref_cache(NULL), prefix, fn, strlen(prefix), 
0, cb_data);
+   return do_for_each_ref(ref_cache, prefix, fn, strlen(prefix), 0, 
cb_data);
 }
 
 int for_each_ref_in_submodule(const char *submodule, const char *prefix,
@@ -1642,7 +1646,7 @@ int for_each_remote_ref_submodule(const char *submodule, 
each_ref_fn fn, void *c
 
 int for_each_replace_ref(each_ref_fn fn, void *cb_data)
 {
-   return do_for_each_ref(get_ref_cache(NULL), refs/replace/, fn, 13, 0, 
cb_data);
+   return do_for_each_ref(ref_cache, refs/replace/, fn, 13, 0, cb_data);
 }
 
 int head_ref_namespaced(each_ref_fn fn, void *cb_data)
@@ -1665,7 +1669,7 @@ int for_each_namespaced_ref(each_ref_fn fn, void *cb_data)
struct strbuf buf = STRBUF_INIT;
int ret;
strbuf_addf(buf, %srefs/, get_git_namespace());
-   ret = do_for_each_ref(get_ref_cache(NULL), buf.buf, fn, 0, 0, cb_data);
+   ret = do_for_each_ref(ref_cache, buf.buf, fn, 0, 0, cb_data);
strbuf_release(buf);
return ret;
 }
@@ -1707,7 +1711,7 @@ int for_each_glob_ref(each_ref_fn fn, const char 
*pattern, void *cb_data)
 
 int for_each_rawref(each_ref_fn fn, void *cb_data)
 {
-   return do_for_each_ref(get_ref_cache(NULL), , fn, 0,
+   return do_for_each_ref(ref_cache, , fn, 0,
   DO_FOR_EACH_INCLUDE_BROKEN, cb_data);
 }
 
@@ -1913,7 +1917,7 @@ static struct ref_lock *lock_ref_sha1_basic(const char 
*refname,
 * name is a proper prefix of our refname.
 */
if (missing 
-!is_refname_available(refname, NULL, 
get_packed_refs(get_ref_cache(NULL {
+!is_refname_available(refname, NULL, get_packed_refs(ref_cache))) 
{

[PATCH v2 32/33] refs: change do_for_each_*() functions to take ref_cache arguments

2013-04-22 Thread Michael Haggerty
Change the callers convert submodule names into ref_cache pointers.

Signed-off-by: Michael Haggerty mhag...@alum.mit.edu
---
 refs.c | 29 ++---
 1 file changed, 14 insertions(+), 15 deletions(-)

diff --git a/refs.c b/refs.c
index b1cda1b..f246b77 100644
--- a/refs.c
+++ b/refs.c
@@ -1503,16 +1503,15 @@ void warn_dangling_symref(FILE *fp, const char 
*msg_fmt, const char *refname)
 }
 
 /*
- * Call fn for each reference in the specified submodule, omitting
+ * Call fn for each reference in the specified ref_cache, omitting
  * references not in the containing_dir of base.  fn is called for all
  * references, including broken ones.  If fn ever returns a non-zero
  * value, stop the iteration and return that value; otherwise, return
  * 0.
  */
-static int do_for_each_entry(const char *submodule, const char *base,
+static int do_for_each_entry(struct ref_cache *refs, const char *base,
 each_ref_entry_fn fn, void *cb_data)
 {
-   struct ref_cache *refs = get_ref_cache(submodule);
struct ref_dir *packed_dir = get_packed_refs(refs);
struct ref_dir *loose_dir = get_loose_refs(refs);
int retval = 0;
@@ -1541,7 +1540,7 @@ static int do_for_each_entry(const char *submodule, const 
char *base,
 }
 
 /*
- * Call fn for each reference in the specified submodule for which the
+ * Call fn for each reference in the specified ref_cache for which the
  * refname begins with base.  If trim is non-zero, then trim that many
  * characters off the beginning of each refname before passing the
  * refname to fn.  flags can be DO_FOR_EACH_INCLUDE_BROKEN to include
@@ -1549,8 +1548,8 @@ static int do_for_each_entry(const char *submodule, const 
char *base,
  * value, stop the iteration and return that value; otherwise, return
  * 0.
  */
-static int do_for_each_ref(const char *submodule, const char *base, 
each_ref_fn fn,
-  int trim, int flags, void *cb_data)
+static int do_for_each_ref(struct ref_cache *refs, const char *base,
+  each_ref_fn fn, int trim, int flags, void *cb_data)
 {
struct ref_entry_cb data;
data.base = base;
@@ -1559,7 +1558,7 @@ static int do_for_each_ref(const char *submodule, const 
char *base, each_ref_fn
data.fn = fn;
data.cb_data = cb_data;
 
-   return do_for_each_entry(submodule, base, do_one_ref, data);
+   return do_for_each_entry(refs, base, do_one_ref, data);
 }
 
 static int do_head_ref(const char *submodule, each_ref_fn fn, void *cb_data)
@@ -1592,23 +1591,23 @@ int head_ref_submodule(const char *submodule, 
each_ref_fn fn, void *cb_data)
 
 int for_each_ref(each_ref_fn fn, void *cb_data)
 {
-   return do_for_each_ref(NULL, , fn, 0, 0, cb_data);
+   return do_for_each_ref(get_ref_cache(NULL), , fn, 0, 0, cb_data);
 }
 
 int for_each_ref_submodule(const char *submodule, each_ref_fn fn, void 
*cb_data)
 {
-   return do_for_each_ref(submodule, , fn, 0, 0, cb_data);
+   return do_for_each_ref(get_ref_cache(submodule), , fn, 0, 0, cb_data);
 }
 
 int for_each_ref_in(const char *prefix, each_ref_fn fn, void *cb_data)
 {
-   return do_for_each_ref(NULL, prefix, fn, strlen(prefix), 0, cb_data);
+   return do_for_each_ref(get_ref_cache(NULL), prefix, fn, strlen(prefix), 
0, cb_data);
 }
 
 int for_each_ref_in_submodule(const char *submodule, const char *prefix,
each_ref_fn fn, void *cb_data)
 {
-   return do_for_each_ref(submodule, prefix, fn, strlen(prefix), 0, 
cb_data);
+   return do_for_each_ref(get_ref_cache(submodule), prefix, fn, 
strlen(prefix), 0, cb_data);
 }
 
 int for_each_tag_ref(each_ref_fn fn, void *cb_data)
@@ -1643,7 +1642,7 @@ int for_each_remote_ref_submodule(const char *submodule, 
each_ref_fn fn, void *c
 
 int for_each_replace_ref(each_ref_fn fn, void *cb_data)
 {
-   return do_for_each_ref(NULL, refs/replace/, fn, 13, 0, cb_data);
+   return do_for_each_ref(get_ref_cache(NULL), refs/replace/, fn, 13, 0, 
cb_data);
 }
 
 int head_ref_namespaced(each_ref_fn fn, void *cb_data)
@@ -1666,7 +1665,7 @@ int for_each_namespaced_ref(each_ref_fn fn, void *cb_data)
struct strbuf buf = STRBUF_INIT;
int ret;
strbuf_addf(buf, %srefs/, get_git_namespace());
-   ret = do_for_each_ref(NULL, buf.buf, fn, 0, 0, cb_data);
+   ret = do_for_each_ref(get_ref_cache(NULL), buf.buf, fn, 0, 0, cb_data);
strbuf_release(buf);
return ret;
 }
@@ -1708,7 +1707,7 @@ int for_each_glob_ref(each_ref_fn fn, const char 
*pattern, void *cb_data)
 
 int for_each_rawref(each_ref_fn fn, void *cb_data)
 {
-   return do_for_each_ref(NULL, , fn, 0,
+   return do_for_each_ref(get_ref_cache(NULL), , fn, 0,
   DO_FOR_EACH_INCLUDE_BROKEN, cb_data);
 }
 
@@ -2103,7 +2102,7 @@ int pack_refs(unsigned int flags)
 
write_or_die(cbdata.fd, PACKED_REFS_HEADER, strlen(PACKED_REFS_HEADER));
 
-   do_for_each_entry(NULL, , 

What's cooking in git.git (Apr 2013, #07; Mon, 22)

2013-04-22 Thread Junio C Hamano
What's cooking in git.git (Apr 2013, #07; Mon, 22)
--

Here are the topics that have been cooking.  Commits prefixed with
'-' are only in 'pu' (proposed updates) while commits prefixed with
'+' are in 'next'.

Both of the two topics on preparing git add users for the
behaviour change in Git 2.0 are in 'master'.  We may want to tweak
the wording of warning messages and such before the feature freeze.

You can find the changes described here in the integration branches
of the repositories listed at

http://git-blame.blogspot.com/p/git-public-repositories.html

--
[Graduated to master]

* ap/strbuf-humanize (2013-04-10) 2 commits
  (merged to 'next' on 2013-04-14 at 66d7af5)
 + count-objects: add -H option to humanize sizes
 + strbuf: create strbuf_humanise_bytes() to show byte sizes

 Teach --human-readable aka -H option to git count-objects to
 show various large numbers in Ki/Mi/GiB scaled as necessary.

 I've decided to let this topic supersede mc/count-objects-kibibytes.
 Human users will get an even easier output with -H and by not
 changing the output without an explicit option we do not have to
 break third-party tools that may have been reading from the output
 of this command.


* as/clone-reference-with-gitfile (2013-04-09) 2 commits
  (merged to 'next' on 2013-04-15 at ab0d128)
 + clone: Allow repo using gitfile as a reference
 + clone: Fix error message for reference repository

 git clone did not work if a repository pointed at by the
 --reference option is a gitfile that points at another place.


* fc/branch-upstream-color (2013-04-15) 1 commit
  (merged to 'next' on 2013-04-15 at 2fc50fd)
 + branch: colour upstream branches

 Add more colors to git branch -vv output.


* fc/remote-hg (2013-04-11) 21 commits
  (merged to 'next' on 2013-04-16 at cbeaf41)
 + remote-hg: activate graphlog extension for hg_log()
 + remote-hg: fix bad file paths
 + remote-hg: document location of stored hg repository
 + remote-hg: fix bad state issue
 + remote-hg: add 'insecure' option
 + remote-hg: add simple mail test
 + remote-hg: add basic author tests
 + remote-hg: show more proper errors
 + remote-hg: force remote push
 + remote-hg: push to the appropriate branch
 + remote-hg: update tags globally
 + remote-hg: update remote bookmarks
 + remote-hg: refactor export
 + remote-hg: split bookmark handling
 + remote-hg: redirect buggy mercurial output
 + remote-hg: trivial test cleanups
 + remote-hg: make sure fake bookmarks are updated
 + remote-hg: fix for files with spaces
 + remote-hg: properly report errors on bookmark pushes
 + remote-hg: add missing config variable in doc
 + remote-hg: trivial cleanups

 Updates remote-hg helper (in contrib/).


* jk/a-thread-only-dies-once (2013-04-16) 2 commits
  (merged to 'next' on 2013-04-18 at 3208f44)
 + run-command: use thread-aware die_is_recursing routine
 + usage: allow pluggable die-recursion checks

 A regression fix for the logic to detect die() handler triggering
 itself recursively.


* jk/chopped-ident (2013-04-17) 3 commits
  (merged to 'next' on 2013-04-19 at ecec2d4)
 + blame: handle broken commit headers gracefully
 + pretty: handle broken commit headers gracefully
 + cat-file: print tags raw for cat-file -p

 A commit object whose author or committer ident are malformed
 crashed some code that trusted that a name, an email and an
 timestamp can always be found in it.


* jk/doc-http-backend (2013-04-13) 3 commits
  (merged to 'next' on 2013-04-19 at 7932840)
 + doc/http-backend: match query-string in apache half-auth example
 + doc/http-backend: give some lighttpd config examples
 + doc/http-backend: clarify half-auth repo configuration

 Improve documentation to illustrate push authenticated, fetch
 anonymous configuration for smart HTTP servers.


* jx/i18n-branch-error-messages (2013-04-15) 1 commit
  (merged to 'next' on 2013-04-18 at 630c211)
 + i18n: branch: mark strings for translation


* lf/read-blob-data-from-index (2013-04-17) 3 commits
  (merged to 'next' on 2013-04-17 at 611208f)
 + convert.c: remove duplicate code
 + read_blob_data_from_index(): optionally return the size of blob data
 + attr.c: extract read_index_data() as read_blob_data_from_index()

 Reduce duplicated code between convert.c and attr.c.


* mv/sequencer-pick-error-diag (2013-04-11) 1 commit
  (merged to 'next' on 2013-04-16 at a2da926)
 + cherry-pick: make sure all input objects are commits

 git cherry-pick $blob $tree is diagnosed as a nonsense.


* mv/ssl-ftp-curl (2013-04-12) 1 commit
  (merged to 'next' on 2013-04-15 at 7fdada6)
 + Support FTP-over-SSL/TLS for regular FTP

 Does anybody really use commit walkers over ftp???


* nd/checkout-keep-sparse (2013-04-15) 1 commit
  (merged to 'next' on 2013-04-19 at 803dabc)
 + checkout: add --ignore-skip-worktree-bits in sparse checkout mode

 Make the initial sparse selection of the paths more sticky across
 git checkout.

Re: [PATCH] t4202 (log): add failing test for log with subtree

2013-04-22 Thread Ramkumar Ramachandra
Junio C Hamano wrote:
  (1) It uses the given pathname as single pathspec and drill down
  the same way without --follow until it notices the path
  disappears and until then there is no attempt to detect renames
  is made.  And it only does -M variant of rename detection

On this.  It might be profitable to auto-follow at a low threshold
(and change --follow to a number  argument like -M, -C).  I'm not
asking you to do it for more than one-file at a time, but I often view
one file's history: I was just going through the history of
builtin/merge-trees.c (what I was looking for was mostly in the
builtin-* variant), and it would've been nice if I didn't have to quit
and come back with a --follow.
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 0/2] git add -A/--no-all finishing touches

2013-04-22 Thread Junio C Hamano
Applying Jonathan's idea on top of the early part that has graduated
to 'master', here is to add --ignore-removal (which is a more
natural way to say --no-all) and use it in the warning message.

Junio C Hamano (2):
  git add: --ignore-removal is a better named --no-all
  git add: rephrase -A/--no-all warning

 Documentation/git-add.txt | 10 ++
 builtin/add.c | 23 +--
 2 files changed, 23 insertions(+), 10 deletions(-)

-- 
1.8.2.1-683-g39c426e

--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 1/2] git add: --ignore-removal is a better named --no-all

2013-04-22 Thread Junio C Hamano
In the historical context of git add --all . that tells the
command to pay attention to all kinds of changes (implying
without ignoring removals), the option --no-all to countermand
it may have made some sense, but because we will be making --all
the default when a pathspec is given, it makes more sense to rename
the option to a more explicit --ignore-removal.  The -all option
naturally becomes its negation: --no-ignore-removal.

Signed-off-by: Junio C Hamano gits...@pobox.com
---
 Documentation/git-add.txt | 10 ++
 builtin/add.c | 11 +++
 2 files changed, 17 insertions(+), 4 deletions(-)

diff --git a/Documentation/git-add.txt b/Documentation/git-add.txt
index 5c501a2..48754cb 100644
--- a/Documentation/git-add.txt
+++ b/Documentation/git-add.txt
@@ -9,9 +9,9 @@ SYNOPSIS
 
 [verse]
 'git add' [-n] [-v] [--force | -f] [--interactive | -i] [--patch | -p]
- [--edit | -e] [--[no-]all | [--update | -u]] [--intent-to-add | -N]
- [--refresh] [--ignore-errors] [--ignore-missing] [--]
- [pathspec...]
+ [--edit | -e] [--[no-]all | --[no-]ignore-removal | [--update | -u]]
+ [--intent-to-add | -N] [--refresh] [--ignore-errors] 
[--ignore-missing]
+ [--] [pathspec...]
 
 DESCRIPTION
 ---
@@ -111,6 +111,7 @@ of Git, hence the form without pathspec should not be 
used.
 
 -A::
 --all::
+--no-ignore-removal::
Update the index not only where the working tree has a file
matching pathspec but also where the index already has an
entry.  This adds, modifies, and removes index entries to
@@ -122,6 +123,7 @@ and its subdirectories. This default will change in a 
future version
 of Git, hence the form without pathspec should not be used.
 
 --no-all::
+--ignore-removal::
Update the index by adding new files that are unknown to the
index and files modified in the working tree, but ignore
files that have been removed from the working tree.  This
@@ -130,7 +132,7 @@ of Git, hence the form without pathspec should not be 
used.
 This option is primarily to help the current users of Git, whose
 git add pathspec... ignores removed files.  In future versions
 of Git, git add pathspec... will be a synonym to git add -A
-pathspec... and git add --no-all pathspec... will behave like
+pathspec... and git add --ignore-removal pathspec... will behave like
 today's git add pathspec..., ignoring removed files.
 
 -N::
diff --git a/builtin/add.c b/builtin/add.c
index 54cd2d4..aefbc45 100644
--- a/builtin/add.c
+++ b/builtin/add.c
@@ -382,6 +382,13 @@ static int ignore_add_errors, intent_to_add, 
ignore_missing;
 static int addremove = ADDREMOVE_DEFAULT;
 static int addremove_explicit = -1; /* unspecified */
 
+static int ignore_removal_cb(const struct option *opt, const char *arg, int 
unset)
+{
+   /* if we are told to ignore, we are not adding removals */
+   *(int *)opt-value = !unset ? 0 : 1;
+   return 0;
+}
+
 static struct option builtin_add_options[] = {
OPT__DRY_RUN(show_only, N_(dry run)),
OPT__VERBOSE(verbose, N_(be verbose)),
@@ -393,6 +400,10 @@ static struct option builtin_add_options[] = {
OPT_BOOL('u', update, take_worktree_changes, N_(update tracked 
files)),
OPT_BOOL('N', intent-to-add, intent_to_add, N_(record only the fact 
that the path will be added later)),
OPT_BOOL('A', all, addremove_explicit, N_(add changes from all 
tracked and untracked files)),
+   { OPTION_CALLBACK, 0, ignore-removal, addremove_explicit,
+ NULL /* takes no arguments */,
+ N_(ignore paths removed in the working tree (same as --no-all)),
+ PARSE_OPT_NOARG, ignore_removal_cb },
OPT_BOOL( 0 , refresh, refresh_only, N_(don't add, only refresh the 
index)),
OPT_BOOL( 0 , ignore-errors, ignore_add_errors, N_(just skip files 
which cannot be added because of errors)),
OPT_BOOL( 0 , ignore-missing, ignore_missing, N_(check if - even 
missing - files are ignored in dry run)),
-- 
1.8.2.1-683-g39c426e

--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 2/2] git add: rephrase -A/--no-all warning

2013-04-22 Thread Junio C Hamano
With the synonym --ignore-removal for --no-all, we can rephrase
the Git 2.0 transition warning message in a more natural way.

Signed-off-by: Junio C Hamano gits...@pobox.com
---
 builtin/add.c | 12 ++--
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/builtin/add.c b/builtin/add.c
index aefbc45..c55615b 100644
--- a/builtin/add.c
+++ b/builtin/add.c
@@ -97,13 +97,13 @@ static int fix_unmerged_status(struct diff_filepair *p,
 }
 
 static const char *add_would_remove_warning = N_(
-   You ran 'git add' with neither '-A (--all)' or '--no-all', whose\n
-behaviour will change in Git 2.0 with respect to paths you removed from\n
-your working tree. Paths like '%s' that are\n
-removed are ignored with this version of Git.\n
+   You ran 'git add' with neither '-A (--all)' or '--ignore-removal',\n
+whose behaviour will change in Git 2.0 with respect to paths you removed.\n
+Paths like '%s' that are\n
+removed from your working tree are ignored with this version of Git.\n
 \n
-* 'git add --no-all pathspec', which is the current default, ignores\n
-  paths you removed from your working tree.\n
+* 'git add --ignore-removal pathspec', which is the current default,\n
+  ignores paths you removed from your working tree.\n
 \n
 * 'git add --all pathspec' will let you also record the removals.\n
 \n
-- 
1.8.2.1-683-g39c426e

--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] t4202 (log): add failing test for log with subtree

2013-04-22 Thread Philip Oakley

From: Ramkumar Ramachandra artag...@gmail.com
Sent: Monday, April 22, 2013 8:54 PM

Thomas Rast wrote:
There is a market for a rename detection that works at the tree 
level.


Exactly.  And making it auto-follow with a low threshold would be a
great default.  We'll have to deal with D/F conflicts that Junio was
talking about in (2), every once in a while.  We'll have a lot more
incentive to build the D/F conflict resolution process a nice UI.

git-core will actually start working with trees the way it works with 
blobs.

--


Is this not similar to the previous attempts at bulk rename detection? 
Such as $gmane/160233.


A practical bulk rename detection would be good. It doesn't have to be 
perfect.


Philip 


--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] bisect: Store first bad commit as comment in log file

2013-04-22 Thread Torstein Hegge
On Mon, Apr 15, 2013 at 11:53:39 +0200, Torstein Hegge wrote:
 On Mon, Apr 15, 2013 at 06:38:09 +0200, Christian Couder wrote:
  I wonder if we should also write something into the bisect log if for
  example the bisection stopped because there are only 'skip'ped commits
  left to test. But maybe this could go into another patch after this
  one.
 
 Yes, that would be useful, but I wasn't able to determine all the cases
 that would be relevant to log. Only skipped commits left to test is one,
 but bisect--helper also exits on various problems related to merge base
 handling. The handling of problems related to inconsistent user input is
 probably not relevant to log.

I took another look at this. I wasn't able to come up with anything
useful for the The merge base $rev is bad case, but for the only
skipped commits left to test case one could do something like this.

There has to be a better way to get the range of possible first bad
commits, similar to the output of 'git log --bisect --format=%H'.

--- 8 ---
Subject: [PATCH] bisect: Log possibly bad, skipped commits at bisection end

If the bisection completes with only skipped commits left to as possible
first bad commit, output the list of possible first bad commits to human
readers of the bisection log.

Signed-off-by: Torstein Hegge he...@resisty.net
---
 git-bisect.sh   |   10 ++
 t/t6030-bisect-porcelain.sh |   20 
 2 files changed, 30 insertions(+)

diff --git a/git-bisect.sh b/git-bisect.sh
index c58eea7..d7518e9 100755
--- a/git-bisect.sh
+++ b/git-bisect.sh
@@ -317,6 +317,16 @@ bisect_next() {
bad_commit=$(git show-branch $bad_rev)
echo # first bad commit: $bad_commit $GIT_DIR/BISECT_LOG
exit 0
+   elif test $res -eq 2
+   then
+   echo # only skipped commits left to test 
$GIT_DIR/BISECT_LOG
+   good_revs=$(git for-each-ref --format=--not %(objectname) 
refs/bisect/good-*)
+   for skipped in $(git rev-list refs/bisect/bad $good_revs)
+   do
+   skipped_commit=$(git show-branch $skipped)
+   echo # possible first bad commit: $skipped_commit 
$GIT_DIR/BISECT_LOG
+   done
+   exit $res
fi
 
# Check for an error in the bisection process
diff --git a/t/t6030-bisect-porcelain.sh b/t/t6030-bisect-porcelain.sh
index 4d3074a..064f5ce 100755
--- a/t/t6030-bisect-porcelain.sh
+++ b/t/t6030-bisect-porcelain.sh
@@ -759,4 +759,24 @@ test_expect_success 'bisect log: successfull result' '
git bisect reset
 '
 
+cat  expected.bisect-skip-log EOF
+# bad: [32a594a3fdac2d57cf6d02987e30eec68511498c] Add 4: Ciao for now into 
hello.
+# good: [7b7f204a749c3125d5224ed61ea2ae1187ad046f] Add 2: A new day for git 
into hello.
+git bisect start '32a594a3fdac2d57cf6d02987e30eec68511498c' 
'7b7f204a749c3125d5224ed61ea2ae1187ad046f'
+# skip: [3de952f2416b6084f557ec417709eac740c6818c] Add 3: Another new day for 
git into hello.
+git bisect skip 3de952f2416b6084f557ec417709eac740c6818c
+# only skipped commits left to test
+# possible first bad commit: [32a594a3fdac2d57cf6d02987e30eec68511498c] Add 
4: Ciao for now into hello.
+# possible first bad commit: [3de952f2416b6084f557ec417709eac740c6818c] Add 
3: Another new day for git into hello.
+EOF
+
+test_expect_success 'bisect log: only skip commits left' '
+   git bisect reset 
+   git bisect start $HASH4 $HASH2 
+   test_must_fail git bisect skip 
+   git bisect log bisect-skip-log.txt 
+   test_cmp expected.bisect-skip-log bisect-skip-log.txt 
+   git bisect reset
+'
+
 test_done
-- 
1.7.10.4

--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] t4202 (log): add failing test for log with subtree

2013-04-22 Thread Matthieu Moy
Thomas Rast tr...@inf.ethz.ch writes:

 So how can we fix that?  We could try to somehow figure out that M:sub/
 refers to the same thing as M^2:/, by looking at them at the tree level.
 Let's provisionally call this --follow-tree-rename.

There was a patch serie long ago that implemented directory rename
detection:

  http://thread.gmane.org/gmane.comp.version-control.git/163328

I'm not sure why it hasn't been merged.

-- 
Matthieu Moy
http://www-verimag.imag.fr/~moy/
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] t4202 (log): add failing test for log with subtree

2013-04-22 Thread Ramkumar Ramachandra
Philip Oakley wrote:
 Is this not similar to the previous attempts at bulk rename detection? Such
 as $gmane/160233.

Yes.  Does anyone know what happened to the series?

... and I wonder how git merge -s subtree works (still reading).
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] bisect: Store first bad commit as comment in log file

2013-04-22 Thread Junio C Hamano
Torstein Hegge he...@resisty.net writes:

 I took another look at this. I wasn't able to come up with anything
 useful for the The merge base $rev is bad case, but for the only
 skipped commits left to test case one could do something like this.

We skipped them because we can gain _no_ information from testing
these commits. They are not even possibly bad, but are unknown.

So it feels to me that by definition listing them would not be
useful. What am I missing?

--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] zlib: fix compilation failures with Sun C Compilaer

2013-04-22 Thread Eric Sunshine
On Mon, Apr 22, 2013 at 12:18 PM, Stefano Lattarini
stefano.lattar...@gmail.com wrote:
 zlib: fix compilation failures with Sun C Compilaer

s/Compilaer/compiler/

 Do this by removing a couple of useless return statements.  Without this
 change, compilation with Sun C Compiler 5.9 (SunOS_i386 Patch 124868-15
 2010/08/11) fails with the following message:

   zlib.c, line 192: void function cannot return value
   zlib.c, line 201: void function cannot return value
   cc: acomp failed for zlib.c

 Signed-off-by: Stefano Lattarini stefano.lattar...@gmail.com
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 00/16] remote-hg: second round of improvements

2013-04-22 Thread Felipe Contreras
Hi,

Now that the safter first round is merged to master, it's time for the second
round which is a little tricker. Most of the patches should be safe, but the
later ones might be not. All the tests pass, even gitifyhg ones, so everything
seems to be fine, but we shall see.

Among the important changes are:

 * Proper support for tags (they are global, and we can push them)
 * Improved e-mail sanitaztion (a bit similar to gitifyhg, but better)
 * Support for hg schemes (like bb://felipec/repo)
 * Support for tags, bookmarks and branches with spaces
 * Performance improvements

Good stuff we should probably merge to master if there are no issues.

Cheers.

Dusty Phillips (1):
  remote-helpers: avoid has_key

Felipe Contreras (15):
  remote-hg: safer bookmark pushing
  remote-hg: use python urlparse
  remote-hg: properly mark branches up-to-date
  remote-hg: add branch_tip() helper
  remote-hg: add support for tag objects
  remote-hg: custom method to write tags
  remote-hg: write tags in the appropriate branch
  remote-hg: add custom local tag write code
  remote-hg: improve email sanitation
  remote-hg: add support for schemes extension
  remote-hg: don't update bookmarks unnecessarily
  remote-hg: allow refs with spaces
  remote-hg: small performance improvement
  remote-hg: use marks instead of inlined files
  remote-hg: strip extra newline

 contrib/remote-helpers/git-remote-bzr |   2 +-
 contrib/remote-helpers/git-remote-hg  | 167 +++---
 contrib/remote-helpers/test-hg.sh |   8 +-
 3 files changed, 141 insertions(+), 36 deletions(-)

-- 
1.8.2.1.790.g4588561

--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 02/16] remote-hg: safer bookmark pushing

2013-04-22 Thread Felipe Contreras
It is possible that the remote has changed the bookmarks, so let's fetch
them before we make any assumptions, just the way mercurial does.

Probably doesn't make a difference, but better be safe than sorry.

Signed-off-by: Felipe Contreras felipe.contre...@gmail.com
---
 contrib/remote-helpers/git-remote-hg | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/contrib/remote-helpers/git-remote-hg 
b/contrib/remote-helpers/git-remote-hg
index 2cd1996..dcf6c98 100755
--- a/contrib/remote-helpers/git-remote-hg
+++ b/contrib/remote-helpers/git-remote-hg
@@ -782,6 +782,8 @@ def do_export(parser):
 continue
 
 if peer:
+rb = peer.listkeys('bookmarks')
+old = rb.get(bmark, '')
 if not peer.pushkey('bookmarks', bmark, old, new):
 print error %s % ref
 continue
-- 
1.8.2.1.790.g4588561

--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 01/16] remote-helpers: avoid has_key

2013-04-22 Thread Felipe Contreras
From: Dusty Phillips du...@linux.ca

It is deprecated.

[fc: do the same in remote-bzr]

Signed-off-by: Felipe Contreras felipe.contre...@gmail.com
---
 contrib/remote-helpers/git-remote-bzr | 2 +-
 contrib/remote-helpers/git-remote-hg  | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/contrib/remote-helpers/git-remote-bzr 
b/contrib/remote-helpers/git-remote-bzr
index aa7bc97..cc6609b 100755
--- a/contrib/remote-helpers/git-remote-bzr
+++ b/contrib/remote-helpers/git-remote-bzr
@@ -94,7 +94,7 @@ class Marks:
 return self.last_mark
 
 def is_marked(self, rev):
-return self.marks.has_key(rev)
+return str(rev) in self.marks
 
 def new_mark(self, rev, mark):
 self.marks[rev] = mark
diff --git a/contrib/remote-helpers/git-remote-hg 
b/contrib/remote-helpers/git-remote-hg
index 5481331..2cd1996 100755
--- a/contrib/remote-helpers/git-remote-hg
+++ b/contrib/remote-helpers/git-remote-hg
@@ -129,7 +129,7 @@ class Marks:
 self.last_mark = mark
 
 def is_marked(self, rev):
-return self.marks.has_key(str(rev))
+return str(rev) in self.marks
 
 def get_tip(self, branch):
 return self.tips.get(branch, 0)
-- 
1.8.2.1.790.g4588561

--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 03/16] remote-hg: use python urlparse

2013-04-22 Thread Felipe Contreras
It's simpler, and we don't need to depend on certain Mercurial versions.

Also, now we don't update the URL if 'file://' is not present.

Signed-off-by: Felipe Contreras felipe.contre...@gmail.com
---
 contrib/remote-helpers/git-remote-hg | 9 +
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/contrib/remote-helpers/git-remote-hg 
b/contrib/remote-helpers/git-remote-hg
index dcf6c98..b6589a3 100755
--- a/contrib/remote-helpers/git-remote-hg
+++ b/contrib/remote-helpers/git-remote-hg
@@ -22,6 +22,7 @@ import shutil
 import subprocess
 import urllib
 import atexit
+import urlparse
 
 #
 # If you want to switch to hg-git compatibility mode:
@@ -793,11 +794,11 @@ def do_export(parser):
 print
 
 def fix_path(alias, repo, orig_url):
-repo_url = util.url(repo.url())
-url = util.url(orig_url)
-if str(url) == str(repo_url):
+url = urlparse.urlparse(orig_url, 'file')
+if url.scheme != 'file' or os.path.isabs(url.path):
 return
-cmd = ['git', 'config', 'remote.%s.url' % alias, hg::%s % repo_url]
+abs_url = urlparse.urljoin(%s/ % os.getcwd(), orig_url)
+cmd = ['git', 'config', 'remote.%s.url' % alias, hg::%s % abs_url]
 subprocess.call(cmd)
 
 def main(args):
-- 
1.8.2.1.790.g4588561

--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH 05/16] remote-hg: add branch_tip() helper

2013-04-22 Thread Felipe Contreras
Idea from gitifyhg, the backwards compatibility is how Mercurial used to
do it.

Signed-off-by: Felipe Contreras felipe.contre...@gmail.com
---
 contrib/remote-helpers/git-remote-hg | 11 ---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/contrib/remote-helpers/git-remote-hg 
b/contrib/remote-helpers/git-remote-hg
index a4db5b0..bd93f82 100755
--- a/contrib/remote-helpers/git-remote-hg
+++ b/contrib/remote-helpers/git-remote-hg
@@ -457,6 +457,13 @@ def do_capabilities(parser):
 
 print
 
+def branch_tip(repo, branch):
+# older versions of mercurial don't have this
+if hasattr(repo, 'branchtip'):
+return repo.branchtip(branch)
+else:
+return repo.branchtags()[branch]
+
 def get_branch_tip(repo, branch):
 global branches
 
@@ -467,9 +474,7 @@ def get_branch_tip(repo, branch):
 # verify there's only one head
 if (len(heads)  1):
 warn(Branch '%s' has more than one head, consider merging % branch)
-# older versions of mercurial don't have this
-if hasattr(repo, branchtip):
-return repo.branchtip(branch)
+return branch_tip(repo, branch)
 
 return heads[0]
 
-- 
1.8.2.1.790.g4588561

--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


  1   2   >