Re: [PATCH] clone: allow initial sparse checkouts

2014-02-22 Thread Robin H. Johnson
On Sun, Feb 23, 2014 at 09:52:16AM +0700,  Duy Nguyen wrote:
> On Sun, Feb 23, 2014 at 9:31 AM, Robin H. Johnson  wrote:
> > Presently if you want to perform a sparse checkout, you must either do a
> > full clone and then recheckout, or do a git init, manually set up
> > sparse, and then fetch and checkout.
> I think you could do "clone -n" (no checkout), set up sparse, then checkout.
Yes, I think there are a few more ways, but still would be nice to 

> 
> > This patch implements easily accessible sparse checkouts during clone,
> > in the --sparse-checkout option.
> >
> > $ git clone REPO --sparse-checkout PATH
> Or take a file as input if there are lots of paths/rules.
How much demand for taking a file of rules, and opinions of syntax to do
that vs specify on the commandline?

--sparse-checkout-from FILE
vs.
--sparse-checkout 'http://vger.kernel.org/majordomo-info.html


Re: [PATCH] clone: allow initial sparse checkouts

2014-02-22 Thread Duy Nguyen
On Sun, Feb 23, 2014 at 9:31 AM, Robin H. Johnson  wrote:
> Presently if you want to perform a sparse checkout, you must either do a
> full clone and then recheckout, or do a git init, manually set up
> sparse, and then fetch and checkout.

I think you could do "clone -n" (no checkout), set up sparse, then checkout.

> This patch implements easily accessible sparse checkouts during clone,
> in the --sparse-checkout option.
>
> $ git clone REPO --sparse-checkout PATH

Or take a file as input if there are lots of paths/rules.
-- 
Duy
--
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 v3 0/8] Hiding refs

2014-02-22 Thread Duy Nguyen
(Digging up an old thread about initial refs listing in git protocol)

On Thu, Feb 7, 2013 at 7:12 AM, Junio C Hamano  wrote:
> Ævar Arnfjörð Bjarmason  writes:
>
>> I think there's a simpler way to do this, which is that:
>>
>>  * New clients supporting v2 of the protocol send some piece of data
>>that would break old servers.
>>
>>  * If that fails the new client goes "oh jeeze, I guess it's an old
>>server", and try again with the old protocol.
>>
>>  * The client then saves a date (or the version the server gave us)
>>indicating that it tried the new protocol on that remote, tries
>>again sometime later.
>
> For that to work, the new server needs to wait for the client to
> speak first.  How would that server handle old clients who expect to
> be spoken first?  Wait with a read timeout (no timeout is the right
> timeout for everybody)?

I think the client always speaks first when it asks for a remote
service. Earlier in this thread you described the new protocol
upload-pack-2. Why can't it be a new service "upload-pack-2" in
git-daemon?

So new client will try requesting "upload-pack-2" service with client
capability advertisement before ref listing. Old servers do not
recognize this service and disconnect so the new client falls back to
the good old "upload-pack" (one more round trip though, but you could
configure new client to use old protocol for certain "old" hosts).
Similar thing happens for ssh transport. "upload-pack" service is
always there for old clients.
-- 
Duy
--
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] clone: allow initial sparse checkouts

2014-02-22 Thread Robin H. Johnson
Presently if you want to perform a sparse checkout, you must either do a
full clone and then recheckout, or do a git init, manually set up
sparse, and then fetch and checkout.

This patch implements easily accessible sparse checkouts during clone,
in the --sparse-checkout option.

$ git clone REPO --sparse-checkout PATH

Signed-off-by: Robin H. Johnson 
---
 Documentation/git-clone.txt |  5 +
 builtin/clone.c | 24 
 2 files changed, 29 insertions(+)

diff --git a/Documentation/git-clone.txt b/Documentation/git-clone.txt
index 0363d00..1c21207 100644
--- a/Documentation/git-clone.txt
+++ b/Documentation/git-clone.txt
@@ -14,6 +14,7 @@ SYNOPSIS
  [-o ] [-b ] [-u ] [--reference ]
  [--separate-git-dir ]
  [--depth ] [--[no-]single-branch]
+ [--sparse-checkout ]
  [--recursive | --recurse-submodules] [--] 
  []
 
@@ -209,6 +210,10 @@ objects from the source repository into a pack in the 
cloned repository.
The result is Git repository can be separated from working
tree.
 
+--sparse-checkout ::
+   Perform the initial checkout as a sparse checkout, checking out only the
+   paths specified by this option. This option may occur multiple times, 
with
+   one path per instance.
 
 ::
The (possibly remote) repository to clone from.  See the
diff --git a/builtin/clone.c b/builtin/clone.c
index 43e772c..1137371 100644
--- a/builtin/clone.c
+++ b/builtin/clone.c
@@ -48,6 +48,7 @@ static int option_verbosity;
 static int option_progress = -1;
 static struct string_list option_config;
 static struct string_list option_reference;
+static struct string_list option_sparse_checkout_path;
 
 static int opt_parse_reference(const struct option *opt, const char *arg, int 
unset)
 {
@@ -97,6 +98,8 @@ static struct option builtin_clone_options[] = {
   N_("separate git dir from working tree")),
OPT_STRING_LIST('c', "config", &option_config, N_("key=value"),
N_("set config inside the new repository")),
+   OPT_STRING_LIST(0, "sparse-checkout", &option_sparse_checkout_path, 
N_("path"),
+   N_("set path for sparse checkout")),
OPT_END()
 };
 
@@ -270,6 +273,24 @@ static void setup_reference(void)
for_each_string_list(&option_reference, add_one_reference, NULL);
 }
 
+static void setup_sparse_checkout(void)
+{
+   FILE *info_sparse_checkout_fp;
+   struct string_list_item *item;
+   char *path = git_pathdup("info/sparse-checkout");
+   git_config_set("core.sparsecheckout", "true");
+   safe_create_leading_directories(path);
+   info_sparse_checkout_fp = fopen(path, "w");
+   if (!info_sparse_checkout_fp)
+   die(_("unable to create %s"), path);
+   for_each_string_list_item(item, &option_sparse_checkout_path) {
+   fprintf(info_sparse_checkout_fp, "%s\n", item->string);
+   }
+   fclose(info_sparse_checkout_fp);
+   adjust_shared_perm(path);
+   free(path);
+}
+
 static void copy_alternates(struct strbuf *src, struct strbuf *dst,
const char *src_repo)
 {
@@ -873,6 +894,9 @@ int cmd_clone(int argc, const char **argv, const char 
*prefix)
init_db(option_template, INIT_DB_QUIET);
write_config(&option_config);
 
+   if(option_sparse_checkout_path.nr)
+   setup_sparse_checkout();
+
git_config(git_default_config, NULL);
 
if (option_bare) {
-- 
1.9.0.291.g027825b.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] i18n: mark all progress lines for translation

2014-02-22 Thread Peter Krefting

Nguy?n Thái Ng?c Duy:

I can't think of any case that progress lines are for machine. It 
started because of the only local untranslated line in "git clone". 
But I think we should do all at once.


Indeed, a good move. Anything that is to be displayed to the end user 
should be subject to localization; if it is part of a protocol, then 
it needs to be translated on the receiving end.


--
\\// Peter - http://www.softwolves.pp.se/
--
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: Fwd: git-reviewed: linking commits to review discussion in git

2014-02-22 Thread Thomas Rast
Jeff King  writes:

> On Mon, Feb 17, 2014 at 03:12:48PM -0500, Murtuza Mukadam wrote:
>
>> We have linked peer review discussions on
>> git@vger.kernel.org to their respective commits within the main
>> git.git repository. You can view the linked reviews from 2012
>> until present in the GitHub repo at:
>> https://github.com/mmukadam/git/tree/review
>
> Neat. We've experimented in the past with mapping commits back to
> mailing list discussions.  Thomas (cc'd) has a script that creates
> git-notes trees mapping commits to the relevant message-id, which can
> then be found in the list archive.
>
> To me, the interesting bits of such a project are:
>
>   1. How do we decide which messages led to which commits? There is
>  definitely some room for heuristics here, as patches are sometimes
>  tweaked in transit, or come in multiple stages (e.g., the original
>  patch, then somebody suggests a fixup on top). You might want to
>  compare your work with the script from Thomas here:
>
>http://repo.or.cz/w/trackgit.git

Eh, or don't.  My script nowadays uses Junio's suggestion of matching on
(author, authordate) with a little bit of tweaking in case there is no
match.  The name/date match works for most cases even in slightly
tweaked forms.

(The very first version elaborately tried all sorts of things, including
attempting to patch on master, next etc. to see where it applies, and
turned out to be wy too slow.)

I'm no longer convinced that there's anything a computer can do beyond
(author, authordate), anyway.  Perhaps someone with a clue in UIs --
that's definitely not me -- could make a website where users can
complete or correct the autogenerated mappings to go further.

-- 
Thomas Rast
t...@thomasrast.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] builtin/blame.c::find_copy_in_blob: no need to scan for line end

2014-02-22 Thread David Kastrup
David Kastrup  writes:

Oh, good grief.  Forgot to sign off, and on rereading, the commit
message is clearly subfabulous.  So forget this one.  The content is
fine, though.

-- 
David Kastrup
--
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] builtin/blame.c::find_copy_in_blob: no need to scan for region end

2014-02-22 Thread David Kastrup
The region end can be looked up just like its beginning.

Signed-off-by: David Kastrup 
---
 builtin/blame.c | 9 +
 1 file changed, 1 insertion(+), 8 deletions(-)

diff --git a/builtin/blame.c b/builtin/blame.c
index e44a6bb..96716dd 100644
--- a/builtin/blame.c
+++ b/builtin/blame.c
@@ -939,7 +939,6 @@ static void find_copy_in_blob(struct scoreboard *sb,
  mmfile_t *file_p)
 {
const char *cp;
-   int cnt;
mmfile_t file_o;
struct handle_split_cb_data d;
 
@@ -950,13 +949,7 @@ static void find_copy_in_blob(struct scoreboard *sb,
 */
cp = nth_line(sb, ent->lno);
file_o.ptr = (char *) cp;
-   cnt = ent->num_lines;
-
-   while (cnt && cp < sb->final_buf + sb->final_buf_size) {
-   if (*cp++ == '\n')
-   cnt--;
-   }
-   file_o.size = cp - file_o.ptr;
+   file_o.size = nth_line(sb, ent->lno + ent->num_lines) - cp;
 
/*
 * file_o is a part of final image we are annotating.
-- 
1.8.3.2

--
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] builtin/blame.c::find_copy_in_blob: no need to scan for line end

2014-02-22 Thread David Kastrup
---
 builtin/blame.c | 9 +
 1 file changed, 1 insertion(+), 8 deletions(-)

diff --git a/builtin/blame.c b/builtin/blame.c
index e44a6bb..96716dd 100644
--- a/builtin/blame.c
+++ b/builtin/blame.c
@@ -939,7 +939,6 @@ static void find_copy_in_blob(struct scoreboard *sb,
  mmfile_t *file_p)
 {
const char *cp;
-   int cnt;
mmfile_t file_o;
struct handle_split_cb_data d;
 
@@ -950,13 +949,7 @@ static void find_copy_in_blob(struct scoreboard *sb,
 */
cp = nth_line(sb, ent->lno);
file_o.ptr = (char *) cp;
-   cnt = ent->num_lines;
-
-   while (cnt && cp < sb->final_buf + sb->final_buf_size) {
-   if (*cp++ == '\n')
-   cnt--;
-   }
-   file_o.size = cp - file_o.ptr;
+   file_o.size = nth_line(sb, ent->lno + ent->num_lines) - cp;
 
/*
 * file_o is a part of final image we are annotating.
-- 
1.8.3.2

--
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] sha1_file: fix delta_stack memory leak in unpack_entry

2014-02-22 Thread Thomas Rast
Junio C Hamano  writes:

> Jeff King  writes:
>
>> On Fri, Feb 21, 2014 at 06:47:47AM +0700, Nguyễn Thái Ngọc Duy wrote:
>>
>>> This delta_stack array can grow to any length depending on the actual
>>> delta chain, but we forget to free it. Normally it does not matter
>>> because we use small_delta_stack[] from stack and small_delta_stack
>>> can hold 64-delta chains, more than standard --depth=50 in pack-objects.
>>> 
>>> Signed-off-by: Nguyễn Thái Ngọc Duy 
>>> ---
>>>  Found when trying to see if making some objects loose at this phase
>>>  could help git-blame and how many objects will be loosened. Gotta go
>>>  soon, didn't really test it, but I bet it'll work.
>>
>> This looks correct to me.
>
> This comes from abe601bb, right?  The change looks correct to me, too.

Ow, sorry about that.  Thanks for the fix!

-- 
Thomas Rast
t...@thomasrast.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: git gc --aggressive led to about 40 times slower "git log --raw"

2014-02-22 Thread Duy Nguyen
On Sat, Feb 22, 2014 at 4:14 PM, Duy Nguyen  wrote:
> On Sat, Feb 22, 2014 at 3:53 PM, David Kastrup  wrote:
>> David Kastrup  writes:
>>
>>> Duy Nguyen  writes:
>>>
 OK with git://git.savannah.gnu.org/emacs.git we have

  - a 209MB pack with --aggressive
  - 1.3GB with --depth=50
  - 1.3GB with --window=4000 --depth=32
  - 1.3GB with --depth=20
  - 821MB with --depth=250 for commits --before=2.years.ago, --depth=50
 for the rest
...

 I'm not really happy with --depth=250 producing 209MB while
 --depth=250 --before=2.year.ago a 800MB pack. It looks wrong (or maybe
 I did something wrong)

>> Another thing: did you really use --depth=250 here or did you use
>> --aggressive?  It may be that the latter also sets other options?
>
> I can't use --aggressive because I need to feed revisions directly to
> pack-objects. --aggressive also sets --window=250. Thanks for
> checking. My machine will have another workout session.

And 800MB is reduced to 177MB, containing history older than 2 years.
The final pack is 199MB, within the size range of current --aggressive
and should be reasonably fast on most operations. Again blame could
still hit long delta chains but I think we should just unpack some
trees/blobs when we hit long delta chains.

I think we should update --aggressive to do it this way. So

 - gc.aggressiveDepth defaults to 50 (or 20?), this is used for recent history
 - gc.aggressiveDeepDepth defaults to 250 (or smaller??), used for
ancient history
 - gc.aggressiveDeepOption is rev-list a rev-list option to define
"ancient history", default to --before=2.years.ago. This option could
be specified multiple times.

Both packing phases use the same gc.aggressiveWindow. We could add
gc.aggressiveDeepWindow too.

GSoC project?
-- 
Duy
--
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: Still waiting for your response

2014-02-22 Thread Mrs. Supini Thrunkul
Hello,

I am Mrs. Supini Thrunkul from Tai Yau Bank Hong Kong, I need your cooperation 
to transfer $ 47.3 million US Dollars to any trusted account within your 
control.

Contact me for more details.  

Mrs. Supini Thrunkul
Tel: +85 2580 848 65



--
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] diff: do not reuse_worktree_file for submodules

2014-02-22 Thread Thomas Rast
Junio C Hamano  writes:

> Thomas Rast  writes:
>
>> @@ -2845,8 +2845,9 @@ static struct diff_tempfile *prepare_temp_file(const 
>> char *name,
>>  remove_tempfile_installed = 1;
>>  }
>>  
>> -if (!one->sha1_valid ||
>> -reuse_worktree_file(name, one->sha1, 1)) {
>> +if (!S_ISGITLINK(one->mode) &&
>> +(!one->sha1_valid ||
>> + reuse_worktree_file(name, one->sha1, 1))) {
>
> I agree with the goal/end result, but I have to wonder if the
> reuse_worktree_file() be the helper function that ought to
> encapsulate such a logic?
>
> Instead of feeding it an object name and a path, if we passed a
> diff_filespec to the helper, it would have access to the mode as
> well.  It would result in a more intrusive change, so I'd prefer to
> see your patch applied first and then build such a refactor on top,
> perhaps like the attached.

I see that you already queued 721e727, which has the change you
described plus moving the S_ISGITLINK test into reuse_worktree_file.
The change looks good to me.  However, two nits about the comments:
diff.c now says

  /*
   * Given a name and sha1 pair, if the index tells us the file in
   * the work tree has that object contents, return true, so that
   * prepare_temp_file() does not have to inflate and extract.
   */
  static int reuse_worktree_file(const struct diff_filespec *spec, int 
want_file)
  {
  const struct cache_entry *ce;
  struct stat st;
  int pos, len;
  const char *name = spec->path;
  const unsigned char *sha1 = spec->sha1;

  /* reading the directory will not give us "Submodule commit XYZ" */
  if (S_ISGITLINK(spec->mode))
  return 0;

But the function comment is no longer accurate, and the comment about
the S_ISGITLINK exit is rather obscure if one doesn't know what the
callers want.  So how about this on top?

 diff.c | 17 +
 1 file changed, 13 insertions(+), 4 deletions(-)

diff --git i/diff.c w/diff.c
index a342ea6..dabf913 100644
--- i/diff.c
+++ w/diff.c
@@ -2578,9 +2578,14 @@ void fill_filespec(struct diff_filespec *spec, const 
unsigned char *sha1,
 }
 
 /*
- * Given a name and sha1 pair, if the index tells us the file in
- * the work tree has that object contents, return true, so that
- * prepare_temp_file() does not have to inflate and extract.
+ * Given a diff_filespec, determine if the corresponding worktree file
+ * can be used for diffing instead of reading the object from the
+ * repository.
+ *
+ * We normally try packfiles, worktree, loose objects in this order.
+ *
+ * If want_file=1 or git was compiled with NO_FAST_WORKING_DIRECTORY,
+ * the order is: worktree, packfiles, loose objects.
  */
 static int reuse_worktree_file(const struct diff_filespec *spec, int want_file)
 {
@@ -2590,7 +2595,11 @@ static int reuse_worktree_file(const struct 
diff_filespec *spec, int want_file)
const char *name = spec->path;
const unsigned char *sha1 = spec->sha1;
 
-   /* reading the directory will not give us "Submodule commit XYZ" */
+   /*
+* The diff representation of a submodule is "Submodule commit
+* XYZ", but in the worktree we have a directory.  So they
+* never match.
+*/
if (S_ISGITLINK(spec->mode))
return 0;
 


-- 
Thomas Rast
t...@thomasrast.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: git gc --aggressive led to about 40 times slower "git log --raw"

2014-02-22 Thread Andreas Schwab
David Kastrup  writes:

> That does look strange: Emacs has a history of more than 30 years.  But
> the Git mirror is quite younger.  Maybe one needs to make sure to use
> the author date rather than the commit date here?

There is no difference between commit and author date in the Emacs git
mirror since bzr doesn't keep that distinction (and cvs didn't either).

Andreas.

-- 
Andreas Schwab, sch...@linux-m68k.org
GPG Key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5
"And now for something completely different."
--
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 2/8] merge-recursive: internal flag to avoid touching the worktree

2014-02-22 Thread Thomas Rast
From: Thomas Rast 

o->call_depth has a double function: a nonzero call_depth means we
want to construct virtual merge bases, but it also means we want to
avoid touching the worktree.  Introduce a new flag o->no_worktree to
trigger only the latter.

Signed-off-by: Thomas Rast 
Signed-off-by: Junio C Hamano 
---
 merge-recursive.c | 37 +
 merge-recursive.h |  1 +
 2 files changed, 22 insertions(+), 16 deletions(-)

diff --git a/merge-recursive.c b/merge-recursive.c
index c36dc79..35be144 100644
--- a/merge-recursive.c
+++ b/merge-recursive.c
@@ -408,10 +408,10 @@ static void record_df_conflict_files(struct merge_options 
*o,
int i;
 
/*
-* If we're merging merge-bases, we don't want to bother with
-* any working directory changes.
+* If we're working in-core only (e.g., merging merge-bases),
+* we don't want to bother with any working directory changes.
 */
-   if (o->call_depth)
+   if (o->call_depth || o->no_worktree)
return;
 
/* Ensure D/F conflicts are adjacent in the entries list. */
@@ -724,7 +724,7 @@ static void update_file_flags(struct merge_options *o,
  int update_cache,
  int update_wd)
 {
-   if (o->call_depth)
+   if (o->call_depth || o->no_worktree)
update_wd = 0;
 
if (update_wd) {
@@ -931,7 +931,8 @@ static struct merge_file_info merge_file_1(struct 
merge_options *o,
result.clean = merge_submodule(result.sha,
   one->path, one->sha1,
   a->sha1, b->sha1,
-  !o->call_depth);
+  !(o->call_depth ||
+o->no_worktree));
} else if (S_ISLNK(a->mode)) {
hashcpy(result.sha, a->sha1);
 
@@ -1003,7 +1004,7 @@ static void handle_change_delete(struct merge_options *o,
 const char *change, const char *change_past)
 {
char *renamed = NULL;
-   if (dir_in_way(path, !o->call_depth)) {
+   if (dir_in_way(path, !(o->call_depth || o->no_worktree))) {
renamed = unique_path(o, path, a_sha ? o->branch1 : o->branch2);
}
 
@@ -1128,10 +1129,10 @@ static void handle_file(struct merge_options *o,
char *add_name = unique_path(o, rename->path, other_branch);
update_file(o, 0, add->sha1, add->mode, add_name);
 
-   remove_file(o, 0, rename->path, 0);
+   remove_file(o, 0, rename->path, o->call_depth || 
o->no_worktree);
dst_name = unique_path(o, rename->path, cur_branch);
} else {
-   if (dir_in_way(rename->path, !o->call_depth)) {
+   if (dir_in_way(rename->path, !(o->call_depth || 
o->no_worktree))) {
dst_name = unique_path(o, rename->path, cur_branch);
output(o, 1, _("%s is a directory in %s adding as %s 
instead"),
   rename->path, other_branch, dst_name);
@@ -1238,7 +1239,7 @@ static void conflict_rename_rename_2to1(struct 
merge_options *o,
 * merge base just undo the renames; they can be detected
 * again later for the non-recursive merge.
 */
-   remove_file(o, 0, path, 0);
+   remove_file(o, 0, path, o->call_depth || o->no_worktree);
update_file(o, 0, mfi_c1.sha, mfi_c1.mode, a->path);
update_file(o, 0, mfi_c2.sha, mfi_c2.mode, b->path);
} else {
@@ -1246,7 +1247,7 @@ static void conflict_rename_rename_2to1(struct 
merge_options *o,
char *new_path2 = unique_path(o, path, ci->branch2);
output(o, 1, _("Renaming %s to %s and %s to %s instead"),
   a->path, new_path1, b->path, new_path2);
-   remove_file(o, 0, path, 0);
+   remove_file(o, 0, path, o->call_depth || o->no_worktree);
update_file(o, 0, mfi_c1.sha, mfi_c1.mode, new_path1);
update_file(o, 0, mfi_c2.sha, mfi_c2.mode, new_path2);
free(new_path2);
@@ -1405,6 +1406,7 @@ static int process_renames(struct merge_options *o,
 * add-source case).
 */
remove_file(o, 1, ren1_src,
+   o->call_depth || o->no_worktree ||
renamed_stage == 2 || 
!was_tracked(ren1_src));
 
hashcpy(src_other.sha1, 
ren1->src_entry->stages[other_stage].sha);
@@ -1601,7 +1603,7 @@ static int merge_content(struct merge_options *o,
 o->branch2 == rename_conflict_info->branch1) ?

[PATCH v2 3/8] merge-recursive: -Xindex-only to leave worktree unchanged

2014-02-22 Thread Thomas Rast
From: Thomas Rast 

Using the new no_worktree flag from the previous commit, we can teach
merge-recursive to leave the worktree untouched.  Expose this with a
new strategy option so that scripts can use it.

Signed-off-by: Junio C Hamano 
---
 Documentation/merge-strategies.txt |  4 
 merge-recursive.c  |  2 ++
 t/t3030-merge-recursive.sh | 13 +
 3 files changed, 19 insertions(+)

diff --git a/Documentation/merge-strategies.txt 
b/Documentation/merge-strategies.txt
index fb6e593..2934e99 100644
--- a/Documentation/merge-strategies.txt
+++ b/Documentation/merge-strategies.txt
@@ -92,6 +92,10 @@ subtree[=];;
is prefixed (or stripped from the beginning) to make the shape of
two trees to match.
 
+index-only;;
+   Write the merge result only to the index; do not touch the
+   worktree.
+
 octopus::
This resolves cases with more than two heads, but refuses to do
a complex merge that needs manual resolution.  It is
diff --git a/merge-recursive.c b/merge-recursive.c
index 35be144..f59c1d3 100644
--- a/merge-recursive.c
+++ b/merge-recursive.c
@@ -2096,6 +2096,8 @@ int parse_merge_opt(struct merge_options *o, const char 
*s)
if ((o->rename_score = parse_rename_score(&score)) == -1 || 
*score != 0)
return -1;
}
+   else if (!strcmp(s, "index-only"))
+   o->no_worktree = 1;
else
return -1;
return 0;
diff --git a/t/t3030-merge-recursive.sh b/t/t3030-merge-recursive.sh
index 2f96100..2f3a16c 100755
--- a/t/t3030-merge-recursive.sh
+++ b/t/t3030-merge-recursive.sh
@@ -296,6 +296,19 @@ test_expect_success 'merge-recursive result' '
 
 '
 
+test_expect_success 'merge-recursive --index-only' '
+
+   rm -fr [abcd] &&
+   git checkout -f "$c2" &&
+   test_expect_code 1 git merge-recursive --index-only "$c0" -- "$c2" 
"$c1" &&
+   git ls-files -s >actual &&
+   # reuses "expected" from previous test!
+   test_cmp expected actual &&
+   git diff HEAD >actual-diff &&
+   : >expected-diff &&
+   test_cmp expected-diff actual-diff
+'
+
 test_expect_success 'fail if the index has unresolved entries' '
 
rm -fr [abcd] &&
-- 
1.9.0.313.g3d0a325

--
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 4/8] combine-diff: do not pass revs->dense_combined_merges redundantly

2014-02-22 Thread Thomas Rast
The existing code passed revs->dense_combined_merges along revs itself
into the combine-diff functions, which is rather redundant.  Remove
the 'dense' argument until much further down the callchain to simplify
callers.

Note that while the caller in submodule.c needs to do extra work now,
the next commit will simplify this to a single setting again.

Signed-off-by: Thomas Rast 
---
 builtin/diff.c |  3 +--
 combine-diff.c | 13 ++---
 diff-lib.c |  6 ++
 diff.h |  6 +++---
 log-tree.c |  2 +-
 submodule.c|  5 -
 6 files changed, 17 insertions(+), 18 deletions(-)

diff --git a/builtin/diff.c b/builtin/diff.c
index 0f247d2..47f663b 100644
--- a/builtin/diff.c
+++ b/builtin/diff.c
@@ -196,8 +196,7 @@ static int builtin_diff_combined(struct rev_info *revs,
revs->dense_combined_merges = revs->combine_merges = 1;
for (i = 1; i < ents; i++)
sha1_array_append(&parents, ent[i].item->sha1);
-   diff_tree_combined(ent[0].item->sha1, &parents,
-  revs->dense_combined_merges, revs);
+   diff_tree_combined(ent[0].item->sha1, &parents, revs);
sha1_array_clear(&parents);
return 0;
 }
diff --git a/combine-diff.c b/combine-diff.c
index 3b92c448..6e80a73 100644
--- a/combine-diff.c
+++ b/combine-diff.c
@@ -952,7 +952,7 @@ static void show_combined_header(struct combine_diff_path 
*elem,
 }
 
 static void show_patch_diff(struct combine_diff_path *elem, int num_parent,
-   int dense, int working_tree_file,
+   int working_tree_file,
struct rev_info *rev)
 {
struct diff_options *opt = &rev->diffopt;
@@ -967,6 +967,7 @@ static void show_patch_diff(struct combine_diff_path *elem, 
int num_parent,
struct userdiff_driver *textconv = NULL;
int is_binary;
const char *line_prefix = diff_line_prefix(opt);
+   int dense = rev->dense_combined_merges;
 
context = opt->context;
userdiff = userdiff_find_by_path(elem->path);
@@ -1214,7 +1215,6 @@ static void show_raw_diff(struct combine_diff_path *p, 
int num_parent, struct re
  */
 void show_combined_diff(struct combine_diff_path *p,
   int num_parent,
-  int dense,
   struct rev_info *rev)
 {
struct diff_options *opt = &rev->diffopt;
@@ -1226,7 +1226,7 @@ void show_combined_diff(struct combine_diff_path *p,
  DIFF_FORMAT_NAME_STATUS))
show_raw_diff(p, num_parent, rev);
else if (opt->output_format & DIFF_FORMAT_PATCH)
-   show_patch_diff(p, num_parent, dense, 1, rev);
+   show_patch_diff(p, num_parent, 1, rev);
 }
 
 static void free_combined_pair(struct diff_filepair *pair)
@@ -1297,7 +1297,6 @@ static void handle_combined_callback(struct diff_options 
*opt,
 
 void diff_tree_combined(const unsigned char *sha1,
const struct sha1_array *parents,
-   int dense,
struct rev_info *rev)
 {
struct diff_options *opt = &rev->diffopt;
@@ -1365,7 +1364,7 @@ void diff_tree_combined(const unsigned char *sha1,
   opt->line_termination);
for (p = paths; p; p = p->next) {
if (p->len)
-   show_patch_diff(p, num_parent, dense,
+   show_patch_diff(p, num_parent,
0, rev);
}
}
@@ -1381,7 +1380,7 @@ void diff_tree_combined(const unsigned char *sha1,
free_pathspec(&diffopts.pathspec);
 }
 
-void diff_tree_combined_merge(const struct commit *commit, int dense,
+void diff_tree_combined_merge(const struct commit *commit,
  struct rev_info *rev)
 {
struct commit_list *parent = get_saved_parents(rev, commit);
@@ -1391,6 +1390,6 @@ void diff_tree_combined_merge(const struct commit 
*commit, int dense,
sha1_array_append(&parents, parent->item->object.sha1);
parent = parent->next;
}
-   diff_tree_combined(commit->object.sha1, &parents, dense, rev);
+   diff_tree_combined(commit->object.sha1, &parents, rev);
sha1_array_clear(&parents);
 }
diff --git a/diff-lib.c b/diff-lib.c
index 346cac6..8d0f572 100644
--- a/diff-lib.c
+++ b/diff-lib.c
@@ -174,9 +174,7 @@ int run_diff_files(struct rev_info *revs, unsigned int 
option)
i--;
 
if (revs->combine_merges && num_compare_stages == 2) {
-   show_combined_diff(dpath, 2,
-  revs->dense_combined_merges,
-  revs);
+   show_combined_diff(dpath, 2, revs);

[PATCH v2 1/8] merge-recursive: remove dead conditional in update_stages()

2014-02-22 Thread Thomas Rast
From: Thomas Rast 

650467c (merge-recursive: Consolidate different update_stages
functions, 2011-08-11) changed the former argument 'clear' to always
be true.  Remove the useless conditional.

Signed-off-by: Thomas Rast 
Signed-off-by: Junio C Hamano 
---
 merge-recursive.c | 6 ++
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/merge-recursive.c b/merge-recursive.c
index 8400a8e..c36dc79 100644
--- a/merge-recursive.c
+++ b/merge-recursive.c
@@ -545,11 +545,9 @@ static int update_stages(const char *path, const struct 
diff_filespec *o,
 * would_lose_untracked).  Instead, reverse the order of the calls
 * (executing update_file first and then update_stages).
 */
-   int clear = 1;
int options = ADD_CACHE_OK_TO_ADD | ADD_CACHE_SKIP_DFCHECK;
-   if (clear)
-   if (remove_file_from_cache(path))
-   return -1;
+   if (remove_file_from_cache(path))
+   return -1;
if (o)
if (add_cacheinfo(o->mode, o->sha1, path, 1, 0, options))
return -1;
-- 
1.9.0.313.g3d0a325

--
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 6/8] merge-recursive: allow storing conflict hunks in index

2014-02-22 Thread Thomas Rast
Add a --conflicts-in-index option to merge-recursive, which instructs
it to always store the 3-way merged result in the index.  (Normally it
only does so in recursive invocations, but not for the final result.)

This serves as a building block for the "remerge diff" feature coming
up in a subsequent patch.  The external option lets us easily use it
from tests, where we'd otherwise need a new test-* helper to access
the feature.

Furthermore, it might occasionally be useful for scripts that want to
look at the result of invoking git-merge without tampering with the
worktree.  They could already get the _conflicts_ with --index-only,
but not (conveniently) the conflict-hunk formatted files that would
normally be written to the worktree.

Signed-off-by: Thomas Rast 
---
 Documentation/merge-strategies.txt |  5 +
 merge-recursive.c  |  4 
 merge-recursive.h  |  1 +
 t/t3030-merge-recursive.sh | 20 
 4 files changed, 30 insertions(+)

diff --git a/Documentation/merge-strategies.txt 
b/Documentation/merge-strategies.txt
index 2934e99..3468d99 100644
--- a/Documentation/merge-strategies.txt
+++ b/Documentation/merge-strategies.txt
@@ -96,6 +96,11 @@ index-only;;
Write the merge result only to the index; do not touch the
worktree.
 
+conflicts-in-index;;
+   For conflicted files, write 3-way merged contents with
+   conflict hunks to the index, instead of leaving their entries
+   unresolved.
+
 octopus::
This resolves cases with more than two heads, but refuses to do
a complex merge that needs manual resolution.  It is
diff --git a/merge-recursive.c b/merge-recursive.c
index f59c1d3..b682812 100644
--- a/merge-recursive.c
+++ b/merge-recursive.c
@@ -724,6 +724,8 @@ static void update_file_flags(struct merge_options *o,
  int update_cache,
  int update_wd)
 {
+   if (o->conflicts_in_index)
+   update_cache = 1;
if (o->call_depth || o->no_worktree)
update_wd = 0;
 
@@ -2098,6 +2100,8 @@ int parse_merge_opt(struct merge_options *o, const char 
*s)
}
else if (!strcmp(s, "index-only"))
o->no_worktree = 1;
+   else if (!strcmp(s, "conflicts-in-index"))
+   o->conflicts_in_index = 1;
else
return -1;
return 0;
diff --git a/merge-recursive.h b/merge-recursive.h
index d8dd7a1..9b8e20b 100644
--- a/merge-recursive.h
+++ b/merge-recursive.h
@@ -16,6 +16,7 @@ struct merge_options {
unsigned buffer_output : 1;
unsigned renormalize : 1;
unsigned no_worktree : 1; /* do not touch worktree */
+   unsigned conflicts_in_index : 1; /* index will contain conflict hunks */
long xdl_opts;
int verbosity;
int diff_rename_limit;
diff --git a/t/t3030-merge-recursive.sh b/t/t3030-merge-recursive.sh
index 2f3a16c..4192fd3 100755
--- a/t/t3030-merge-recursive.sh
+++ b/t/t3030-merge-recursive.sh
@@ -309,6 +309,26 @@ test_expect_success 'merge-recursive --index-only' '
test_cmp expected-diff actual-diff
 '
 
+test_expect_success 'merge-recursive --index-only --conflicts-in-index' '
+   # first pass: do a merge as usual to obtain "expected"
+   rm -fr [abcd] &&
+   git checkout -f "$c2" &&
+   test_expect_code 1 git merge-recursive "$c0" -- "$c2" "$c1" &&
+   git add [abcd] &&
+   git ls-files -s >expected &&
+   # second pass: actual test
+   rm -fr [abcd] &&
+   git checkout -f "$c2" &&
+   test_expect_code 1 \
+   git merge-recursive --index-only --conflicts-in-index \
+   "$c0" -- "$c2" "$c1" &&
+   git ls-files -s >actual &&
+   test_cmp expected actual &&
+   git diff HEAD >actual-diff &&
+   : >expected-diff &&
+   test_cmp expected-diff actual-diff
+'
+
 test_expect_success 'fail if the index has unresolved entries' '
 
rm -fr [abcd] &&
-- 
1.9.0.313.g3d0a325

--
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 5/8] Fold all merge diff variants into an enum

2014-02-22 Thread Thomas Rast
The four ways of displaying merge diffs,

* none: no diff
* -m: against each parent
* -c: combined
* --cc: combined-condensed

were encoded in three flag bits in struct rev_info.  Fold them all
into a single enum field that captures the variants.

This makes it easier to add new merge diff variants without yet more
special casing.  It should also be slightly easier to read because one
does not have to ensure that the flag bits are set in an expected
combination.

Signed-off-by: Thomas Rast 
---
 builtin/diff-files.c|  5 +++--
 builtin/diff-tree.c |  2 +-
 builtin/diff.c  |  9 +
 builtin/fmt-merge-msg.c |  2 +-
 builtin/log.c   |  9 -
 builtin/merge.c |  1 -
 combine-diff.c  |  2 +-
 diff-lib.c  |  7 ---
 log-tree.c  |  4 ++--
 revision.c  | 13 +++--
 revision.h  | 22 +++---
 submodule.c |  4 +---
 12 files changed, 44 insertions(+), 36 deletions(-)

diff --git a/builtin/diff-files.c b/builtin/diff-files.c
index 9200069..172b50d 100644
--- a/builtin/diff-files.c
+++ b/builtin/diff-files.c
@@ -57,9 +57,10 @@ int cmd_diff_files(int argc, const char **argv, const char 
*prefix)
 * was not asked to.  "diff-files -c -p" should not densify
 * (the user should ask with "diff-files --cc" explicitly).
 */
-   if (rev.max_count == -1 && !rev.combine_merges &&
+   if (rev.max_count == -1 &&
+   !merge_diff_mode_is_any_combined(&rev) &&
(rev.diffopt.output_format & DIFF_FORMAT_PATCH))
-   rev.combine_merges = rev.dense_combined_merges = 1;
+   rev.merge_diff_mode = MERGE_DIFF_COMBINED_CONDENSED;
 
if (read_cache_preload(&rev.diffopt.pathspec) < 0) {
perror("read_cache_preload");
diff --git a/builtin/diff-tree.c b/builtin/diff-tree.c
index be6417d..2950f80 100644
--- a/builtin/diff-tree.c
+++ b/builtin/diff-tree.c
@@ -96,7 +96,7 @@ static int diff_tree_stdin(char *line)
 static void diff_tree_tweak_rev(struct rev_info *rev, struct 
setup_revision_opt *opt)
 {
if (!rev->diffopt.output_format) {
-   if (rev->dense_combined_merges)
+   if (rev->merge_diff_mode == MERGE_DIFF_COMBINED_CONDENSED)
rev->diffopt.output_format = DIFF_FORMAT_PATCH;
else
rev->diffopt.output_format = DIFF_FORMAT_RAW;
diff --git a/builtin/diff.c b/builtin/diff.c
index 47f663b..fd4c75f 100644
--- a/builtin/diff.c
+++ b/builtin/diff.c
@@ -192,8 +192,8 @@ static int builtin_diff_combined(struct rev_info *revs,
if (argc > 1)
usage(builtin_diff_usage);
 
-   if (!revs->dense_combined_merges && !revs->combine_merges)
-   revs->dense_combined_merges = revs->combine_merges = 1;
+   if (!merge_diff_mode_is_any_combined(revs))
+   revs->merge_diff_mode = MERGE_DIFF_COMBINED_CONDENSED;
for (i = 1; i < ents; i++)
sha1_array_append(&parents, ent[i].item->sha1);
diff_tree_combined(ent[0].item->sha1, &parents, revs);
@@ -242,9 +242,10 @@ static int builtin_diff_files(struct rev_info *revs, int 
argc, const char **argv
 * dense one, --cc can be explicitly asked for, or just rely
 * on the default).
 */
-   if (revs->max_count == -1 && !revs->combine_merges &&
+   if (revs->max_count == -1 &&
+   !merge_diff_mode_is_any_combined(revs) &&
(revs->diffopt.output_format & DIFF_FORMAT_PATCH))
-   revs->combine_merges = revs->dense_combined_merges = 1;
+   revs->merge_diff_mode = MERGE_DIFF_COMBINED_CONDENSED;
 
setup_work_tree();
if (read_cache_preload(&revs->diffopt.pathspec) < 0) {
diff --git a/builtin/fmt-merge-msg.c b/builtin/fmt-merge-msg.c
index 3906eda..2deeacd 100644
--- a/builtin/fmt-merge-msg.c
+++ b/builtin/fmt-merge-msg.c
@@ -637,7 +637,7 @@ int fmt_merge_msg(struct strbuf *in, struct strbuf *out,
head = lookup_commit_or_die(head_sha1, "HEAD");
init_revisions(&rev, NULL);
rev.commit_format = CMIT_FMT_ONELINE;
-   rev.ignore_merges = 1;
+   rev.merge_diff_mode = MERGE_DIFF_IGNORE;
rev.limited = 1;
 
strbuf_complete_line(out);
diff --git a/builtin/log.c b/builtin/log.c
index b97373d..cebebea 100644
--- a/builtin/log.c
+++ b/builtin/log.c
@@ -499,13 +499,12 @@ static int show_tree_object(const unsigned char *sha1,
 
 static void show_rev_tweak_rev(struct rev_info *rev, struct setup_revision_opt 
*opt)
 {
-   if (rev->ignore_merges) {
+   if (!rev->merge_diff_mode) {
/* There was no "-m" on the command line */
-   rev->ignore_merges = 0;
-   if (!rev->first_parent_only && !rev->combine_merges) {
+   rev->merge_diff_mode = MERGE_DIFF_EACH;
+   if (!rev->first_parent_only) {

[PATCH v2 8/8] log --remerge-diff: show what the conflict resolution changed

2014-02-22 Thread Thomas Rast
Git has --cc as a very fast inspection tool that shows a brief summary
of what a conflicted merge "looks like", and -c/-m as "give me the
full information" data dumps.

But --cc actually loses information: if the merge lost(!) some changes
from one side, that hunk would fully agree with the other side, and
therefore be elided.  So --cc cannot be used to investigate mismerges.
Indeed it is rather hard to find a merge that has lost changes, unless
one knows where to look.

The new option --remerge-diff is an attempt at filling this gap,
admittedly at the cost of a lot of CPU cycles.  For each merge commit,
it diffs the merge result against a recursive merge of the merge's
parents.

For files that can be auto-merged cleanly, it will typically show
nothing.  However, it will make it obvious when the merge introduces
extra changes.

For files that result in merge conflicts, we diff against the
representation with conflict hunks (what the user would usually see in
the worktree).  So the diff will show what was changed in the conflict
hunks to resolve the conflict.

It still takes a bit of staring to tell an evil from a regular merge.
But at least the information is there, unlike with --cc; and the
output is usually much shorter than with -c.

Signed-off-by: Thomas Rast 
---
 Documentation/rev-list-options.txt |   7 +
 log-tree.c | 298 +
 merge-recursive.c  |   3 +-
 merge-recursive.h  |   1 +
 revision.c |   2 +
 revision.h |   4 +-
 t/t4213-log-remerge-diff.sh| 222 +++
 7 files changed, 535 insertions(+), 2 deletions(-)
 create mode 100755 t/t4213-log-remerge-diff.sh

diff --git a/Documentation/rev-list-options.txt 
b/Documentation/rev-list-options.txt
index 03533af..73264dc 100644
--- a/Documentation/rev-list-options.txt
+++ b/Documentation/rev-list-options.txt
@@ -790,6 +790,13 @@ options may be given. See linkgit:git-diff-files[1] for 
more options.
in that case, the output represents the changes the merge
brought _into_ the then-current branch.
 
+--remerge-diff::
+   Diff merge commits against a recursive merge of their parents,
+   with conflict hunks.  Intuitively speaking, this shows what
+   the author of the merge changed to resolve the merge.  It
+   assumes that all (or most) merges are recursive merges; other
+   strategies are not supported.
+
 -r::
Show recursive diffs.
 
diff --git a/log-tree.c b/log-tree.c
index 30b3063..9b831e9 100644
--- a/log-tree.c
+++ b/log-tree.c
@@ -11,6 +11,8 @@
 #include "gpg-interface.h"
 #include "sequencer.h"
 #include "line-log.h"
+#include "cache-tree.h"
+#include "merge-recursive.h"
 
 struct decoration name_decoration = { "object names" };
 
@@ -723,6 +725,300 @@ static int do_diff_combined(struct rev_info *opt, struct 
commit *commit)
 }
 
 /*
+ * Helpers for make_asymmetric_conflict_entries() below.
+ */
+static char *load_cache_entry_blob(struct cache_entry *entry,
+  unsigned long *size)
+{
+   enum object_type type;
+   void *data;
+
+   if (!entry)
+   return NULL;
+
+   data = read_sha1_file(entry->sha1, &type, size);
+   if (type != OBJ_BLOB)
+   die("BUG: load_cache_entry_blob for non-blob");
+
+   return data;
+}
+
+static void strbuf_append_cache_entry_blob(struct strbuf *sb,
+  struct cache_entry *entry)
+{
+   unsigned long size;
+   char *data = load_cache_entry_blob(entry, &size);;
+
+   if (!data)
+   return;
+
+   strbuf_add(sb, data, size);
+   free(data);
+}
+
+static void assemble_conflict_entry(struct strbuf *sb,
+   const char *branch1,
+   const char *branch2,
+   struct cache_entry *entry1,
+   struct cache_entry *entry2)
+{
+   strbuf_addf(sb, "<<< %s\n", branch1);
+   strbuf_append_cache_entry_blob(sb, entry1);
+   strbuf_addstr(sb, "===\n");
+   strbuf_append_cache_entry_blob(sb, entry2);
+   strbuf_addf(sb, ">>> %s\n", branch2);
+}
+
+/*
+ * For --remerge-diff, we need conflicted (<<< ... >>>)
+ * representations of as many conflicts as possible.  Default conflict
+ * generation only applies to files that have all three stages.
+ *
+ * This function generates conflict hunk representations for files
+ * that have only one of stage 2 or 3.  The corresponding side in the
+ * conflict hunk format will be empty.  A stage 1, if any, will be
+ * dropped in the process.
+ */
+static void make_asymmetric_conflict_entries(const char *branch1,
+const char *branch2)
+{
+   int o = 0, i = 0;
+
+   /*
+* NEEDSWORK: we trample all over the cache below, so we need
+

[PATCH v2 7/8] name-hash: allow dir hashing even when !ignore_case

2014-02-22 Thread Thomas Rast
The directory hash (for fast checks if the index already has a
directory) was only used in ignore_case mode and so depended on that
flag.

Make it generally available on request.

Signed-off-by: Thomas Rast 
---
 cache.h |  2 ++
 name-hash.c | 19 ---
 2 files changed, 14 insertions(+), 7 deletions(-)

diff --git a/cache.h b/cache.h
index dc040fb..e162021 100644
--- a/cache.h
+++ b/cache.h
@@ -276,6 +276,7 @@ struct index_state {
struct cache_tree *cache_tree;
struct cache_time timestamp;
unsigned name_hash_initialized : 1,
+has_dir_hash : 1,
 initialized : 1;
struct hash_table name_hash;
struct hash_table dir_hash;
@@ -284,6 +285,7 @@ struct index_state {
 extern struct index_state the_index;
 
 /* Name hashing */
+extern void init_name_hash(struct index_state *istate, int force_dir_hash);
 extern void add_name_hash(struct index_state *istate, struct cache_entry *ce);
 extern void remove_name_hash(struct index_state *istate, struct cache_entry 
*ce);
 extern void free_name_hash(struct index_state *istate);
diff --git a/name-hash.c b/name-hash.c
index e5b6e1a..c8953be 100644
--- a/name-hash.c
+++ b/name-hash.c
@@ -141,16 +141,19 @@ static void hash_index_entry(struct index_state *istate, 
struct cache_entry *ce)
*pos = ce;
}
 
-   if (ignore_case && !(ce->ce_flags & CE_UNHASHED))
+   if (istate->has_dir_hash && !(ce->ce_flags & CE_UNHASHED))
add_dir_entry(istate, ce);
 }
 
-static void lazy_init_name_hash(struct index_state *istate)
+void init_name_hash(struct index_state *istate, int force_dir_hash)
 {
int nr;
 
if (istate->name_hash_initialized)
return;
+
+   istate->has_dir_hash = force_dir_hash || ignore_case;
+
if (istate->cache_nr)
preallocate_hash(&istate->name_hash, istate->cache_nr);
for (nr = 0; nr < istate->cache_nr; nr++)
@@ -161,7 +164,7 @@ static void lazy_init_name_hash(struct index_state *istate)
 void add_name_hash(struct index_state *istate, struct cache_entry *ce)
 {
/* if already hashed, add reference to directory entries */
-   if (ignore_case && (ce->ce_flags & CE_STATE_MASK) == CE_STATE_MASK)
+   if (istate->has_dir_hash && (ce->ce_flags & CE_STATE_MASK) == 
CE_STATE_MASK)
add_dir_entry(istate, ce);
 
ce->ce_flags &= ~CE_UNHASHED;
@@ -181,7 +184,7 @@ void add_name_hash(struct index_state *istate, struct 
cache_entry *ce)
 void remove_name_hash(struct index_state *istate, struct cache_entry *ce)
 {
/* if already hashed, release reference to directory entries */
-   if (ignore_case && (ce->ce_flags & CE_STATE_MASK) == CE_HASHED)
+   if (istate->has_dir_hash && (ce->ce_flags & CE_STATE_MASK) == CE_HASHED)
remove_dir_entry(istate, ce);
 
ce->ce_flags |= CE_UNHASHED;
@@ -228,7 +231,7 @@ struct cache_entry *index_dir_exists(struct index_state 
*istate, const char *nam
struct cache_entry *ce;
struct dir_entry *dir;
 
-   lazy_init_name_hash(istate);
+   init_name_hash(istate, 0);
dir = find_dir_entry(istate, name, namelen);
if (dir && dir->nr)
return dir->ce;
@@ -250,7 +253,7 @@ struct cache_entry *index_file_exists(struct index_state 
*istate, const char *na
unsigned int hash = hash_name(name, namelen);
struct cache_entry *ce;
 
-   lazy_init_name_hash(istate);
+   init_name_hash(istate, 0);
ce = lookup_hash(hash, &istate->name_hash);
 
while (ce) {
@@ -286,9 +289,11 @@ void free_name_hash(struct index_state *istate)
if (!istate->name_hash_initialized)
return;
istate->name_hash_initialized = 0;
-   if (ignore_case)
+   if (istate->has_dir_hash) {
/* free directory entries */
for_each_hash(&istate->dir_hash, free_dir_entry, NULL);
+   istate->has_dir_hash = 0;
+   }
 
free_hash(&istate->name_hash);
free_hash(&istate->dir_hash);
-- 
1.9.0.313.g3d0a325

--
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 0/8] log --remerge-diff

2014-02-22 Thread Thomas Rast
This is the second iteration of

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

Changes since the last version:

* Dropped patches 4 and 5 (log --merge-bases)

* Implemented the "full-file conflict" scheme explained in the
  previous cover letter: if the conflicted version is lacking one
  stage of a file, it synthesizes a conflict file of the form

<<<
===
content of the stage that exists
>>>

  (or the other way around if stage3 is missing).  This occurs at
  least with delete/modify conflicts.

* Implemented some basic handling of directory/file conflicts.  I'm
  not completely happy yet -- see the NEEDSWORK comments -- but at
  least it gives consistent input to the diffing stage.

  This required access to the dir hash, so there's a new patch 7 that
  makes this possible.

Patches 1-6 (used to be 1-3 and 6-8) are unchanged.


Thomas Rast (8):
  merge-recursive: remove dead conditional in update_stages()
  merge-recursive: internal flag to avoid touching the worktree
  merge-recursive: -Xindex-only to leave worktree unchanged
  combine-diff: do not pass revs->dense_combined_merges redundantly
  Fold all merge diff variants into an enum
  merge-recursive: allow storing conflict hunks in index
  name-hash: allow dir hashing even when !ignore_case
  log --remerge-diff: show what the conflict resolution changed

 Documentation/merge-strategies.txt |   9 ++
 Documentation/rev-list-options.txt |   7 +
 builtin/diff-files.c   |   5 +-
 builtin/diff-tree.c|   2 +-
 builtin/diff.c |  12 +-
 builtin/fmt-merge-msg.c|   2 +-
 builtin/log.c  |   9 +-
 builtin/merge.c|   1 -
 cache.h|   2 +
 combine-diff.c |  13 +-
 diff-lib.c |  13 +-
 diff.h |   6 +-
 log-tree.c | 304 -
 merge-recursive.c  |  52 ---
 merge-recursive.h  |   3 +
 name-hash.c|  19 ++-
 revision.c |  15 +-
 revision.h |  24 ++-
 submodule.c|   3 +-
 t/t3030-merge-recursive.sh |  33 
 t/t4213-log-remerge-diff.sh| 222 +++
 21 files changed, 678 insertions(+), 78 deletions(-)
 create mode 100755 t/t4213-log-remerge-diff.sh

-- 
1.9.0.313.g3d0a325

--
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: git gc --aggressive led to about 40 times slower "git log --raw"

2014-02-22 Thread Duy Nguyen
On Sat, Feb 22, 2014 at 3:53 PM, David Kastrup  wrote:
> David Kastrup  writes:
>
>> Duy Nguyen  writes:
>>
>>> OK with git://git.savannah.gnu.org/emacs.git we have
>>>
>>>  - a 209MB pack with --aggressive
>>>  - 1.3GB with --depth=50
>>>  - 1.3GB with --window=4000 --depth=32
>>>  - 1.3GB with --depth=20
>>>  - 821MB with --depth=250 for commits --before=2.years.ago, --depth=50
>>> for the rest
>>>
>>> So I don't think we should go with your following patch because the
>>> size explosion is just too much no matter how faster it could be. An
>>> immediate action could be just make --depth=250 configurable and let
>>> people deal with it. A better option is something like "3 repack
>>> steps" you described where we pack deep depth first, mark .keep, pack
>>> shallower depth and combine them all into one.
>>>
>>> I'm not really happy with --depth=250 producing 209MB while
>>> --depth=250 --before=2.year.ago a 800MB pack. It looks wrong (or maybe
>>> I did something wrong)
>>
>> That does look strange: Emacs has a history of more than 30 years.  But
>> the Git mirror is quite younger.  Maybe one needs to make sure to use
>> the author date rather than the commit date here?

I think commit date is fine because it covers a large portion of
objects (649946 per total 739990) and it does not (or should not)
affect object ordering in pack-objects/rev-list.

> Another thing: did you really use --depth=250 here or did you use
> --aggressive?  It may be that the latter also sets other options?

I can't use --aggressive because I need to feed revisions directly to
pack-objects. --aggressive also sets --window=250. Thanks for
checking. My machine will have another workout session.
-- 
Duy
--
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] tag: support --sort=version

2014-02-22 Thread Duy Nguyen
On Sat, Feb 22, 2014 at 2:59 PM, Jeff King  wrote:
> On Fri, Feb 21, 2014 at 06:58:16PM +0700, Duy Nguyen wrote:
>
>> >   --sort=[-][comparison:]field
>> [...]
>> Why not reversed order? So its syntax could be
>>
>> [ "-" ] FIELD [ ":" [ "version" | "v" ] ]
>>
>> It fits better to current f-e-r syntax where modifiers are after the
>> colon. And it avoids the possibility that someone adds field "version"
>> and we can't tell what "version" is what.
>
> I find my version a bit more obvious, for two reasons:
>
>   1. "version" here is not a modifier of the field name, it is a
>  modifier of the sort. You cannot use it in non-sort contexts (like
>  --format), and you cannot order it like other modifiers (you cannot
>  say "refname:version:short", only "refname:short:version").

Or you can read it like "type cast this field as a version", where
sorting is affected but formatting, not so much. So you can specify it
with --format (but it's no-op, unless we find a fancy way to color
versions). I don't see a problem with accepting both
refname:version:short and refname:short:version in future for-each-ref
either. It will be the first time we accept multiple modifiers though.

>   2. There are actually two sort-modifiers: "-" for ordering, and then a
>  comparator. In your proposal, they are split, whereas in mine, they
>  are next to each other.
-- 
Duy
--
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: git gc --aggressive led to about 40 times slower "git log --raw"

2014-02-22 Thread David Kastrup
David Kastrup  writes:

> Duy Nguyen  writes:
>
>> OK with git://git.savannah.gnu.org/emacs.git we have
>>
>>  - a 209MB pack with --aggressive
>>  - 1.3GB with --depth=50
>>  - 1.3GB with --window=4000 --depth=32
>>  - 1.3GB with --depth=20
>>  - 821MB with --depth=250 for commits --before=2.years.ago, --depth=50
>> for the rest
>>
>> So I don't think we should go with your following patch because the
>> size explosion is just too much no matter how faster it could be. An
>> immediate action could be just make --depth=250 configurable and let
>> people deal with it. A better option is something like "3 repack
>> steps" you described where we pack deep depth first, mark .keep, pack
>> shallower depth and combine them all into one.
>>
>> I'm not really happy with --depth=250 producing 209MB while
>> --depth=250 --before=2.year.ago a 800MB pack. It looks wrong (or maybe
>> I did something wrong)
>
> That does look strange: Emacs has a history of more than 30 years.  But
> the Git mirror is quite younger.  Maybe one needs to make sure to use
> the author date rather than the commit date here?

Another thing: did you really use --depth=250 here or did you use
--aggressive?  It may be that the latter also sets other options?

-- 
David Kastrup
--
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: git gc --aggressive led to about 40 times slower "git log --raw"

2014-02-22 Thread David Kastrup
Duy Nguyen  writes:

> OK with git://git.savannah.gnu.org/emacs.git we have
>
>  - a 209MB pack with --aggressive
>  - 1.3GB with --depth=50
>  - 1.3GB with --window=4000 --depth=32
>  - 1.3GB with --depth=20
>  - 821MB with --depth=250 for commits --before=2.years.ago, --depth=50
> for the rest
>
> So I don't think we should go with your following patch because the
> size explosion is just too much no matter how faster it could be. An
> immediate action could be just make --depth=250 configurable and let
> people deal with it. A better option is something like "3 repack
> steps" you described where we pack deep depth first, mark .keep, pack
> shallower depth and combine them all into one.
>
> I'm not really happy with --depth=250 producing 209MB while
> --depth=250 --before=2.year.ago a 800MB pack. It looks wrong (or maybe
> I did something wrong)

That does look strange: Emacs has a history of more than 30 years.  But
the Git mirror is quite younger.  Maybe one needs to make sure to use
the author date rather than the commit date here?

-- 
David Kastrup
--
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/4] config: teach "git config --file -" to read from the standard input

2014-02-22 Thread Jeff King
On Wed, Feb 19, 2014 at 12:58:55AM +0200, Kirill A. Shutemov wrote:

> The patch extends git config --file interface to allow read config from
> stdin.
> 
> Editing stdin or setting value in stdin is an error.
> 
> Include by absolute path is allowed in stdin config, but not by relative
> path.
> 
> Signed-off-by: Kirill A. Shutemov 
> ---

This version of the series looks good to me.

-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] demonstrate git-commit --dry-run exit code behaviour

2014-02-22 Thread Jeff King
On Fri, Feb 21, 2014 at 12:21:13PM -0800, Junio C Hamano wrote:

> Tay Ray Chuan  writes:
> 
> > In particular, show that --short and --porcelain, while implying
> > --dry-run, do not return the same exit code as --dry-run. This is due to
> > the wt_status.commitable flag being set only when a long status is
> > requested.
> 
> I am not sure if --short/--porcelain should even be accepted by "git
> commit" in the first place.  It used to be that "git status" and
> "git commit" were the same program in a different guise and "git
> status " were merely a "git commit --dry-run ",
> but the recent push is in the direction of making them totally
> separate in the end-user's minds.  So if we want a proper fix, I
> would actually think that these options should *error out* at the
> command line parser level, way before checking if there is anything
> to commit.

I do not think they are any less useful than "git commit --dry-run" in
the first place. If you want to ask "what would happen if I ran commit
with these arguments", you can get the answer in any of several formats
(and --porcelain is the only machine-readable one).

I have never found "commit --dry-run" to be useful, but I assumed that
somebody does.

-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 3/3] make commit --verbose work with --no-status

2014-02-22 Thread Jeff King
On Sat, Feb 22, 2014 at 03:09:22AM +0800, Tay Ray Chuan wrote:

> @@ -1141,7 +1146,12 @@ static int parse_and_validate_options(int argc, const 
> char *argv[],
>   if (all && argc > 0)
>   die(_("Paths with -a does not make sense."));
>  
> - if (status_format != STATUS_FORMAT_DEFAULT)
> + if (verbose && !include_status) {
> + include_status = 1;
> + status_format = STATUS_FORMAT_NONE;
> + }
> +
> + if (status_format != STATUS_FORMAT_DEFAULT && !verbose)
>   dry_run = 1;

What happens here when there is an alternate status format _and_
--verbose is used? If I say "git commit --porcelain" it should imply
--dry-run. But "git commit --porcelain --verbose" no longer does so
after your patch.

-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 1/3] rename STATUS_FORMAT_NONE to STATUS_FORMAT_DEFAULT

2014-02-22 Thread Jeff King
On Sat, Feb 22, 2014 at 03:09:20AM +0800, Tay Ray Chuan wrote:

> In f3f47a1 (status: add --long output format option), STATUS_FORMAT_NONE
> was introduced, meaning "the user did not specify anything". Rename this
> to *_DEFAULT to better indicate its meaning.

Hmm. We later introduced STATUS_FORMAT_UNSPECIFIED in 84b4202d. It seems
like that is the same thing as the _DEFAULT you are proposing here. Can
we collapse them into a single value?

-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] sha1_file: fix delta_stack memory leak in unpack_entry

2014-02-22 Thread Jeff King
On Fri, Feb 21, 2014 at 10:09:33AM -0800, Junio C Hamano wrote:

> >> This delta_stack array can grow to any length depending on the actual
> >> delta chain, but we forget to free it. Normally it does not matter
> >> because we use small_delta_stack[] from stack and small_delta_stack
> >> can hold 64-delta chains, more than standard --depth=50 in pack-objects.
> [...]
> 
> This comes from abe601bb, right?  The change looks correct to me, too.

Yes, it does.

-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 v2] tag: support --sort=

2014-02-22 Thread Jeff King
On Sat, Feb 22, 2014 at 10:29:22AM +0700, Nguyễn Thái Ngọc Duy wrote:

> Signed-off-by: Nguyễn Thái Ngọc Duy 
> ---
>  The new prereq GNULINUX is an ugly workaround until people provide
>  strverscmp compat implementation. I hope that will happen soon as
>  strverscmp.c does not look very complex.

Should GNULINUX be called HAVE_STRVERSCMP in the Makefile?

Then this:

> --- a/git-compat-util.h
> +++ b/git-compat-util.h
> @@ -721,4 +721,11 @@ void warn_on_inaccessible(const char *path);
>  /* Get the passwd entry for the UID of the current process. */
>  struct passwd *xgetpwuid_self(void);
>  
> +#ifndef __GNU_LIBRARY__
> +static inline int strverscmp(const char *s1, const char *s2)
> +{
> + die("strverscmp() not supported");
> +}
> +#endif

becomes "#ifndef HAVE_STRVERSCMP", and this:

> diff --git a/t/test-lib.sh b/t/test-lib.sh
> index 1531c24..5e8c39a 100644
> --- a/t/test-lib.sh
> +++ b/t/test-lib.sh
> @@ -771,6 +771,8 @@ case $(uname -s) in
>   ;;
>  esac
>  
> +[ "$(uname -o)" = "GNU/Linux" ] && test_set_prereq GNULINUX
> +

can pick up the value from GIT-BUILD-OPTIONS as a prerequisite (see the
way we handle NO_PERL for an example). Though if we can just grab the
glibc version as a fallback, we can do away with that completely.

-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] tag: support --sort=version

2014-02-22 Thread Jeff King
On Fri, Feb 21, 2014 at 06:58:16PM +0700, Duy Nguyen wrote:

> >   --sort=[-][comparison:]field
> [...]
> Why not reversed order? So its syntax could be
> 
> [ "-" ] FIELD [ ":" [ "version" | "v" ] ]
> 
> It fits better to current f-e-r syntax where modifiers are after the
> colon. And it avoids the possibility that someone adds field "version"
> and we can't tell what "version" is what.

I find my version a bit more obvious, for two reasons:

  1. "version" here is not a modifier of the field name, it is a
 modifier of the sort. You cannot use it in non-sort contexts (like
 --format), and you cannot order it like other modifiers (you cannot
 say "refname:version:short", only "refname:short:version").

  2. There are actually two sort-modifiers: "-" for ordering, and then a
 comparator. In your proposal, they are split, whereas in mine, they
 are next to each other.

-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