[PATH] branch.c:install_branch_config():Simplify code generating verbose message.

2014-03-06 Thread Paweł Wawruch
From adfcfa0a334378a6242347efc0d614fa193610db Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pawe=C5=82=20Wawruch?= pa...@aleg.pl
Date: Thu, 6 Mar 2014 00:05:00 +0100
Subject: [PATCH] branch.c:install_branch_config(): Simplify the long chain of
 if statements. Threre was a long chain of if statements. The code can be more
 clear. The chain is replaced with table of strings. New approach is more
 compact.

---
 branch.c | 38 --
 1 file changed, 16 insertions(+), 22 deletions(-)

diff --git a/branch.c b/branch.c
index 723a36b..ebc2172 100644
--- a/branch.c
+++ b/branch.c
@@ -77,29 +77,23 @@ void install_branch_config(int flag, const char *local, 
const char *origin, cons
strbuf_release(key);
 
if (flag  BRANCH_CONFIG_VERBOSE) {
-   if (remote_is_branch  origin)
-   printf_ln(rebasing ?
- _(Branch %s set up to track remote branch %s 
from %s by 
rebasing.) :
- _(Branch %s set up to track remote branch %s 
from %s.),
- local, shortname, origin);
-   else if (remote_is_branch  !origin)
-   printf_ln(rebasing ?
- _(Branch %s set up to track local branch %s 
by rebasing.) :
- _(Branch %s set up to track local branch 
%s.),
- local, shortname);
-   else if (!remote_is_branch  origin)
-   printf_ln(rebasing ?
- _(Branch %s set up to track remote ref %s by 
rebasing.) :
- _(Branch %s set up to track remote ref %s.),
- local, remote);
-   else if (!remote_is_branch  !origin)
-   printf_ln(rebasing ?
- _(Branch %s set up to track local ref %s by 
rebasing.) :
- _(Branch %s set up to track local ref %s.),
- local, remote);
+   const char *messages[8] ;
+   messages[0] = _(Branch %s set up to track remote branch %s 
from %s by 
rebasing.);
+   messages[1] = _(Branch %s set up to track remote branch %s 
from %s.);
+   messages[2] = _(Branch %s set up to track local branch %s by 
rebasing.);
+   messages[3] = _(Branch %s set up to track local branch %s.);
+   messages[4] = _(Branch %s set up to track remote ref %s by 
rebasing.);
+   messages[5] = _(Branch %s set up to track remote ref %s.);
+   messages[6] = _(Branch %s set up to track local ref %s by 
rebasing.);
+   messages[7] = _(Branch %s set up to track local ref %s.);
+
+   const char *name = remote_is_branch ? remote : shortname;
+   int message_number = rebasing + 2 * (origin != NULL) + 4 * 
remote_is_branch;
+
+   if (message_number  2)
+   printf_ln(messages[message_number], local, name, 
origin);
else
-   die(BUG: impossible combination of %d and %p,
-   remote_is_branch, origin);
+   printf_ln(messages[message_number], local, name);
}
 }
 
-- 
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 v3] upload-pack: send shallow info over stdin to pack-objects

2014-03-06 Thread Nguyễn Thái Ngọc Duy
From: Duy Nguyen pclo...@gmail.com

Before cdab485 (upload-pack: delegate rev walking in shallow fetch to
pack-objects - 2013-08-16) upload-pack does not write to the source
repository. cdab485 starts to write $GIT_DIR/shallow_XX if it's a
shallow fetch, so the source repo must be writable.

git:// servers do not need write access to repos and usually don't
have it, which means cdab485 breaks shallow clone over git://

Instead of using a temporary file as the media for shallow points, we
can send them over stdin to pack-objects as well. Prepend shallow
SHA-1 with --shallow so pack-objects knows what is
what.

read_object_list_from_stdin() does not accept --shallow lines because
upload-pack never uses that code. When upload-pack does, then it can
learn about --shallow lines.

Signed-off-by: Nguyễn Thái Ngọc Duy pclo...@gmail.com
---
 OK new approach, stop creating shallow_XX in upload-pack.

 builtin/pack-objects.c   |  7 +++
 shallow.c|  2 ++
 t/t5537-fetch-shallow.sh | 13 +
 upload-pack.c| 21 -
 4 files changed, 34 insertions(+), 9 deletions(-)

diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c
index c733379..79e848e 100644
--- a/builtin/pack-objects.c
+++ b/builtin/pack-objects.c
@@ -2467,6 +2467,13 @@ static void get_object_list(int ac, const char **av)
write_bitmap_index = 0;
continue;
}
+   if (starts_with(line, --shallow )) {
+   unsigned char sha1[20];
+   if (get_sha1_hex(line + 10, sha1))
+   die(not an SHA-1 '%s', line + 10);
+   register_shallow(sha1);
+   continue;
+   }
die(not a rev '%s', line);
}
if (handle_revision_arg(line, revs, flags, 
REVARG_CANNOT_BE_FILENAME))
diff --git a/shallow.c b/shallow.c
index bbc98b5..41ff4a0 100644
--- a/shallow.c
+++ b/shallow.c
@@ -33,6 +33,8 @@ int register_shallow(const unsigned char *sha1)
graft-nr_parent = -1;
if (commit  commit-object.parsed)
commit-parents = NULL;
+   if (is_shallow == -1)
+   is_shallow = 1;
return register_commit_graft(graft, 0);
 }
 
diff --git a/t/t5537-fetch-shallow.sh b/t/t5537-fetch-shallow.sh
index 3ae9092..a980574 100755
--- a/t/t5537-fetch-shallow.sh
+++ b/t/t5537-fetch-shallow.sh
@@ -173,4 +173,17 @@ EOF
)
 '
 
+test_expect_success POSIXPERM,SANITY 'shallow fetch from a read-only repo' '
+   cp -R .git read-only.git 
+   find read-only.git -print | xargs chmod -w 
+   test_when_finished find read-only.git -type d -print | xargs chmod +w 

+   git clone --no-local --depth=2 read-only.git from-read-only 
+   git --git-dir=from-read-only/.git log --format=%s actual 
+   cat expect EOF 
+add-1-back
+4
+EOF
+   test_cmp expect actual
+'
+
 test_done
diff --git a/upload-pack.c b/upload-pack.c
index 0c44f6b..a5c50e4 100644
--- a/upload-pack.c
+++ b/upload-pack.c
@@ -70,6 +70,14 @@ static ssize_t send_client_data(int fd, const char *data, 
ssize_t sz)
return sz;
 }
 
+static int write_one_shallow(const struct commit_graft *graft, void *cb_data)
+{
+   FILE *fp = cb_data;
+   if (graft-nr_parent == -1)
+   fprintf(fp, --shallow %s\n, sha1_to_hex(graft-sha1));
+   return 0;
+}
+
 static void create_pack_file(void)
 {
struct child_process pack_objects;
@@ -81,12 +89,10 @@ static void create_pack_file(void)
const char *argv[12];
int i, arg = 0;
FILE *pipe_fd;
-   char *shallow_file = NULL;
 
if (shallow_nr) {
-   shallow_file = setup_temporary_shallow(NULL);
argv[arg++] = --shallow-file;
-   argv[arg++] = shallow_file;
+   argv[arg++] = ;
}
argv[arg++] = pack-objects;
argv[arg++] = --revs;
@@ -114,6 +120,9 @@ static void create_pack_file(void)
 
pipe_fd = xfdopen(pack_objects.in, w);
 
+   if (shallow_nr)
+   for_each_commit_graft(write_one_shallow, pipe_fd);
+
for (i = 0; i  want_obj.nr; i++)
fprintf(pipe_fd, %s\n,
sha1_to_hex(want_obj.objects[i].item-sha1));
@@ -242,12 +251,6 @@ static void create_pack_file(void)
error(git upload-pack: git-pack-objects died with error.);
goto fail;
}
-   if (shallow_file) {
-   if (*shallow_file)
-   unlink(shallow_file);
-   free(shallow_file);
-   }
-
/* flush the data */
if (0 = buffered) {
data[0] = buffered;
-- 
1.9.0.66.g14f785a

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

Re: [PATCH] disable grafts during fetch/push/bundle

2014-03-06 Thread Michael Haggerty
On 03/05/2014 08:18 PM, Junio C Hamano wrote:
 Jeff King p...@peff.net writes:
 
 On Wed, Mar 05, 2014 at 10:49:24AM -0800, Junio C Hamano wrote:

 ... the plan, at least in my mind, has always been exactly that: grafts
 were a nice little attempt but is broken---if you really wanted to
 muck with the history without rewriting (which is still discouraged,
 by the way), do not use graft, but use replace.

 I certainly had in the back of my mind that grafts were a lesser form of
 replace, and that eventually we could get rid of the former. Perhaps
 my question should have been: why haven't we deprecated grafts yet?.
 
 Given that we discourage grafts strongly and replace less so
 (but still discourage it), telling the users that biting the bullet
 and rewriting the history is _the_ permanent solution, I think it is
 understandable why nobody has bothered to.

Replace objects are better than grafts in *almost* every dimension.  The
exception is that it is dead simple to create grafts, whereas I always
have to break open the man pages to remember how to create a replace
object that does the same thing.

So I think a helpful step towards deprecating grafts would be to offer a
couple of convenience features to help people kick the grafts habit:

* A tool that converts grafts (i.e., the grafts read from
$GIT_DIR/info/grafts) into the equivalent replacements.

* A tool that creates a new replacement object that is the equivalent of
a graft.  I.e., it should do, using replace references, the equivalent
of the following command:

  echo SHA1 [PARENT1...] $GIT_DIR/info/grafts

These features could be added to git replace or could be built into a
new git grafts command.

Michael

-- 
Michael Haggerty
mhag...@alum.mit.edu
http://softwareswirl.blogspot.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 v4] Replace memcpy with hashcpy when dealing hash copy globally

2014-03-06 Thread Sun He
hashcpy() can keep the abstraction of object name behind it.
Use it instead of memcpy() with hard-coded 20-byte length when
moving object names between pieces of memory.
We can benefit from it, when we switch to another hash algorithm,
eg. MD5, by just fixing the hashcpy().

Leave ppc/sha1.c as it is, because the function is about the
SHA-1 hash algorithm whose output is and will always be 20-byte.

Helped-by: Michael Haggerty mhag...@alum.mit.edu
Helped-by: Duy Nguyen pclo...@gmail.com
Helped-by: Junio C Hamano gits...@pobox.com
Signed-off-by: Sun He sunheeh...@gmail.com
---
PATCH v4 changed the reason why should take this patch as tutored by
Junio C Hamano.
 Thanks to Junio C Hamano

PATCH v3 delete the one-space indentation on each line of commit message
as is suggested by Eric Sunshine.
 Thanks to Eric Sunshine.

PATCH v2 leave ppc/sha1.c alone.

The general rule is if cache.h or git-compat-util.h is included,
it is the first #include, and system includes will be always in
git-compat-tuil.h.
via Duy Nguyen

The change in PATCH v1 is not proper because I placed cache.h
in the end.
And adding it to the head is not a good way to achieve the goal,
as is said above ---.
 Thanks to Duy Nguyen.

Find the potential places with memcpy by the bash command:
 $ git grep 'memcpy.*20'
 Thanks to Junio C Hamano

 bundle.c| 2 +-
 grep.c  | 2 +-
 pack-bitmap-write.c | 2 +-
 reflog-walk.c   | 4 ++--
 refs.c  | 2 +-
 5 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/bundle.c b/bundle.c
index e99065c..7809fbb 100644
--- a/bundle.c
+++ b/bundle.c
@@ -19,7 +19,7 @@ static void add_to_ref_list(const unsigned char *sha1, const 
char *name,
list-list = xrealloc(list-list,
list-alloc * sizeof(list-list[0]));
}
-   memcpy(list-list[list-nr].sha1, sha1, 20);
+   hashcpy(list-list[list-nr].sha1, sha1);
list-list[list-nr].name = xstrdup(name);
list-nr++;
 }
diff --git a/grep.c b/grep.c
index c668034..f5101f7 100644
--- a/grep.c
+++ b/grep.c
@@ -1650,7 +1650,7 @@ void grep_source_init(struct grep_source *gs, enum 
grep_source_type type,
break;
case GREP_SOURCE_SHA1:
gs-identifier = xmalloc(20);
-   memcpy(gs-identifier, identifier, 20);
+   hashcpy(gs-identifier, identifier);
break;
case GREP_SOURCE_BUF:
gs-identifier = NULL;
diff --git a/pack-bitmap-write.c b/pack-bitmap-write.c
index 1218bef..5f1791a 100644
--- a/pack-bitmap-write.c
+++ b/pack-bitmap-write.c
@@ -530,7 +530,7 @@ void bitmap_writer_finish(struct pack_idx_entry **index,
header.version = htons(default_version);
header.options = htons(flags | options);
header.entry_count = htonl(writer.selected_nr);
-   memcpy(header.checksum, writer.pack_checksum, 20);
+   hashcpy(header.checksum, writer.pack_checksum);
 
sha1write(f, header, sizeof(header));
dump_bitmap(f, writer.commits);
diff --git a/reflog-walk.c b/reflog-walk.c
index b2fbdb2..d490f7d 100644
--- a/reflog-walk.c
+++ b/reflog-walk.c
@@ -32,8 +32,8 @@ static int read_one_reflog(unsigned char *osha1, unsigned 
char *nsha1,
sizeof(struct reflog_info));
}
item = array-items + array-nr;
-   memcpy(item-osha1, osha1, 20);
-   memcpy(item-nsha1, nsha1, 20);
+   hashcpy(item-osha1, osha1);
+   hashcpy(item-nsha1, nsha1);
item-email = xstrdup(email);
item-timestamp = timestamp;
item-tz = tz;
diff --git a/refs.c b/refs.c
index 89228e2..f90b7ea 100644
--- a/refs.c
+++ b/refs.c
@@ -1222,7 +1222,7 @@ static int resolve_gitlink_packed_ref(struct ref_cache 
*refs,
if (ref == NULL)
return -1;
 
-   memcpy(sha1, ref-u.value.sha1, 20);
+   hashcpy(sha1, ref-u.value.sha1);
return 0;
 }
 
-- 
1.9.0.138.g2de3478.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] disable grafts during fetch/push/bundle

2014-03-06 Thread Christian Couder
On Thu, Mar 6, 2014 at 9:42 AM, Michael Haggerty mhag...@alum.mit.edu wrote:
 On 03/05/2014 08:18 PM, Junio C Hamano wrote:
 Jeff King p...@peff.net writes:

 On Wed, Mar 05, 2014 at 10:49:24AM -0800, Junio C Hamano wrote:

 ... the plan, at least in my mind, has always been exactly that: grafts
 were a nice little attempt but is broken---if you really wanted to
 muck with the history without rewriting (which is still discouraged,
 by the way), do not use graft, but use replace.

 I certainly had in the back of my mind that grafts were a lesser form of
 replace, and that eventually we could get rid of the former. Perhaps
 my question should have been: why haven't we deprecated grafts yet?.

 Given that we discourage grafts strongly and replace less so
 (but still discourage it), telling the users that biting the bullet
 and rewriting the history is _the_ permanent solution, I think it is
 understandable why nobody has bothered to.

 Replace objects are better than grafts in *almost* every dimension.  The
 exception is that it is dead simple to create grafts, whereas I always
 have to break open the man pages to remember how to create a replace
 object that does the same thing.

 So I think a helpful step towards deprecating grafts would be to offer a
 couple of convenience features to help people kick the grafts habit:

 * A tool that converts grafts (i.e., the grafts read from
 $GIT_DIR/info/grafts) into the equivalent replacements.

Yeah, I sent a kind of rough draft of a script to do that last year to
the mailing list, but I didn't take the time to convert it to a real
script or command.

 * A tool that creates a new replacement object that is the equivalent of
 a graft.  I.e., it should do, using replace references, the equivalent
 of the following command:

   echo SHA1 [PARENT1...] $GIT_DIR/info/grafts

Yeah, maybe it can be a git create-replace-ref command and it could
have a --convert-graft-file option to convert an existing graft file.

There have been discussions about such a command already some time ago.

 These features could be added to git replace or could be built into a
 new git grafts command.

I think Junio previously said that it was better if such features were
not part of git replace. But maybe I misunderstood his subtle
saying.

And I don't think git grafts is a good name. It looks too much like
we are encouraging people to use grafts.

Thanks,
Christian.
--
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] make --set-upstream work for local branches not in refs/heads

2014-03-06 Thread Krzesimir Nowak
On Tue, 2014-03-04 at 11:44 -0800, Junio C Hamano wrote:
 Krzesimir Nowak krzesi...@endocode.com writes:
 
  It might be possible (in Gerrited setups) to have local branches
  outside refs/heads/, like for example in following fetch config:
 
  [remote origin]
  url = ssh://u...@example.com/my-project
  fetch = +refs/heads/*:refs/remotes/origin/*
  fetch = +refs/wip/*:refs/remotes/origin-wip/*
 
  Let's say that 'test' branch already exist in origin/refs/wip/. If I
  call:
 
  git checkout test
 
  then it will create a new branch and add an entry to .git/config:
 
  [branch test]
  remote = origin
  merge = refs/wip/test
 
  But if I create a branch 'test2' and call:
 
  git push --set-upstream origin test2:refs/wip/test2
 
  then branch is pushed, but no entry in .git config is created.
 
 By definition anything otuside refs/heads/ is not a branch, so do
 not call things in refs/wip branches.  Retitle it to work for
 local refs outside refs/heads or something.

I always have problems with proper use of git's terminology. Sorry.

 
 Having said that, I do not see a major problem if we allowed
 
   [branch test2]
   remote = origin
 merge = refs/wip/test2
 
 to be created when push --setupstream is requested, making
 test2@{upstream} to point at refs/remotes/origin-wip/test2.
 
 I do not know what the correct implementation of such a feature
 should be, though.

Hm, have some idea about it, though I will leave its sanity to judge to
you.

Given the following config snippet:
[remote origin]
url = ssh://u...@example.com/my-project
fetch = +refs/heads/*:refs/remotes/origin/*
fetch = +refs/wip/*:refs/remotes/origin-wip/*

We could have get_local_ref_hierarchies function defined somewhat as
follows (memory management details are left out):

char **get_local_ref_hierarchies(char *remote)
{
char **refspecs = get_fetch_refspecs_for_remote (remote);
char **iter;
char **local = NULL;

for (iter = refspecs; iter  *iter; ++iter) {
char *src = get_src_refspec_part (*iter);
push (local, src);
}

/* maybe filter dups and make refs/heads/ first */
return local;
}

I'm sure that there are some corner-cases this code does not handle.

Also, maybe it would be good to add some information when --set-upstream
does nothing. Something like after doing git push --set-upstream origin
test:refs/wip/test:


Could not set temp to track refs/wip/test. Either call:
git config branch.test.remote origin
git config branch.test.merge refs/wip/test

or (this part would appear if this solution in patch is accepted)

git config --add remote.origin.fetch \
+refs/wip/*:refs/remotes/origin-wip/*


Cheers,
-- 
Krzesimir Nowak
Software Developer
Endocode AG

krzesi...@endocode.com

--
Endocode AG, Johannisstraße 20, 10117 Berlin
i...@endocode.com | www.endocode.com

Vorstandsvorsitzender: Mirko Boehm
Vorstände: Dr. Karl Beecher, Chris Kühl, Sebastian Sucker
Aufsichtsratsvorsitzende: Jennifer Beecher

Registergericht: Amtsgericht Charlottenburg - HRB 150748 B



--
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] commit.c: Replace starts_with() with skip_prefix()

2014-03-06 Thread Eric Sunshine
On Wed, Mar 5, 2014 at 9:06 AM, Karthik Nayak karthik@gmail.com wrote:
 Replaces all instances of starts_with() by skip_prefix(),

Use imperative mode: Replace all...

 which can not only be used to check presence of a prefix,
 but also used further on as it returns the string after the prefix,
 if the prefix is present.

This is a lot better than previous versions. It could be improved a
bit by more directly stating that skip_prefix() singly does what the
current code is doing in two steps. (See Tanay's submission [1] for an
example of a well-crafted commit message). However, we're probably at
the point of diminishing returns, so no need to reroll just for this.

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

 Signed-off-by: Karthik Nayak karthik@gmail.com
 ---

 Hey Eric,
 Here are the changes i have made in this Patch v2:
 1. Edited the variables names to fit their usage
 2. set my emacs to indent 8 tabs, so proper indentation
 3. fixed my error where i increased the value by 1 in parse_signed_commit().
 Thanks again for your patience.

Thanks for the reroll and for explaining the changes. More below.

 ---
  commit.c | 23 ---
  1 file changed, 12 insertions(+), 11 deletions(-)

 diff --git a/commit.c b/commit.c
 index 6bf4fe0..f006490 100644
 --- a/commit.c
 +++ b/commit.c
 @@ -553,6 +553,7 @@ static void record_author_date(struct author_date_slab 
 *author_date,
 struct ident_split ident;
 char *date_end;
 unsigned long date;
 +   const char *buf_split;

In a previous review, I suggested reading Junio's response [1] to a
similar submission. Of particular interest, Junio says:

A good rule of thumb to remember is to name things after what
they are, not how you obtain them, how they are used or what
they are used for/as.

The name 'buf_split' is clearly a how you obtain them, which does
not convey much. Better would be to name the variable to reflect what
it references once assigned.

[1]: http://thread.gmane.org/gmane.comp.version-control.git/243231/focus=243259

 if (!commit-buffer) {
 unsigned long size;
 @@ -562,18 +563,19 @@ static void record_author_date(struct author_date_slab 
 *author_date,
 return;
 }

 +   buf_split = skip_prefix(buf, author );
 +
 for (buf = commit-buffer ? commit-buffer : buffer;
  buf;
  buf = line_end + 1) {
 line_end = strchrnul(buf, '\n');
 -   if (!starts_with(buf, author )) {
 +   if (!buf_split) {
 if (!line_end[0] || line_end[1] == '\n')
 return; /* end of header */
 continue;
 }
 -   if (split_ident_line(ident,
 -buf + strlen(author ),
 -line_end - (buf + strlen(author ))) ||
 +   if (split_ident_line(ident, buf_split,
 +line_end - buf_split) ||
 !ident.date_begin || !ident.date_end)
 goto fail_exit; /* malformed author line */
 break;
 @@ -1098,6 +1100,7 @@ int parse_signed_commit(const unsigned char *sha1,
 char *buffer = read_sha1_file(sha1, type, size);
 int in_signature, saw_signature = -1;
 char *line, *tail;
 +   const char *line_split;

Ditto.

 if (!buffer || type != OBJ_COMMIT)
 goto cleanup;
 @@ -,11 +1114,11 @@ int parse_signed_commit(const unsigned char *sha1,
 char *next = memchr(line, '\n', tail - line);

 next = next ? next + 1 : tail;
 +   line_split = skip_prefix(line, gpg_sig_header);
 if (in_signature  line[0] == ' ')
 sig = line + 1;
 -   else if (starts_with(line, gpg_sig_header) 
 -line[gpg_sig_header_len] == ' ')
 -   sig = line + gpg_sig_header_len + 1;
 +   else if (line_split  line_split[0] == ' ')
 +   sig = line_split + 1;

A shortcoming of this change is that skip_prefix() is now being called
unconditionally, even when its result won't be used (as in the first
'if' statement). The original code did the work of checking the prefix
only if the first 'if' statement evaluated to false.

 if (sig) {
 strbuf_add(signature, sig, next - sig);
 saw_signature = 1;
 @@ -1193,10 +1196,8 @@ static void parse_gpg_output(struct signature_check 
 *sigc)
 for (i = 0; i  ARRAY_SIZE(sigcheck_gpg_status); i++) {
 const char *found, *next;

 -   if (starts_with(buf, sigcheck_gpg_status[i].check + 1)) {
 -   /* At the very beginning of the buffer */
 -   found = buf + 

Re: [PATCH v4 22/27] checkout: clean up half-prepared directories in --to mode

2014-03-06 Thread Eric Sunshine
On Sat, Mar 1, 2014 at 7:12 AM, Nguyễn Thái Ngọc Duy pclo...@gmail.com wrote:
 Signed-off-by: Nguyễn Thái Ngọc Duy pclo...@gmail.com
 ---
  builtin/checkout.c | 49 +++--
  1 file changed, 47 insertions(+), 2 deletions(-)

 diff --git a/builtin/checkout.c b/builtin/checkout.c
 index fa7b54a..28f9ac1 100644
 --- a/builtin/checkout.c
 +++ b/builtin/checkout.c
 @@ -20,6 +20,7 @@
  #include resolve-undo.h
  #include submodule.h
  #include argv-array.h
 +#include sigchain.h

  static const char * const checkout_usage[] = {
 N_(git checkout [options] branch),
 @@ -814,6 +815,35 @@ static int switch_branches(const struct checkout_opts 
 *opts,
 return ret || writeout_error;
  }

 +static const char *junk_work_tree;
 +static const char *junk_git_dir;
 +static int is_junk;
 +static pid_t junk_pid;
 +
 +static void remove_junk(void)
 +{
 +   struct strbuf sb = STRBUF_INIT;
 +   if (!is_junk || getpid() != junk_pid)
 +   return;
 +   if (junk_git_dir) {
 +   strbuf_addstr(sb, junk_git_dir);
 +   remove_dir_recursively(sb, 0);
 +   strbuf_reset(sb);
 +   }
 +   if (junk_work_tree) {
 +   strbuf_addstr(sb, junk_work_tree);
 +   remove_dir_recursively(sb, 0);
 +   strbuf_reset(sb);
 +   }

strbuf_release(sb);

 +}
 +
 +static void remove_junk_on_signal(int signo)
 +{
 +   remove_junk();
 +   sigchain_pop(signo);
 +   raise(signo);
 +}
 +
  static int prepare_linked_checkout(const struct checkout_opts *opts,
struct branch_info *new)
  {
 @@ -822,7 +852,7 @@ static int prepare_linked_checkout(const struct 
 checkout_opts *opts,
 const char *path = opts-new_worktree, *name;
 struct stat st;
 struct child_process cp;
 -   int counter = 0, len;
 +   int counter = 0, len, ret;

 if (!new-commit)
 die(_(no branch specified));
 @@ -848,13 +878,21 @@ static int prepare_linked_checkout(const struct 
 checkout_opts *opts,
 strbuf_addf(sb_repo, %d, counter);
 }
 name = strrchr(sb_repo.buf, '/') + 1;
 +
 +   junk_pid = getpid();
 +   atexit(remove_junk);
 +   sigchain_push_common(remove_junk_on_signal);
 +
 if (mkdir(sb_repo.buf, 0777))
 die_errno(_(could not create directory of '%s'), 
 sb_repo.buf);
 +   junk_git_dir = sb_repo.buf;
 +   is_junk = 1;

 strbuf_addf(sb_git, %s/.git, path);
 if (safe_create_leading_directories_const(sb_git.buf))
 die_errno(_(could not create leading directories of '%s'),
   sb_git.buf);
 +   junk_work_tree = path;

 write_file(sb_git.buf, 1, gitdir: %s/repos/%s\n,
real_path(get_git_common_dir()), name);
 @@ -879,7 +917,14 @@ static int prepare_linked_checkout(const struct 
 checkout_opts *opts,
 memset(cp, 0, sizeof(cp));
 cp.git_cmd = 1;
 cp.argv = opts-saved_argv;
 -   return run_command(cp);
 +   ret = run_command(cp);
 +   if (!ret)
 +   is_junk = 0;
 +   strbuf_release(sb);
 +   strbuf_release(sb_repo);
 +   strbuf_release(sb_git);
 +   return ret;
 +
  }

  static int git_checkout_config(const char *var, const char *value, void *cb)
 --
 1.9.0.40.gaa8c3ea
--
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: Unable to shrink repository size

2014-03-06 Thread Duy Nguyen
On Thu, Mar 6, 2014 at 9:55 AM, Robert Dailey rcdailey.li...@gmail.com wrote:
 What I'd like to do is somehow hunt down the largest commit (*not*
 blob) in the entire history of the repository to hopefully find out
 where huge directories have been checked in.

Another try

git rev-list --all|while read i;do echo -n $i ; git ls-tree -lr
$i|awk '{a+=$4;} END {print a;}';done

You may need to feed it to gnuplot or something to see steep slopes.
-- 
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


Immediate Parckage Shipping Notification

2014-03-06 Thread Mr.John Roland
Atten:

Simply contact Diplomat Mrs Cherina Garcia with your full delivery address And 
your nearest airport to land,  on this information below so that she can 
deliver the Package to you; Name: Mrs Cherina Garcia
Email:(mrs.charina.gar...@barid.com)

Regards,
Mr, John Roland
--
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/6] test patch hunk editing with commit -p -m

2014-03-06 Thread Benoit Pierre
Add (failing) test: with commit changing the environment to let hooks
now that no editor will be used (by setting GIT_EDITOR to :), the
edit hunk functionality does not work (no editor is launched and the
whole hunk is committed).

Signed-off-by: Benoit Pierre benoit.pie...@gmail.com
---
 t/t7513-commit_-p_-m_hunk_edit.sh | 37 +
 1 file changed, 37 insertions(+)
 create mode 100755 t/t7513-commit_-p_-m_hunk_edit.sh

diff --git a/t/t7513-commit_-p_-m_hunk_edit.sh 
b/t/t7513-commit_-p_-m_hunk_edit.sh
new file mode 100755
index 000..e0ad905
--- /dev/null
+++ b/t/t7513-commit_-p_-m_hunk_edit.sh
@@ -0,0 +1,37 @@
+#!/bin/sh
+
+test_description='hunk edit with commit -p -m'
+. ./test-lib.sh
+
+if ! test_have_prereq PERL
+then
+   skip_all=skipping '$test_description' tests, perl not available
+   test_done
+fi
+
+test_expect_success 'setup (initial)' '
+   echo line1 file 
+   git add file 
+   git commit -m commit1
+   echo line3 file
+'
+
+test_expect_success 'setup expected' '
+cat expected EOF
+diff --git a/file b/file
+index a29bdeb..c0d0fb4 100644
+--- a/file
 b/file
+@@ -1 +1,2 @@
+ line1
++line2
+EOF
+'
+
+test_expect_failure 'edit hunk commit -p -m message' '
+   echo e | env GIT_EDITOR=sed s/+line3\$/+line2/ -i git commit -p -m 
commit2 file 
+   git diff HEAD^ HEAD diff 
+   test_cmp expected diff
+'
+
+test_done
-- 
1.9.0

--
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/6] fix hunk editing with 'commit -p -m'

2014-03-06 Thread Benoit Pierre
This patch fixes the fact that hunk editing with 'commit -p -m' does not work:
GIT_EDITOR is set to ':' to indicate to hooks that no editor will be launched,
which result in the 'hunk edit' option not launching the editor (and selecting
the whole hunk).

The fix consists in deferring the GIT_EDITOR override to the hook subprocess,
like it's already done for GIT_INDEX_FILE:
- modify 'run_hook' so the first parameter is the environment to set
- add a 'run_hook_v' variant that take a va_list
- add a new 'run_commit_hook' helper (to set both GIT_EDITOR and GIT_INDEX_FILE)

N.B.: the merge builtin 'prepare-commit-msg' hook handling has also been updated
to be consistent; i.e. GIT_EDITOR will not be set to ':' if the '--edit' option
is used.

Benoit Pierre (6):
  test patch hunk editing with commit -p -m
  commit: fix patch hunk editing with commit -p -m
  merge: fix GIT_EDITOR override for commit hook
  merge hook tests: fix and update tests
  merge hook tests: fix missing '' in test
  merge hook tests: use 'test_must_fail' instead of '!'

 builtin/commit.c   | 35 ---
 builtin/merge.c|  4 ++--
 commit.h   |  3 +++
 run-command.c  | 27 +++
 run-command.h  |  3 ++-
 t/t7505-prepare-commit-msg-hook.sh | 23 +++
 t/t7513-commit_-p_-m_hunk_edit.sh  | 37 +
 7 files changed, 106 insertions(+), 26 deletions(-)
 create mode 100755 t/t7513-commit_-p_-m_hunk_edit.sh

-- 
1.9.0

--
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 5/6] merge hook tests: fix missing '' in test

2014-03-06 Thread Benoit Pierre
Signed-off-by: Benoit Pierre benoit.pie...@gmail.com
---
 t/t7505-prepare-commit-msg-hook.sh | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/t/t7505-prepare-commit-msg-hook.sh 
b/t/t7505-prepare-commit-msg-hook.sh
index ae7b2db..604c06e 100755
--- a/t/t7505-prepare-commit-msg-hook.sh
+++ b/t/t7505-prepare-commit-msg-hook.sh
@@ -189,7 +189,7 @@ test_expect_success 'with failing hook (merge)' '
git add file 
rm -f $HOOK 
git commit -m other 
-   write_script $HOOK -EOF
+   write_script $HOOK -EOF 
exit 1
EOF
git checkout - 
-- 
1.9.0

--
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 3/6] merge: fix GIT_EDITOR override for commit hook

2014-03-06 Thread Benoit Pierre
Don't set GIT_EDITOR to : when calling prepare-commit-msg hook if the
editor is going to be called (e.g. with merge -e).

Signed-off-by: Benoit Pierre benoit.pie...@gmail.com
---
 builtin/merge.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/builtin/merge.c b/builtin/merge.c
index d2a1bfe..da7cafe 100644
--- a/builtin/merge.c
+++ b/builtin/merge.c
@@ -821,7 +821,7 @@ static void prepare_to_commit(struct commit_list 
*remoteheads)
if (0  option_edit)
strbuf_commented_addf(msg, _(merge_editor_comment), 
comment_line_char);
write_merge_msg(msg);
-   if (run_commit_hook(1, get_index_file(), prepare-commit-msg,
+   if (run_commit_hook(0  option_edit, get_index_file(), 
prepare-commit-msg,
git_path(MERGE_MSG), merge, NULL))
abort_commit(remoteheads, NULL);
if (0  option_edit) {
-- 
1.9.0

--
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/6] merge hook tests: use 'test_must_fail' instead of '!'

2014-03-06 Thread Benoit Pierre
Signed-off-by: Benoit Pierre benoit.pie...@gmail.com
---
 t/t7505-prepare-commit-msg-hook.sh | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/t/t7505-prepare-commit-msg-hook.sh 
b/t/t7505-prepare-commit-msg-hook.sh
index 604c06e..1be6cec 100755
--- a/t/t7505-prepare-commit-msg-hook.sh
+++ b/t/t7505-prepare-commit-msg-hook.sh
@@ -167,7 +167,7 @@ test_expect_success 'with failing hook' '
head=`git rev-parse HEAD` 
echo more  file 
git add file 
-   ! GIT_EDITOR=\\$FAKE_EDITOR\ git commit -c $head
+   test_must_fail env GIT_EDITOR=\\$FAKE_EDITOR\ git commit -c $head
 
 '
 
@@ -177,7 +177,7 @@ test_expect_success 'with failing hook (--no-verify)' '
head=`git rev-parse HEAD` 
echo more  file 
git add file 
-   ! GIT_EDITOR=\\$FAKE_EDITOR\ git commit --no-verify -c $head
+   test_must_fail env GIT_EDITOR=\\$FAKE_EDITOR\ git commit 
--no-verify -c $head
 
 '
 
-- 
1.9.0

--
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 4/6] merge hook tests: fix and update tests

2014-03-06 Thread Benoit Pierre
- update 'no editor' hook test and add 'editor' hook test
- reset tree at the beginning of failing hook tests to avoid failures
  due to an unclean tree after running a previous test

Signed-off-by: Benoit Pierre benoit.pie...@gmail.com
---
 t/t7505-prepare-commit-msg-hook.sh | 17 -
 1 file changed, 16 insertions(+), 1 deletion(-)

diff --git a/t/t7505-prepare-commit-msg-hook.sh 
b/t/t7505-prepare-commit-msg-hook.sh
index 3573751..ae7b2db 100755
--- a/t/t7505-prepare-commit-msg-hook.sh
+++ b/t/t7505-prepare-commit-msg-hook.sh
@@ -141,7 +141,19 @@ test_expect_success 'with hook (merge)' '
git commit -m other 
git checkout - 
git merge other 
-   test `git log -1 --pretty=format:%s` = merge
+   test `git log -1 --pretty=format:%s` = merge (no editor)
+'
+
+test_expect_success 'with hook and editor (merge)' '
+
+   head=`git rev-parse HEAD` 
+   git checkout -B other HEAD@{1} 
+   echo more  file 
+   git add file 
+   git commit -m other 
+   git checkout - 
+   env GIT_EDITOR=\\$FAKE_EDITOR\ git merge -e other 
+   test `git log -1 --pretty=format:%s` = merge
 '
 
 cat  $HOOK 'EOF'
@@ -151,6 +163,7 @@ EOF
 
 test_expect_success 'with failing hook' '
 
+   git reset --hard 
head=`git rev-parse HEAD` 
echo more  file 
git add file 
@@ -160,6 +173,7 @@ test_expect_success 'with failing hook' '
 
 test_expect_success 'with failing hook (--no-verify)' '
 
+   git reset --hard 
head=`git rev-parse HEAD` 
echo more  file 
git add file 
@@ -169,6 +183,7 @@ test_expect_success 'with failing hook (--no-verify)' '
 
 test_expect_success 'with failing hook (merge)' '
 
+   git reset --hard 
git checkout -B other HEAD@{1} 
echo more  file 
git add file 
-- 
1.9.0

--
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/6] commit: fix patch hunk editing with commit -p -m

2014-03-06 Thread Benoit Pierre
Don't change git environment: move the GIT_EDITOR=: override to the
hook command subprocess, like it's already done for GIT_INDEX_FILE.

Signed-off-by: Benoit Pierre benoit.pie...@gmail.com
---
 builtin/commit.c  | 35 ---
 builtin/merge.c   |  4 ++--
 commit.h  |  3 +++
 run-command.c | 27 +++
 run-command.h |  3 ++-
 t/t7513-commit_-p_-m_hunk_edit.sh |  2 +-
 6 files changed, 51 insertions(+), 23 deletions(-)

diff --git a/builtin/commit.c b/builtin/commit.c
index 3767478..2f5a44f 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -612,7 +612,7 @@ static int prepare_to_commit(const char *index_file, const 
char *prefix,
/* This checks and barfs if author is badly specified */
determine_author_info(author_ident);
 
-   if (!no_verify  run_hook(index_file, pre-commit, NULL))
+   if (!no_verify  run_commit_hook(use_editor, index_file, pre-commit, 
NULL))
return 0;
 
if (squash_message) {
@@ -866,8 +866,8 @@ static int prepare_to_commit(const char *index_file, const 
char *prefix,
return 0;
}
 
-   if (run_hook(index_file, prepare-commit-msg,
-git_path(commit_editmsg), hook_arg1, hook_arg2, NULL))
+   if (run_commit_hook(use_editor, index_file, prepare-commit-msg,
+   git_path(commit_editmsg), hook_arg1, hook_arg2, 
NULL))
return 0;
 
if (use_editor) {
@@ -883,7 +883,7 @@ static int prepare_to_commit(const char *index_file, const 
char *prefix,
}
 
if (!no_verify 
-   run_hook(index_file, commit-msg, git_path(commit_editmsg), NULL)) 
{
+   run_commit_hook(use_editor, index_file, commit-msg, 
git_path(commit_editmsg), NULL)) {
return 0;
}
 
@@ -1067,8 +1067,6 @@ static int parse_and_validate_options(int argc, const 
char *argv[],
use_editor = 0;
if (0 = edit_flag)
use_editor = edit_flag;
-   if (!use_editor)
-   setenv(GIT_EDITOR, :, 1);
 
/* Sanity check options */
if (amend  !current_head)
@@ -1445,6 +1443,29 @@ static int run_rewrite_hook(const unsigned char *oldsha1,
return finish_command(proc);
 }
 
+int run_commit_hook(int editor_is_used, const char *index_file, const char 
*name, ...)
+{
+   const char *hook_env[3] =  { NULL };
+   char index[PATH_MAX];
+   va_list args;
+   int ret;
+
+   snprintf(index, sizeof(index), GIT_INDEX_FILE=%s, index_file);
+   hook_env[0] = index;
+
+   /*
+* Let the hook know that no editor will be launched.
+*/
+   if (!editor_is_used)
+   hook_env[1] = GIT_EDITOR=:;
+
+   va_start(args, name);
+   ret = run_hook_v(hook_env, name, args);
+   va_end(args);
+
+   return ret;
+}
+
 int cmd_commit(int argc, const char **argv, const char *prefix)
 {
static struct wt_status s;
@@ -1669,7 +1690,7 @@ int cmd_commit(int argc, const char **argv, const char 
*prefix)
 not exceeded, and then \git reset HEAD\ to recover.));
 
rerere(0);
-   run_hook(get_index_file(), post-commit, NULL);
+   run_commit_hook(use_editor, get_index_file(), post-commit, NULL);
if (amend  !no_post_rewrite) {
struct notes_rewrite_cfg *cfg;
cfg = init_copy_notes_for_rewrite(amend);
diff --git a/builtin/merge.c b/builtin/merge.c
index e576a7f..d2a1bfe 100644
--- a/builtin/merge.c
+++ b/builtin/merge.c
@@ -821,8 +821,8 @@ static void prepare_to_commit(struct commit_list 
*remoteheads)
if (0  option_edit)
strbuf_commented_addf(msg, _(merge_editor_comment), 
comment_line_char);
write_merge_msg(msg);
-   if (run_hook(get_index_file(), prepare-commit-msg,
-git_path(MERGE_MSG), merge, NULL, NULL))
+   if (run_commit_hook(1, get_index_file(), prepare-commit-msg,
+   git_path(MERGE_MSG), merge, NULL))
abort_commit(remoteheads, NULL);
if (0  option_edit) {
if (launch_editor(git_path(MERGE_MSG), NULL, NULL))
diff --git a/commit.h b/commit.h
index 16d9c43..8d97a5c 100644
--- a/commit.h
+++ b/commit.h
@@ -304,4 +304,7 @@ extern void check_commit_signature(const struct commit* 
commit, struct signature
 
 int compare_commits_by_commit_date(const void *a_, const void *b_, void 
*unused);
 
+LAST_ARG_MUST_BE_NULL
+extern int run_commit_hook(int editor_is_used, const char *index_file, const 
char *name, ...);
+
 #endif /* COMMIT_H */
diff --git a/run-command.c b/run-command.c
index 3914d9c..4e9be12 100644
--- a/run-command.c
+++ b/run-command.c
@@ -760,13 +760,11 @@ char *find_hook(const char *name)
return path;
 }
 
-int run_hook(const char *index_file, const char *name, ...)
+int run_hook_v(const char 

Re: Unable to shrink repository size

2014-03-06 Thread Jeff King
On Wed, Mar 05, 2014 at 08:55:30PM -0600, Robert Dailey wrote:

 What I'd like to do is somehow hunt down the largest commit (*not*
 blob) in the entire history of the repository to hopefully find out
 where huge directories have been checked in.
 
 I can't do a search for largest file (which most google results seem
 to show to do) since the culprit is really thousands of unnecessary
 files checked into a single subdirectory somewhere in history.

Other people have offered scripts to look at commit sizes. But it might
also be useful to see sizes by subdirectory. Sort of a du across all
of history. Script is below.

Note that this script also uses cat-file's %(objectsize:disk). So it
is finding the actual on-disk storage, taking into account delta
storage. You will need git v1.8.5 or later to use this feature.

  git rev-list --objects --all |
  git cat-file --batch-check=%(objectsize:disk) %(rest) |
  perl -lne '
my ($size, $path) = split / /, $_, 2;
next unless defined $path; # commit obj
do {
  $sizes{$path} += $size;
} while ($path =~ s{/[^/]+$}{});

END { print $sizes{$_} $_ for (keys %sizes) }
  ' |
  sort -rn

-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] disable grafts during fetch/push/bundle

2014-03-06 Thread Jeff King
On Thu, Mar 06, 2014 at 09:42:46AM +0100, Michael Haggerty wrote:

 Replace objects are better than grafts in *almost* every dimension.  The
 exception is that it is dead simple to create grafts, whereas I always
 have to break open the man pages to remember how to create a replace
 object that does the same thing.
 
 So I think a helpful step towards deprecating grafts would be to offer a
 couple of convenience features to help people kick the grafts habit:

I agree that better tool support would make git replace more pleasant
to use.

 * A tool that converts grafts (i.e., the grafts read from
 $GIT_DIR/info/grafts) into the equivalent replacements.

I don't know if this is strictly necessary, if we make your command
below pleasant to use. I.e., it should just be:

  while read sha1 parents; do
git replace --graft $sha1 $parents
  done .git/info/grafts

We can wrap that in git replace --convert-grafts, but I do not think
grafts are so common that there would be a big demand for it.

 * A tool that creates a new replacement object that is the equivalent of
 a graft.  I.e., it should do, using replace references, the equivalent
 of the following command:
 
   echo SHA1 [PARENT1...] $GIT_DIR/info/grafts
 
 These features could be added to git replace or could be built into a
 new git grafts command.

I think it would be nice to have a set of mode options for
git-replace to do basic editing of a sha1 and install the result
(technically you could split the editing into a separate command, but I
do not see the point in editing a sha1 and then _not_ replacing it).

Perhaps:

  # pretty-print sha1 based on type, start $EDITOR, create a
  # type-appropriate object from the result (e.g., using hash-object,
  # mktree, or mktag), and then set up the object as a replacement for
  # SHA1
  git replace --edit SHA1

  # ditto, but replace the $EDITOR step with the parent list
  git replace --graft SHA1 PARENT1 PARENT2

  # ...or remove entries from a tree
  git replace --remove-entry SHA1 foo bar

-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] disable grafts during fetch/push/bundle

2014-03-06 Thread Michael Haggerty
On 03/06/2014 04:56 PM, Jeff King wrote:
 On Thu, Mar 06, 2014 at 09:42:46AM +0100, Michael Haggerty wrote:
 
 Replace objects are better than grafts in *almost* every dimension.  The
 exception is that it is dead simple to create grafts, whereas I always
 have to break open the man pages to remember how to create a replace
 object that does the same thing.

 So I think a helpful step towards deprecating grafts would be to offer a
 couple of convenience features to help people kick the grafts habit:
 
 I agree that better tool support would make git replace more pleasant
 to use.
 
 * A tool that converts grafts (i.e., the grafts read from
 $GIT_DIR/info/grafts) into the equivalent replacements.
 
 I don't know if this is strictly necessary, if we make your command
 below pleasant to use. I.e., it should just be:
 
   while read sha1 parents; do
 git replace --graft $sha1 $parents
   done .git/info/grafts
 
 We can wrap that in git replace --convert-grafts, but I do not think
 grafts are so common that there would be a big demand for it.

It's probably easier to wrap it than to explain to Windows users what
they have to do.

 * A tool that creates a new replacement object that is the equivalent of
 a graft.  I.e., it should do, using replace references, the equivalent
 of the following command:

   echo SHA1 [PARENT1...] $GIT_DIR/info/grafts

 These features could be added to git replace or could be built into a
 new git grafts command.
 
 I think it would be nice to have a set of mode options for
 git-replace to do basic editing of a sha1 and install the result
 (technically you could split the editing into a separate command, but I
 do not see the point in editing a sha1 and then _not_ replacing it).

If modifying without replacing is needed, it would be pretty easy to add
an option --stdout that writes the SHA1 of the modified object to stdout
instead of creating a replace reference.  That way what you want 95% of
the time is the default but there is still an escape hatch.

 Perhaps:
 
   # pretty-print sha1 based on type, start $EDITOR, create a
   # type-appropriate object from the result (e.g., using hash-object,
   # mktree, or mktag), and then set up the object as a replacement for
   # SHA1
   git replace --edit SHA1
 
   # ditto, but replace the $EDITOR step with the parent list
   git replace --graft SHA1 PARENT1 PARENT2
 
   # ...or remove entries from a tree
   git replace --remove-entry SHA1 foo bar

I like this idea a lot, especially the pretty-printer round-tripping.

git replace could support some of the options that git filter-branch
can take, like --env-filter, --msg-filter, etc. (at least if the target
is a commit object).

All of this would make it possible to build up the changes that you want
to integrate via filter-branch piecemeal instead of having to have a
single monster filter-branch invocation.  For example,

for c in $(git rev-list --all --before=2007-01-01
--author=root@localhost)
do
git replace --env-filter 'export AUTHOR_EMAIL=j...@example.com' $c
done
# Make some more changes to other commits...
# And when everything is done and checked:
git filter-branch --all --tag-name-filter=cat

To me this is easier to construct than the equivalent filter-branch
invocation, and can be faster because its processing can be more easily
limited to the commits that need it.  Of course to really gain speed,
there should be a C program that bakes in replace references by
traversing the object tree rather than processing each commit
separately, like filter-branch.  I predict that this approach would have
most of the speed of BFG.

Michael

-- 
Michael Haggerty
mhag...@alum.mit.edu
http://softwareswirl.blogspot.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 v3] commit.c: Replace starts_with() with skip_prefix()

2014-03-06 Thread Karthik Nayak
Replace all instances of starts_with() by skip_prefix(),
which can not only be used to check presence of a prefix,
but also used further on as it returns the string after the prefix,
if the prefix is present. And also manages to do, what the current
code does in two steps.

Signed-off-by: Karthik Nayak karthik@gmail.com
---
Hello Eric,
In this patch, I have:
1. Fixed the improper placement of buf_date , initialised to a NULL string.
2. Fixed whitespace.
3. Better naming as per your suggestion.
4. Fixed the initilisation before the if statement.
Thanks for your suggestion.
---
 commit.c | 22 +++---
 1 file changed, 11 insertions(+), 11 deletions(-)

diff --git a/commit.c b/commit.c
index 6bf4fe0..4144e00 100644
--- a/commit.c
+++ b/commit.c
@@ -553,6 +553,7 @@ static void record_author_date(struct author_date_slab 
*author_date,
struct ident_split ident;
char *date_end;
unsigned long date;
+   const char *buf_date;
 
if (!commit-buffer) {
unsigned long size;
@@ -565,15 +566,15 @@ static void record_author_date(struct author_date_slab 
*author_date,
for (buf = commit-buffer ? commit-buffer : buffer;
 buf;
 buf = line_end + 1) {
+   buf_date = skip_prefix(buf, author );
line_end = strchrnul(buf, '\n');
-   if (!starts_with(buf, author )) {
+   if (!buf_date) {
if (!line_end[0] || line_end[1] == '\n')
return; /* end of header */
continue;
}
-   if (split_ident_line(ident,
-buf + strlen(author ),
-line_end - (buf + strlen(author ))) ||
+   if (split_ident_line(ident, buf_date,
+line_end - buf_date) ||
!ident.date_begin || !ident.date_end)
goto fail_exit; /* malformed author line */
break;
@@ -1098,6 +1099,7 @@ int parse_signed_commit(const unsigned char *sha1,
char *buffer = read_sha1_file(sha1, type, size);
int in_signature, saw_signature = -1;
char *line, *tail;
+   const char *gpg_sig;
 
if (!buffer || type != OBJ_COMMIT)
goto cleanup;
@@ -1113,9 +1115,9 @@ int parse_signed_commit(const unsigned char *sha1,
next = next ? next + 1 : tail;
if (in_signature  line[0] == ' ')
sig = line + 1;
-   else if (starts_with(line, gpg_sig_header) 
-line[gpg_sig_header_len] == ' ')
-   sig = line + gpg_sig_header_len + 1;
+   else if ((gpg_sig = skip_prefix(line, gpg_sig_header))
+  gpg_sig[0] == ' ')
+   sig = gpg_sig + 1;
if (sig) {
strbuf_add(signature, sig, next - sig);
saw_signature = 1;
@@ -1193,10 +1195,8 @@ static void parse_gpg_output(struct signature_check 
*sigc)
for (i = 0; i  ARRAY_SIZE(sigcheck_gpg_status); i++) {
const char *found, *next;
 
-   if (starts_with(buf, sigcheck_gpg_status[i].check + 1)) {
-   /* At the very beginning of the buffer */
-   found = buf + strlen(sigcheck_gpg_status[i].check + 1);
-   } else {
+   found = skip_prefix(buf, sigcheck_gpg_status[i].check + 1);
+   if (!found) {
found = strstr(buf, sigcheck_gpg_status[i].check);
if (!found)
continue;
-- 
1.9.0.138.g2de3478

--
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


Testing for commit reachability through plumbing commands

2014-03-06 Thread Martin Langhoff
I have a shell script that trims old history on a cronjob. This is for
a repo that is used to track reports that have limited life (like
logs). Old history is trimmed with grafts pointing to an empty root
commit.

Right now, info/graft grows unbound. I am looking for a way to trim
unreachable grafts, I would like to be able to say something like:

 git is-reachable treeish

Grepping through docs and existing code hasn't helped, but perhaps I'm
missing something obvious...

This repository has a couple hundred branches (one per server
tracked). For a single branch, I can picture a relatively easy
approach with git merge-base.

thanks!



m
-- 
 martin.langh...@gmail.com
 -  ask interesting questions
 - don't get distracted with shiny stuff  - working code first
 ~ http://docs.moodle.org/en/User:Martin_Langhoff
--
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] disable grafts during fetch/push/bundle

2014-03-06 Thread Jeff King
On Thu, Mar 06, 2014 at 05:41:27PM +0100, Michael Haggerty wrote:

  We can wrap that in git replace --convert-grafts, but I do not think
  grafts are so common that there would be a big demand for it.
 
 It's probably easier to wrap it than to explain to Windows users what
 they have to do.

How would Windows users get a graft file in the first-place? There's no
GUI for it! ;)

It should be easy to do --convert-grafts, though, and I think it fits
into the scheme we're discussing below.

  I think it would be nice to have a set of mode options for
  git-replace to do basic editing of a sha1 and install the result
  (technically you could split the editing into a separate command, but I
  do not see the point in editing a sha1 and then _not_ replacing it).
 
 If modifying without replacing is needed, it would be pretty easy to add
 an option --stdout that writes the SHA1 of the modified object to stdout
 instead of creating a replace reference.  That way what you want 95% of
 the time is the default but there is still an escape hatch.

Agreed. I had originally though that perhaps something like this should
be part of hash-object, and that replace should farm out the work.
But thinking on it more, it doesn't really make sense as part of
hash-object.

  Perhaps:
  
# pretty-print sha1 based on type, start $EDITOR, create a
# type-appropriate object from the result (e.g., using hash-object,
# mktree, or mktag), and then set up the object as a replacement for
# SHA1
git replace --edit SHA1

Here's a rough series that gets us this far:

  [1/4]: replace: refactor command-mode determination
  [2/4]: replace: use OPT_CMDMODE to handle modes
  [3/4]: replace: factor object resolution out of replace_object
  [4/4]: replace: add --edit option

It shouldn't be too hard to do --graft or --convert-grafts on top.

I also noticed that doing:

git replace foo foo

is less than friendly (we notice the cycle, but just barf). It's
especially easy to do with git replace --edit, if you just exit the
editor without making changes.  Or if you make changes to an
already-replaced object to revert it back, in which case we would want
to notice and delete the replacement.

So I think we want to have git replace foo foo silently converted into
git replace -d foo (but without an error if there is no existing
replacement), and then --edit will just do the right thing, as it's
built on top.

I also noticed that the diff engine does not play well with replacements
of blobs. When we are diffing the trees, we see that the sha1 for path
foo is the same on either side, and do not look further, even though
feeding those sha1s to builtin_diff would fetch the replacements.  I
think compare_tree_entry would have to learn lookup_replace_object (and
I suspect it would make tree diffs noticeably slower when you have even
one replace ref).

 git replace could support some of the options that git filter-branch
 can take, like --env-filter, --msg-filter, etc. (at least if the target
 is a commit object).
 
 All of this would make it possible to build up the changes that you want
 to integrate via filter-branch piecemeal instead of having to have a
 single monster filter-branch invocation.  For example,

Right. I was tempted to suggest that, too, but I think it can get rather
tricky, as you need to replace in a loop, and sometimes the exact
objects you need aren't obvious.  For example, a common use of
--index-filter is to remove a single file. But to remove
foo/bar/baz, you would need to loop over each commit, find the tree
for foo/bar, and then remove the baz entry in 

Still, I really like the workflow of having decent replace tools,
followed by cementing the changes into place with a filter-branch
run (which, btw, does not yet know how to cement trees and blobs into
place). It lets you work on the filtering incrementally, and even share
or work collaboratively on it by pushing refs/replace).

And as you mention, it could be a heck of a lot faster than what we have
now.

-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


[RFC/PATCH 1/4] replace: refactor command-mode determination

2014-03-06 Thread Jeff King
The git-replace command has three modes: listing, deleting,
and replacing. The first two are selected explicitly. If
none is selected, we fallback to listing when there are no
arguments, and replacing otherwise.

Let's figure out up front which operation we are going to
do, before getting into the application logic. That lets us
simplify our option checks (e.g., we currently have to check
whether a useless --force is given both along with an
explicit list, as well as with an implicit one).

This saves some lines, makes the logic easier to follow, and
will facilitate further cleanups.

Signed-off-by: Jeff King p...@peff.net
---
 builtin/replace.c | 14 ++
 1 file changed, 6 insertions(+), 8 deletions(-)

diff --git a/builtin/replace.c b/builtin/replace.c
index 2336325..6a0e8bd 100644
--- a/builtin/replace.c
+++ b/builtin/replace.c
@@ -182,12 +182,16 @@ int cmd_replace(int argc, const char **argv, const char 
*prefix)
 
argc = parse_options(argc, argv, prefix, options, git_replace_usage, 0);
 
+   if (!list  !delete)
+   if (!argc)
+   list = 1;
+
if (list  delete)
usage_msg_opt(-l and -d cannot be used together,
  git_replace_usage, options);
 
-   if (format  delete)
-   usage_msg_opt(--format and -d cannot be used together,
+   if (format  !list)
+   usage_msg_opt(--format cannot be used when not listing,
  git_replace_usage, options);
 
if (force  (list || delete))
@@ -207,9 +211,6 @@ int cmd_replace(int argc, const char **argv, const char 
*prefix)
if (argc != 2)
usage_msg_opt(bad number of arguments,
  git_replace_usage, options);
-   if (format)
-   usage_msg_opt(--format cannot be used when not 
listing,
- git_replace_usage, options);
return replace_object(argv[0], argv[1], force);
}
 
@@ -217,9 +218,6 @@ int cmd_replace(int argc, const char **argv, const char 
*prefix)
if (argc  1)
usage_msg_opt(only one pattern can be given with -l,
  git_replace_usage, options);
-   if (force)
-   usage_msg_opt(-f needs some arguments,
- git_replace_usage, options);
 
return list_replace_refs(argv[0], format);
 }
-- 
1.8.5.2.500.g8060133

--
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 2/4] replace: use OPT_CMDMODE to handle modes

2014-03-06 Thread Jeff King
By using OPT_CMDMODE, the mutual exclusion between modes is
taken care of for us. It also makes it easy for us to
maintain a single variable with the mode, which makes its
intent more clear. We can use a single switch() to make sure
we have covered all of the modes.

This ends up breaking even in code size, but the win will be
much bigger when we start adding more modes.

Signed-off-by: Jeff King p...@peff.net
---
 builtin/replace.c | 49 +
 1 file changed, 25 insertions(+), 24 deletions(-)

diff --git a/builtin/replace.c b/builtin/replace.c
index 6a0e8bd..0b5cb17 100644
--- a/builtin/replace.c
+++ b/builtin/replace.c
@@ -168,11 +168,17 @@ static int replace_object(const char *object_ref, const 
char *replace_ref,
 
 int cmd_replace(int argc, const char **argv, const char *prefix)
 {
-   int list = 0, delete = 0, force = 0;
+   int force = 0;
const char *format = NULL;
+   enum {
+   MODE_UNSPECIFIED = 0,
+   MODE_LIST,
+   MODE_DELETE,
+   MODE_REPLACE
+   } cmdmode = MODE_UNSPECIFIED;
struct option options[] = {
-   OPT_BOOL('l', list, list, N_(list replace refs)),
-   OPT_BOOL('d', delete, delete, N_(delete replace refs)),
+   OPT_CMDMODE('l', list, cmdmode, N_(list replace refs), 
MODE_LIST),
+   OPT_CMDMODE('d', delete, cmdmode, N_(delete replace refs), 
MODE_DELETE),
OPT_BOOL('f', force, force, N_(replace the ref if it 
exists)),
OPT_STRING(0, format, format, N_(format), N_(use this 
format)),
OPT_END()
@@ -182,42 +188,37 @@ int cmd_replace(int argc, const char **argv, const char 
*prefix)
 
argc = parse_options(argc, argv, prefix, options, git_replace_usage, 0);
 
-   if (!list  !delete)
-   if (!argc)
-   list = 1;
+   if (!cmdmode)
+   cmdmode = argc ? MODE_REPLACE : MODE_DELETE;
 
-   if (list  delete)
-   usage_msg_opt(-l and -d cannot be used together,
- git_replace_usage, options);
-
-   if (format  !list)
+   if (format  cmdmode != MODE_LIST)
usage_msg_opt(--format cannot be used when not listing,
  git_replace_usage, options);
 
-   if (force  (list || delete))
-   usage_msg_opt(-f cannot be used with -d or -l,
+   if (force  cmdmode != MODE_REPLACE)
+   usage_msg_opt(-f only makes sense when writing a replacement,
  git_replace_usage, options);
 
-   /* Delete refs */
-   if (delete) {
+   switch (cmdmode) {
+   case MODE_DELETE:
if (argc  1)
usage_msg_opt(-d needs at least one argument,
  git_replace_usage, options);
return for_each_replace_name(argv, delete_replace_ref);
-   }
 
-   /* Replace object */
-   if (!list  argc) {
+   case MODE_REPLACE:
if (argc != 2)
usage_msg_opt(bad number of arguments,
  git_replace_usage, options);
return replace_object(argv[0], argv[1], force);
-   }
 
-   /* List refs, even if list is not set */
-   if (argc  1)
-   usage_msg_opt(only one pattern can be given with -l,
- git_replace_usage, options);
+   case MODE_LIST:
+   if (argc  1)
+   usage_msg_opt(only one pattern can be given with -l,
+ git_replace_usage, options);
+   return list_replace_refs(argv[0], format);
 
-   return list_replace_refs(argv[0], format);
+   default:
+   die(BUG: invalid cmdmode %d, (int)cmdmode);
+   }
 }
-- 
1.8.5.2.500.g8060133

--
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 3/4] replace: factor object resolution out of replace_object

2014-03-06 Thread Jeff King
As we add new options that operate on objects before
replacing them, we'll want to be able to feed raw sha1s
straight into replace_object. Split replace_object into the
object-resolution part and the actual replacement.

Signed-off-by: Jeff King p...@peff.net
---
 builtin/replace.c | 26 ++
 1 file changed, 18 insertions(+), 8 deletions(-)

diff --git a/builtin/replace.c b/builtin/replace.c
index 0b5cb17..a090302 100644
--- a/builtin/replace.c
+++ b/builtin/replace.c
@@ -123,19 +123,17 @@ static int delete_replace_ref(const char *name, const 
char *ref,
return 0;
 }
 
-static int replace_object(const char *object_ref, const char *replace_ref,
- int force)
+static int replace_object_sha1(const char *object_ref,
+  unsigned char object[20],
+  const char *replace_ref,
+  unsigned char repl[20],
+  int force)
 {
-   unsigned char object[20], prev[20], repl[20];
+   unsigned char prev[20];
enum object_type obj_type, repl_type;
char ref[PATH_MAX];
struct ref_lock *lock;
 
-   if (get_sha1(object_ref, object))
-   die(Failed to resolve '%s' as a valid ref., object_ref);
-   if (get_sha1(replace_ref, repl))
-   die(Failed to resolve '%s' as a valid ref., replace_ref);
-
if (snprintf(ref, sizeof(ref),
 refs/replace/%s,
 sha1_to_hex(object))  sizeof(ref) - 1)
@@ -166,6 +164,18 @@ static int replace_object(const char *object_ref, const 
char *replace_ref,
return 0;
 }
 
+static int replace_object(const char *object_ref, const char *replace_ref, int 
force)
+{
+   unsigned char object[20], repl[20];
+
+   if (get_sha1(object_ref, object))
+   die(Failed to resolve '%s' as a valid ref., object_ref);
+   if (get_sha1(replace_ref, repl))
+   die(Failed to resolve '%s' as a valid ref., replace_ref);
+
+   return replace_object_sha1(object_ref, object, replace_ref, repl, 
force);
+}
+
 int cmd_replace(int argc, const char **argv, const char *prefix)
 {
int force = 0;
-- 
1.8.5.2.500.g8060133

--
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 4/4] replace: add --edit option

2014-03-06 Thread Jeff King
This allows you to run:

git replace --edit SHA1

to get dumped in an editor with the contents of the object
for SHA1. The result is then read back in and used as a
replace object for SHA1. The writing/reading is
type-aware, so you get to edit ls-tree output rather than
the binary tree format.

Missing documentation and tests.

Signed-off-by: Jeff King p...@peff.net
---
Besides missing docs and tests, we might find that we want to factor the
code a little differently when we start adding other helpers (like
--graft). I will probably push this forward at some point, but I'm not
planning on working on it for the rest of the day, so if you want to
pick it up as a base in the meantime and try --graft, --env-filter,
or anything else clever on top, please go ahead.

 builtin/replace.c | 110 +-
 1 file changed, 109 insertions(+), 1 deletion(-)

diff --git a/builtin/replace.c b/builtin/replace.c
index a090302..3ed5f75 100644
--- a/builtin/replace.c
+++ b/builtin/replace.c
@@ -12,6 +12,7 @@
 #include builtin.h
 #include refs.h
 #include parse-options.h
+#include run-command.h
 
 static const char * const git_replace_usage[] = {
N_(git replace [-f] object replacement),
@@ -176,6 +177,105 @@ static int replace_object(const char *object_ref, const 
char *replace_ref, int f
return replace_object_sha1(object_ref, object, replace_ref, repl, 
force);
 }
 
+/*
+ * Write the contents of the object named by sha1 to the file filename,
+ * pretty-printed for human editing based on its type.
+ */
+static void export_object(const unsigned char *sha1, const char *filename)
+{
+   const char *argv[] = { cat-file, -p, NULL, NULL };
+   struct child_process cmd = { argv };
+   int fd;
+
+   fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0666);
+   if (fd  0)
+   die_errno(unable to open %s for writing, filename);
+
+   argv[2] = sha1_to_hex(sha1);
+   cmd.git_cmd = 1;
+   cmd.out = fd;
+
+   if (run_command(cmd))
+   die(cat-file reported failure);
+
+   close(fd);
+}
+
+/*
+ * Read a previously-exported (and possibly edited) object back from 
filename,
+ * interpreting it as type, and writing the result to the object database.
+ * The sha1 of the written object is returned via sha1.
+ */
+static void import_object(unsigned char *sha1, enum object_type type,
+ const char *filename)
+{
+   int fd;
+
+   fd = open(filename, O_RDONLY);
+   if (fd  0)
+   die_errno(unable to open %s for reading, filename);
+
+   if (type == OBJ_TREE) {
+   const char *argv[] = { mktree, NULL };
+   struct child_process cmd = { argv };
+   struct strbuf result = STRBUF_INIT;
+
+   cmd.argv = argv;
+   cmd.git_cmd = 1;
+   cmd.in = fd;
+   cmd.out = -1;
+
+   if (start_command(cmd))
+   die(unable to spawn mktree);
+
+   if (strbuf_read(result, cmd.out, 41)  0)
+   die_errno(unable to read from mktree);
+   close(cmd.out);
+
+   if (finish_command(cmd))
+   die(mktree reported failure);
+   if (get_sha1_hex(result.buf, sha1)  0)
+   die(mktree did not return an object name);
+   } else {
+   struct stat st;
+   int flags = HASH_FORMAT_CHECK | HASH_WRITE_OBJECT;
+
+   if (fstat(fd, st)  0)
+   die_errno(unable to fstat %s, filename);
+   if (index_fd(sha1, fd, st, type, NULL, flags)  0)
+   die(unable to write object to database);
+   /* index_fd close()s fd for us */
+   }
+
+   /*
+* No need to close(fd) here; both run-command and index-fd
+* will have done it for us.
+*/
+}
+
+static int edit_and_replace(const char *object_ref, int force)
+{
+   char *tmpfile = git_pathdup(REPLACE_EDITOBJ);
+   enum object_type type;
+   unsigned char old[20], new[20];
+
+   if (get_sha1(object_ref, old)  0)
+   die(Not a valid object name: '%s', object_ref);
+
+   type = sha1_object_info(old, NULL);
+   if (type  0)
+   die(unable to get object type for %s, sha1_to_hex(old));
+
+   export_object(old, tmpfile);
+   if (launch_editor(tmpfile, NULL, NULL)  0)
+   die(editing object file failed);
+   import_object(new, type, tmpfile);
+
+   free(tmpfile);
+
+   return replace_object_sha1(object_ref, old, replacement, new, force);
+}
+
 int cmd_replace(int argc, const char **argv, const char *prefix)
 {
int force = 0;
@@ -184,11 +284,13 @@ int cmd_replace(int argc, const char **argv, const char 
*prefix)
MODE_UNSPECIFIED = 0,
MODE_LIST,
MODE_DELETE,
+   MODE_EDIT,

Re: [BUG] Halt during fetch on MacOS

2014-03-06 Thread Junio C Hamano
Conley Owens c...@android.com writes:

 On Fri, Feb 28, 2014 at 3:26 PM, Conley Owens c...@android.com wrote:
 $ git --version  # This is just the git from MacPorts
 git version 1.8.5.5
 $ sw_vers
 ProductName:Mac OS X
 ProductVersion: 10.8.5
 BuildVersion:   12F45

 OK, I've tried using my own build from master, and I still get the same 
 results.

 I've done a little more investigation and discovered it always hangs at:
 `atexit(notify_parent);` in `run-command.c:start_command`
 when running:
 trace: run_command: 'git-remote-https' 'aosp'
 'https://android.googlesource.com/platform/external/tinyxml2'

 Could this have to do with the atexit implementation?  (eg. limit on
 the number of functions that can be registered, etc)

Thanks.

An interesting theory indeed.  I read that an implementation is
supposed to take at least ATEXIT_MAX (32) calls to atexit(3); while
I do think we register functions with atexit(3) from multiple places
in our code, I doubt we would be making that many.

 $ cc -v
 Apple clang version 4.1 (tags/Apple/clang-421.11.66) (based on LLVM 3.1svn)
 Target: x86_64-apple-darwin12.5.0
 Thread model: posix
--
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] upload-pack: send shallow info over stdin to pack-objects

2014-03-06 Thread Junio C Hamano
Nguyễn Thái Ngọc Duy  pclo...@gmail.com writes:

 From: Duy Nguyen pclo...@gmail.com

 Before cdab485 (upload-pack: delegate rev walking in shallow fetch to
 pack-objects - 2013-08-16) upload-pack does not write to the source
 repository. cdab485 starts to write $GIT_DIR/shallow_XX if it's a
 shallow fetch, so the source repo must be writable.

 git:// servers do not need write access to repos and usually don't
 have it, which means cdab485 breaks shallow clone over git://

 Instead of using a temporary file as the media for shallow points, we
 can send them over stdin to pack-objects as well. Prepend shallow
 SHA-1 with --shallow so pack-objects knows what is
 what.

 read_object_list_from_stdin() does not accept --shallow lines because
 upload-pack never uses that code. When upload-pack does, then it can
 learn about --shallow lines.

 Signed-off-by: Nguyễn Thái Ngọc Duy pclo...@gmail.com
 ---
  OK new approach, stop creating shallow_XX in upload-pack.

Thanks.

I like what I see in this patch, but I wonder if we can essentially
revert that temporary shallow file patch and replace it with the
same (or a similar) mechanism uniformly?

On the receive-pack side, the comment at the bottom of
preprare_shallow_update() makes it clear that, if we wanted to use
hooks, we cannot avoid having the proposed new shallow-file in a
temporary file, which is unfortunate.  Do we have a similar issue on
hooks on the upload-pack side?


  builtin/pack-objects.c   |  7 +++
  shallow.c|  2 ++
  t/t5537-fetch-shallow.sh | 13 +
  upload-pack.c| 21 -
  4 files changed, 34 insertions(+), 9 deletions(-)

Nothing for Documentation/ anywhere?

 diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c
 index c733379..79e848e 100644
 --- a/builtin/pack-objects.c
 +++ b/builtin/pack-objects.c
 @@ -2467,6 +2467,13 @@ static void get_object_list(int ac, const char **av)
   write_bitmap_index = 0;
   continue;
   }
 + if (starts_with(line, --shallow )) {
 + unsigned char sha1[20];
 + if (get_sha1_hex(line + 10, sha1))
 + die(not an SHA-1 '%s', line + 10);
 + register_shallow(sha1);
 + continue;
 + }
   die(not a rev '%s', line);
   }
   if (handle_revision_arg(line, revs, flags, 
 REVARG_CANNOT_BE_FILENAME))
 diff --git a/shallow.c b/shallow.c
 index bbc98b5..41ff4a0 100644
 --- a/shallow.c
 +++ b/shallow.c
 @@ -33,6 +33,8 @@ int register_shallow(const unsigned char *sha1)
   graft-nr_parent = -1;
   if (commit  commit-object.parsed)
   commit-parents = NULL;
 + if (is_shallow == -1)
 + is_shallow = 1;
   return register_commit_graft(graft, 0);
  }
  
 diff --git a/t/t5537-fetch-shallow.sh b/t/t5537-fetch-shallow.sh
 index 3ae9092..a980574 100755
 --- a/t/t5537-fetch-shallow.sh
 +++ b/t/t5537-fetch-shallow.sh
 @@ -173,4 +173,17 @@ EOF
   )
  '
  
 +test_expect_success POSIXPERM,SANITY 'shallow fetch from a read-only repo' '
 + cp -R .git read-only.git 
 + find read-only.git -print | xargs chmod -w 
 + test_when_finished find read-only.git -type d -print | xargs chmod +w 
 
 + git clone --no-local --depth=2 read-only.git from-read-only 
 + git --git-dir=from-read-only/.git log --format=%s actual 
 + cat expect EOF 
 +add-1-back
 +4
 +EOF
 + test_cmp expect actual
 +'
 +
  test_done
 diff --git a/upload-pack.c b/upload-pack.c
 index 0c44f6b..a5c50e4 100644
 --- a/upload-pack.c
 +++ b/upload-pack.c
 @@ -70,6 +70,14 @@ static ssize_t send_client_data(int fd, const char *data, 
 ssize_t sz)
   return sz;
  }
  
 +static int write_one_shallow(const struct commit_graft *graft, void *cb_data)
 +{
 + FILE *fp = cb_data;
 + if (graft-nr_parent == -1)
 + fprintf(fp, --shallow %s\n, sha1_to_hex(graft-sha1));
 + return 0;
 +}
 +
  static void create_pack_file(void)
  {
   struct child_process pack_objects;
 @@ -81,12 +89,10 @@ static void create_pack_file(void)
   const char *argv[12];
   int i, arg = 0;
   FILE *pipe_fd;
 - char *shallow_file = NULL;
  
   if (shallow_nr) {
 - shallow_file = setup_temporary_shallow(NULL);
   argv[arg++] = --shallow-file;
 - argv[arg++] = shallow_file;
 + argv[arg++] = ;
   }
   argv[arg++] = pack-objects;
   argv[arg++] = --revs;
 @@ -114,6 +120,9 @@ static void create_pack_file(void)
  
   pipe_fd = xfdopen(pack_objects.in, w);
  
 + if (shallow_nr)
 + for_each_commit_graft(write_one_shallow, pipe_fd);
 +
   for (i = 0; i  want_obj.nr; i++)
   fprintf(pipe_fd, %s\n,
   

Re: [RFC/PATCH 2/4] replace: use OPT_CMDMODE to handle modes

2014-03-06 Thread Jeff King
On Thu, Mar 06, 2014 at 07:35:19PM +0100, Christian Couder wrote:

  +   if (!cmdmode)
  +   cmdmode = argc ? MODE_REPLACE : MODE_DELETE;
 
 Shouldn't it be MODE_LIST instead of MODE_DELETE?

Argh, yes, thank you for catching. My original iteration used chars like
'd' and 'l' (similar to other uses of OPT_CMDMODE). I switched it at the
last minute to an enum, and somehow thinko'd that completely (and
obviously did not run the tests again afterwards).

-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] disable grafts during fetch/push/bundle

2014-03-06 Thread Junio C Hamano
Jeff King p...@peff.net writes:

 I also noticed that the diff engine does not play well with replacements
 of blobs. When we are diffing the trees, we see that the sha1 for path
 foo is the same on either side, and do not look further, even though
 feeding those sha1s to builtin_diff would fetch the replacements.

Sorry, I do not quite understand.

In git diff A B -- path, if the object name recorded for A:path
and B:path are the same, but the replacement mechanism maps the
object name for that blob object to some other blob object, wouldn't
the result be empty because both sides replace to the same thing
anyway?
--
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] disable grafts during fetch/push/bundle

2014-03-06 Thread Jeff King
On Thu, Mar 06, 2014 at 11:00:08AM -0800, Junio C Hamano wrote:

 Jeff King p...@peff.net writes:
 
  I also noticed that the diff engine does not play well with replacements
  of blobs. When we are diffing the trees, we see that the sha1 for path
  foo is the same on either side, and do not look further, even though
  feeding those sha1s to builtin_diff would fetch the replacements.
 
 Sorry, I do not quite understand.
 
 In git diff A B -- path, if the object name recorded for A:path
 and B:path are the same, but the replacement mechanism maps the
 object name for that blob object to some other blob object, wouldn't
 the result be empty because both sides replace to the same thing
 anyway?

Oh, right, I was being stupid. I did:

  git replace --edit HEAD:some-file

and expected git show to find the diff. But that doesn't make sense.
On top of that, I need to do:

  git replace --edit HEAD^{tree}

to replace the sha1 of the entry in the tree. In which case diff would
find it just fine.

-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: Rewriting git history during git-svn conversion

2014-03-06 Thread Robert Dailey
On Tue, Mar 4, 2014 at 4:56 AM, Thomas Ferris Nicolaisen
tfn...@gmail.com wrote:
 On Mon, Mar 3, 2014 at 7:38 PM, Robert Dailey rcdailey.li...@gmail.com 
 wrote:

 Is it safe to do this while still using git svn fetch? Will it
 properly continue to convert SVN commits on top of my rewritten
 history? If not, what changes can I make after I run the commands
 linked by the URL above so that git svn continues to work normally?


 I think it's OK. git-svn doesn't continuously verify the integrity of
 history already converted, I believe.

 Just try it out, it worked fine in a little demo setup I made
 (although I used rebase -i instead of filter-branch):

 git svn clone .. #maybe clone a little test repository to speed up the testing
 git filter-branch ... #remove unwanted files
 git svn fetch #this should work

 On a related note, maybe you'll enjoy my git-svn demos  ideas here:
 http://www.tfnico.com/presentations/git-and-subversion


So I did try this out. I did a 'fitler-branch', and afterwards I am
unable to do a `git svn fetch`:

$ git svn fetch
fatal: Invalid revision range cf641cf687fc41b769f296af6e4345dd6a8a6d7d
rev-list --pretty=raw --reverse
cf641cf687fc41b769f296af6e4345dd6a8a6d7d..refs/remotes/svn/trunk --:
command returned error: 128

I have a TON of branches, so I need some small command or script that
is able to go through each branch and update the metadata to tell it
what the new (rewritten) HEAD commit on each branch is. I'm assuming
that's the problem (git svn data is referring to old SHA of each
remote tracking branch).

If there is more to it than this please let me know. Thanks so far for
everyone's help.
--
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: Testing for commit reachability through plumbing commands

2014-03-06 Thread Andreas Schwab
Martin Langhoff martin.langh...@gmail.com writes:

 I have a shell script that trims old history on a cronjob. This is for
 a repo that is used to track reports that have limited life (like
 logs). Old history is trimmed with grafts pointing to an empty root
 commit.

 Right now, info/graft grows unbound. I am looking for a way to trim
 unreachable grafts, I would like to be able to say something like:

  git is-reachable treeish

 Grepping through docs and existing code hasn't helped, but perhaps I'm
 missing something obvious...

Does git fsck --unreachable --no-reflogs help?

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


Re: RFC GSoC idea: git configuration caching (needs co-mentor!)

2014-03-06 Thread Junio C Hamano
Michael Haggerty mhag...@alum.mit.edu writes:

 I just wrote up the idea that fell out of the discussion [1] about the
 other configuration features that I proposed.  As far as I am concerned,
 it can be merged as soon as somebody volunteers as a co-mentor.  The
 idea is embodied in a pull request against the git.github.io repository
 [2]; the text is also appended below for your convenience.

 Michael

 [1] http://article.gmane.org/gmane.comp.version-control.git/242952
 [2] https://github.com/git/git.github.io/pull/7

 ### git configuration API improvements

 There are many places in Git that need to read a configuration value.
 Currently, each such site calls `git_config()`, which reads and parses
 the configuration files every time that it is called.  This is
 wasteful, because it results in the configuration files being
 processed multiple times during a single `git` invocation.  It also
 prevents the implementation of potential new features, like adding
 syntax to allow a configuration file to unset a previously-set value.

 This goal of this project is to make configuration work as follows:

 * Read the configuration from files once and cache the results in an
   appropriate data structure in memory.

 * Change `git_config()` to iterate through the pre-read values in
   memory rather than re-reading the configuration files.

 * Add new API calls that allow the cache to be inquired easily and
   efficiently.  Rewrite other functions like `git_config_int()` to be
   cache-aware.

Are you sure about the second sentence of this item is what you
want?

git_config_type(name, value) are all about parsing value (string
or NULL) as type, return the parsed value or complain against a
bad value for name.  They do not care where these name and
value come from right now, and there is no reason for them to
start caring about caching.  They will still be the underlying
helper functions the git_config() callbacks will depend on even
after the second item in your list happens.

A set of new API calls would look more like this, I would think:

extern int git_get_config_string_multi(const char *, int *, const char 
***);
const char **values;
int num_values;

if (git_get_config_string_multi(sample.str, num_values, values))
return -1;
printf([sample]\n);
for (i = 0; i  num_values; i++)
printf(  str = %s\n, value[i]);
printf(\n);
free(values);

with a singleton wrapper that may be in essense:

const char *git_get_config_string(const char *name)
{
const char **values, *result;
int num_values;

if (git_get_config_string_multi(sample.str, num_values, 
values))
return NULL;
result = num_values ? values[num_values - 1] : NULL;
free(values);
return result;
}

that implements the last one wins semantics.  The real thing would
need to avoid allocation and free overhead.

 * Rewrite callers to use the new API wherever possible.

 You will need to consider how to handle other config API entry points
 like `git_config_early()` and `git_config_from_file()`, as well as how
 to invalidate the cache correctly in the case that the configuration
 is changed while `git` is executing.

 See
 [this mailing list
 thread](http://article.gmane.org/gmane.comp.version-control.git/242952)
 for some discussion about this and related ideas.

  - Language: C
  - Difficulty: medium
  - Possible mentors: Michael Haggerty
--
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: Testing for commit reachability through plumbing commands

2014-03-06 Thread Martin Langhoff
On Thu, Mar 6, 2014 at 2:17 PM, Andreas Schwab sch...@linux-m68k.org wrote:
 Does git fsck --unreachable --no-reflogs help?

Well, my script, called regularly, does:

 - adds grafts
 - git repack -AFfd (which unpacks unreachable objects)
 - git prune --expire now

 hmm, I guess could prune the grafts using git fsck --unreachable
--no-reflogs before pruning the objects themselves.

we'll find out if it works :-)



m
-- 
 martin.langh...@gmail.com
 -  ask interesting questions
 - don't get distracted with shiny stuff  - working code first
 ~ http://docs.moodle.org/en/User:Martin_Langhoff
--
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 v4] Replace memcpy with hashcpy when dealing hash copy globally

2014-03-06 Thread Junio C Hamano
Sun He sunheeh...@gmail.com writes:

 hashcpy() can keep the abstraction of object name behind it.

Do we really want to change the phrasing you took the above from to
say *can* keep?

Providing the object name abstraction is the whole point of the
function, so of course it can keep it, but that goes without
saying---it was the sole reason why it was invented in the first
place.

 Use it instead of memcpy() with hard-coded 20-byte length when
 moving object names between pieces of memory.
 We can benefit from it, when we switch to another hash algorithm,
 eg. MD5, by just fixing the hashcpy().

fix can be used in two scenarios, I think.  Something is broken
and you fix it, or something keeps changing and you force it not to
change.  I do not think either applies to hashcpy().  Perhaps
updating, if we really wanted to say it, but because this change
is not about preparing us to any planned switch of hash function,
I'd suggest dropping those two lines starting from We can benefit
from

 Leave ppc/sha1.c as it is, because the function is about the
 SHA-1 hash algorithm whose output is and will always be 20-byte.

Correct.
--
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/RFC] git-gui: Add a 'recursive' checkbox in the clone menu.

2014-03-06 Thread Jens Lehmann
Am 06.03.2014 01:15, schrieb Henri GEIST:
 Le mercredi 05 mars 2014 à 19:00 +0100, Jens Lehmann a écrit :
 Am 05.03.2014 00:01, schrieb Henri GEIST:
 - Wouldn't it be easier to pass the '--recurse-submodules
   option to the git clone call for the superproject instead
   of adding the _do_clone_submodules() function doing a
   subsequent git submodule update --init --recursive? That
   is also be more future proof with respect to the autoclone
   config option we have in mind (which would add that behavior
   for git clone itself, making the call you added redundant).
 
 That is what I planned to do at beginning.
 But git-gui never call git clone anywhere.
 It make the clone step by step with a long and complicated list of
 commands just like a Tcl rewrite of git-clone.
 Have a look on the function _do_clone2 in choose_repository.tcl.

You're right, it does fetch followed by read-tree ... so my
proposal doesn't make much sense here, sorry for bothering you
without checking the source first.

 As I suspect there should be a good reason for this that I did not
 understand I have choose to not refactoring it.

That makes sense. Shawn, could you shed some light on why clone
is coded again using plumbing in git gui instead of just calling
the clone command?

 And in fact looking in the code 'git clone --recursive' do nothing
 else than calling 'git submodule update --init --recursive' like I
 have done to complete this rewrite of 'git-clone'.

Yep. Note to self: Port everything we add to clone to git gui too.
--
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] commit.c: Replace starts_with() with skip_prefix()

2014-03-06 Thread Junio C Hamano
We already have 147972b1 (commit.c: use skip_prefix() instead of
starts_with(), 2014-03-04) that covers the record_author_date() and
parse_gpg_output(), don't we?


--
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] commit.c: Replace starts_with() with skip_prefix()

2014-03-06 Thread Junio C Hamano
Karthik Nayak karthik@gmail.com writes:

 @@ -1098,6 +1099,7 @@ int parse_signed_commit(const unsigned char *sha1,
   char *buffer = read_sha1_file(sha1, type, size);
   int in_signature, saw_signature = -1;
   char *line, *tail;
 + const char *gpg_sig;
  
   if (!buffer || type != OBJ_COMMIT)
   goto cleanup;
 @@ -1113,9 +1115,9 @@ int parse_signed_commit(const unsigned char *sha1,
   next = next ? next + 1 : tail;
   if (in_signature  line[0] == ' ')
   sig = line + 1;
 - else if (starts_with(line, gpg_sig_header) 
 -  line[gpg_sig_header_len] == ' ')
 - sig = line + gpg_sig_header_len + 1;
 + else if ((gpg_sig = skip_prefix(line, gpg_sig_header))
 +gpg_sig[0] == ' ')
 + sig = gpg_sig + 1;

I am not sure if this hunk is a great improvement, as we know the
length of what we are skipping in the gpg_sig_header_len constant
that is used throughout this file.
--
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 GSoC idea: git configuration caching (needs co-mentor!)

2014-03-06 Thread Jeff King
On Thu, Mar 06, 2014 at 11:24:18AM -0800, Junio C Hamano wrote:

  * Add new API calls that allow the cache to be inquired easily and
efficiently.  Rewrite other functions like `git_config_int()` to be
cache-aware.
 
 Are you sure about the second sentence of this item is what you
 want?
 
 git_config_type(name, value) are all about parsing value (string
 or NULL) as type, return the parsed value or complain against a
 bad value for name.  They do not care where these name and
 value come from right now, and there is no reason for them to
 start caring about caching.  They will still be the underlying
 helper functions the git_config() callbacks will depend on even
 after the second item in your list happens.

Yeah, I agree we want a _new_ set of helpers for retrieving values in a
non-callback way. We could call those helpers git_config_int (and
rename the existing pure functions), but I'd rather not, as it simply
invites confusion with the existing ones.

 A set of new API calls would look more like this, I would think:
 
   extern int git_get_config_string_multi(const char *, int *, const char 
 ***);

Not important at this stage, but I was hoping we could keep the names of
the new helpers shorter. :)

   const char *git_get_config_string(const char *name)
 {
   const char **values, *result;
 int num_values;
 
   if (git_get_config_string_multi(sample.str, num_values, 
 values))
   return NULL;
 result = num_values ? values[num_values - 1] : NULL;
 free(values);
   return result;
   }
 
 that implements the last one wins semantics.  The real thing would
 need to avoid allocation and free overhead.

One of the things that needs to be figured out by the student is the
format of the internal cache. I had actually envisioned a mapping of
keys to values, where values are represented as a full list of strings.
Then your string_multi can just return a pointer to that list, and a
last-one-wins lookup can grab the final value, with no allocation or
ownership complexity. We'd lose the relative order of different config
keys, but those should never be important (only the order of single
keys, but that is reflected in the order of the value list).

Another approach would be to actually represent the syntax tree of the
config file in memory. That would make lookups of individual keys more
expensive, but would enable other manipulation. E.g., if your syntax
tree included nodes for comments and other non-semantic constructs, then
we can use it for a complete rewrite. And git config becomes:

  1. Read the tree.

  2. Perform operations on the tree (add nodes, delete nodes, etc).

  3. Write out the tree.

and things like remove the section header when the last item in the
section is removed become trivial during step 2.

But comparing those approaches is something for the student to figure
out, I think.

-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] submodule : Add --no-separate-git-dir option to add and update command.

2014-03-06 Thread Jens Lehmann
Am 06.03.2014 02:25, schrieb Henri GEIST:
 Le mercredi 05 mars 2014 à 19:13 +0100, Jens Lehmann a écrit :
 Am 03.03.2014 21:34, schrieb Henri GEIST:
 Le lundi 03 mars 2014 à 17:45 +, Jens Lehmann a écrit :
 Am 03.03.2014 14:47, schrieb Henri GEIST:
 This new option prevent git submodule add|update to clone the missing
 submodules with the --separate-git-dir option.
 Then the submodule will be regular repository and their gitdir will not
 be placed in the superproject gitdir/modules directory.

 And what is your motivation for this? After all submodules containing
 a .git directory are second class citizens (because they can never be
 safely removed by regular git commands).


 I recognize most people will prefer to have the .git directory separate.
 And I do not intend to make this option the default.

 My reasons are:

   - As it is not clearly stated in the doc that the gitdir is separate.
 The first time I have copied one module to an USB key I had a big
 surprise.

 Oops! Could you please help us by hinting how the documentation
 could be improved here?

 
 Of course.
 There is nothing in Documentation/git-submodule.txt to inform that submodules
 clones are different from regular clones.
 I will write and propose a patch for the documentation.
 But maybe in a new thread.

Thanks!

   - This will not change anything for people not using it.

 I do not agree, as they'll be seeing a new option and might use
 it to go backward as Junio explained in his answer.

   - I use an other patch which I plane to send later which enable multiple
 level of superproject to add a gitlink to the same submodule.
 And in this case the superproject containing the separate gitdir will be
 arbitrary and depend on the processing order of the
 'git submodule update --recursive' command.

 I don't understand that. How is that different from using different
 names (and thus different separate gitdirs) for that duplicated
 submodule? After all, the .git directory is just moved somewhere
 else in the superproject's work tree, and as the name defaults to
 the path of the submodule ...

 
 I think I should give an example.
 If I have a hierarchy like this :
 
 superproject/submodule/subsubmodule
 
 What I often do is:
 
 superproject -- submodule -- subsubmodule
  | ^
  '-'
 
 Where '--' is a gitlink.
 
 
 That mean .gitmodules and index of the superproject contain both submodule and
 submodule/subsubmodule.

Wow, that shouldn't even work (as everything inside submodule
shouldn't be part of the superproject but must be contained in
the submodule itself). Do the git submodule script and other
git commands like git status work for you in such setups?

 And also mean (and that is the point) subsubmodule is a direct 'child' of both
 superproject and submodule.

Which I think should not be possible. If that works with current
Git I suspect we have a bug to fix ... or does your other patch
make this work?

 In this case where should the separate gitdir of subsubmodule be placed ?
   - In superproject/modules/submodule/subsubmodule ?
   - In superproject/submodule/modules/subsubmodule ?
   - Depending on the 'git submodule update' command order ?
   - Or both ?

It should be placed in .git/modules/submodule/modules/subsubmodule
of the superproject (assuming the subsubmodule is part of the first
level submodule). But in your example that would live in
.git/modules/submodule/subsubmodule (but as mentioned above, I do
not consider this a valid setup because then two repositories would
be responsible for the data inside subsubmodule, which will lead to
lots of trouble).
--
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 GSoc Idea: blame: do not overly favor earlier parents

2014-03-06 Thread Junio C Hamano
When looking at a merge, git blame inspects the blob object names
of all parents and if one of them exactly match the merge result,
pass the entire blame down to that parent.  This is very much in
line with the history simplification done with git log when
traversing a history with merges.

On the other hand, when the blob object in the merge result and none
of the parents match exactly, we let each parent to take as much blame
as they can, starting from the earlier parent, and later parents get
a chance to take blame on the leftover bits.

Combination of the above can lead to an unexpected results.

Let's say that M is a two-parent merge, M^1 == A and M^2 == B, and
that M:path == B:path != A:path (i.e. the merge result matches its
second parent exactly).  The entire contents of the path is blamed
to the history leading to B; the history leading to A but not
involved in B will not get any blame.

Now, imagine if you amend M to create N, to add a single line at the
end of path.  M:path != N:path but there is very small difference
between the two.  That means B:path != N:path but the difference
between this merged result and the second parent is very small.

Because we give the chance to get blamed for the whole thing to the
first parent, however, A will grab blame for all the lines that are
common between A:path and B:path.  For the lines that are the same
between M:path and N:path, ideally, we should get identical results,
but it results in a very inconsistent behaviour.

Update blame.c::pass_blame() and give an option to arrange the list
of scapegoats in the order that are similar to the end result, in
order to address this issue.  That way, when blaming N:path, we will
inspect B:path first and let it grab as much blame, as it would happen
when we started the blame for M: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] submodule : Add --no-separate-git-dir option to add and update command.

2014-03-06 Thread Henri GEIST
Le jeudi 06 mars 2014 à 20:48 +0100, Jens Lehmann a écrit :
 Am 06.03.2014 02:25, schrieb Henri GEIST:
  Le mercredi 05 mars 2014 à 19:13 +0100, Jens Lehmann a écrit :
  Am 03.03.2014 21:34, schrieb Henri GEIST:
  Le lundi 03 mars 2014 à 17:45 +, Jens Lehmann a écrit :
  Am 03.03.2014 14:47, schrieb Henri GEIST:
  This new option prevent git submodule add|update to clone the missing
  submodules with the --separate-git-dir option.
  Then the submodule will be regular repository and their gitdir will not
  be placed in the superproject gitdir/modules directory.
 
  And what is your motivation for this? After all submodules containing
  a .git directory are second class citizens (because they can never be
  safely removed by regular git commands).
 
 
  I recognize most people will prefer to have the .git directory separate.
  And I do not intend to make this option the default.
 
  My reasons are:
 
- As it is not clearly stated in the doc that the gitdir is separate.
  The first time I have copied one module to an USB key I had a big
  surprise.
 
  Oops! Could you please help us by hinting how the documentation
  could be improved here?
 
  
  Of course.
  There is nothing in Documentation/git-submodule.txt to inform that 
  submodules
  clones are different from regular clones.
  I will write and propose a patch for the documentation.
  But maybe in a new thread.
 
 Thanks!
 
- This will not change anything for people not using it.
 
  I do not agree, as they'll be seeing a new option and might use
  it to go backward as Junio explained in his answer.
 
- I use an other patch which I plane to send later which enable multiple
  level of superproject to add a gitlink to the same submodule.
  And in this case the superproject containing the separate gitdir will 
  be
  arbitrary and depend on the processing order of the
  'git submodule update --recursive' command.
 
  I don't understand that. How is that different from using different
  names (and thus different separate gitdirs) for that duplicated
  submodule? After all, the .git directory is just moved somewhere
  else in the superproject's work tree, and as the name defaults to
  the path of the submodule ...
 
  
  I think I should give an example.
  If I have a hierarchy like this :
  
  superproject/submodule/subsubmodule
  
  What I often do is:
  
  superproject -- submodule -- subsubmodule
   | ^
   '-'
  
  Where '--' is a gitlink.
  
  
  That mean .gitmodules and index of the superproject contain both submodule 
  and
  submodule/subsubmodule.
 
 Wow, that shouldn't even work (as everything inside submodule
 shouldn't be part of the superproject but must be contained in
 the submodule itself). Do the git submodule script and other
 git commands like git status work for you in such setups?


As I stated above it is the purpose of the other patch that I have not already 
send
to implement this behavior. And that is why it work.
Everything including 'git submodule' and 'git status' work perfectly.
The intent of this patch is only to permit this for gitlinks. Not for regular 
files.
 
  and also mean (and that is the point) subsubmodule is a direct 'child' of 
  both
  superproject and submodule.
 
 Which I think should not be possible. If that works with current
 Git I suspect we have a bug to fix ... or does your other patch
 make this work?

You have no bug on this point without my modification this is not possible.

 
  In this case where should the separate gitdir of subsubmodule be placed ?
- In superproject/modules/submodule/subsubmodule ?
- In superproject/submodule/modules/subsubmodule ?
- Depending on the 'git submodule update' command order ?
- Or both ?
 
 It should be placed in .git/modules/submodule/modules/subsubmodule
 of the superproject (assuming the subsubmodule is part of the first
 level submodule). But in your example that would live in
 .git/modules/submodule/subsubmodule (but as mentioned above, I do
 not consider this a valid setup because then two repositories would
 be responsible for the data inside subsubmodule, which will lead to
 lots of trouble).

That is why a had proposed an option '--no-separate-git-dir'
for 'git submodule add|update' then no repository is responsible for the data
in subsubmodule except subsubmodule itself.




signature.asc
Description: This is a digitally signed message part


Re: RFC GSoc Idea: blame: do not overly favor earlier parents

2014-03-06 Thread David Kastrup
Junio C Hamano gits...@pobox.com writes:

 When looking at a merge, git blame inspects the blob object names
 of all parents and if one of them exactly match the merge result,
 pass the entire blame down to that parent.  This is very much in
 line with the history simplification done with git log when
 traversing a history with merges.

[...]

 Now, imagine if you amend M to create N, to add a single line at the
 end of path.  M:path != N:path but there is very small difference
 between the two.  That means B:path != N:path but the difference
 between this merged result and the second parent is very small.

That sounds very much like

commit d5df1593f27bfceab807242a538cb3fa01256efd
Merge: 7144168 0b4e246
Author: Junio C Hamano gits...@pobox.com
Date:   Fri Feb 28 13:51:19 2014 -0800

Merge branch 'bl/blame-full-history' into pu

By disabling the tree-same optimization (which is consistent with
the default behaviour of git log-family of commands), make git
blame sometimes produce different result from the original code.

Because the git blame output can give result for each line from
only one lineage of the history, however, this can be only useful
when you are lucky---unlike --full-history of git log-family,
where we can show commits from both lineages of histories with an
equal weight.  See $gmane/240392 for more detailed discussion.

* bl/blame-full-history:
  blame: new option --prefer-first to better handle merged cherry-picks

-- 
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: Testing for commit reachability through plumbing commands

2014-03-06 Thread Jeff King
On Thu, Mar 06, 2014 at 12:17:34PM -0500, Martin Langhoff wrote:

 I have a shell script that trims old history on a cronjob. This is for
 a repo that is used to track reports that have limited life (like
 logs). Old history is trimmed with grafts pointing to an empty root
 commit.
 
 Right now, info/graft grows unbound. I am looking for a way to trim
 unreachable grafts, I would like to be able to say something like:
 
  git is-reachable treeish

How about:

git rev-list --objects --all |
cut -d' ' -f1 |
grep $(git rev-parse treeish)

Add --reflog to the rev-list invocation if you want to catch things
referenced by the reflog, too.

If you're looking for a commit, you can drop the --objects, and it
will run much faster.

-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: RFC GSoc Idea: blame: do not overly favor earlier parents

2014-03-06 Thread Junio C Hamano
David Kastrup d...@gnu.org writes:

 Junio C Hamano gits...@pobox.com writes:

 When looking at a merge, git blame inspects the blob object names
 of all parents and if one of them exactly match the merge result,
 pass the entire blame down to that parent.  This is very much in
 line with the history simplification done with git log when
 traversing a history with merges.

 [...]

 Now, imagine if you amend M to create N, to add a single line at the
 end of path.  M:path != N:path but there is very small difference
 between the two.  That means B:path != N:path but the difference
 between this merged result and the second parent is very small.

 That sounds very much like

 commit d5df1593f27bfceab807242a538cb3fa01256efd
 Merge: 7144168 0b4e246
 Author: Junio C Hamano gits...@pobox.com
 Date:   Fri Feb 28 13:51:19 2014 -0800

 Merge branch 'bl/blame-full-history' into pu

That one was an attempt to solve the right issue in a wrong way,
made things worse by breaking the consistency with the history
simplification of git log.

The Idea is to solve it in the way that is still consistent with
the usual history simplification.


--
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] submodule : Add --no-separate-git-dir option to add and update command.

2014-03-06 Thread Jens Lehmann
Am 06.03.2014 21:15, schrieb Henri GEIST:
 Le jeudi 06 mars 2014 à 20:48 +0100, Jens Lehmann a écrit :
 Am 06.03.2014 02:25, schrieb Henri GEIST:
 Le mercredi 05 mars 2014 à 19:13 +0100, Jens Lehmann a écrit :
 Am 03.03.2014 21:34, schrieb Henri GEIST:
   - I use an other patch which I plane to send later which enable multiple
 level of superproject to add a gitlink to the same submodule.
 And in this case the superproject containing the separate gitdir will 
 be
 arbitrary and depend on the processing order of the
 'git submodule update --recursive' command.

 I don't understand that. How is that different from using different
 names (and thus different separate gitdirs) for that duplicated
 submodule? After all, the .git directory is just moved somewhere
 else in the superproject's work tree, and as the name defaults to
 the path of the submodule ...

 I think I should give an example.
 If I have a hierarchy like this :

 superproject/submodule/subsubmodule

 What I often do is:

 superproject -- submodule -- subsubmodule
  | ^
  '-'

 Where '--' is a gitlink.


 That mean .gitmodules and index of the superproject contain both submodule 
 and
 submodule/subsubmodule.

 Wow, that shouldn't even work (as everything inside submodule
 shouldn't be part of the superproject but must be contained in
 the submodule itself). Do the git submodule script and other
 git commands like git status work for you in such setups?
 
 As I stated above it is the purpose of the other patch that I have not 
 already send
 to implement this behavior. And that is why it work.

Ok.

 Everything including 'git submodule' and 'git status' work perfectly.
 The intent of this patch is only to permit this for gitlinks. Not for regular 
 files.

But I still believe that this shouldn't be permitted at all,
no matter if files or submodules are concerned. The pitfalls
files face in such a scenario are pretty much the same for
submodules too.

 and also mean (and that is the point) subsubmodule is a direct 'child' of 
 both
 superproject and submodule.

 Which I think should not be possible. If that works with current
 Git I suspect we have a bug to fix ... or does your other patch
 make this work?
 
 You have no bug on this point without my modification this is not possible.

Glad to hear that.

 In this case where should the separate gitdir of subsubmodule be placed ?
   - In superproject/modules/submodule/subsubmodule ?
   - In superproject/submodule/modules/subsubmodule ?
   - Depending on the 'git submodule update' command order ?
   - Or both ?

 It should be placed in .git/modules/submodule/modules/subsubmodule
 of the superproject (assuming the subsubmodule is part of the first
 level submodule). But in your example that would live in
 .git/modules/submodule/subsubmodule (but as mentioned above, I do
 not consider this a valid setup because then two repositories would
 be responsible for the data inside subsubmodule, which will lead to
 lots of trouble).
 
 That is why a had proposed an option '--no-separate-git-dir'
 for 'git submodule add|update' then no repository is responsible for the 
 data
 in subsubmodule except subsubmodule itself.

As I mentioned in my other email, it doesn't matter at all for
the setup you're describing if the git directory lives under
.git/modules of the superproject or in a .git directory in the
submodule. The problem you're creating with your future patch
is related to the work tree, not the GIT_DIR: subsubmodule
could also be added to and tracked by submodule (as that is
completely unaware of subsubmodule already being tracked by
the superproject). Then you would end up in real trouble, as
superproject and submodule could have differing SHA-1s
recorded for subsubmodule. Don't go there, for just the same
reasons we do not allow that for files.

What is the use case you are trying to solve and why can that
not be handled by adding subsubmodule inside submodule?
--
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] use strchrnul() in place of strchr() and strlen()

2014-03-06 Thread Junio C Hamano
Rohit Mani rohit.m...@outlook.com writes:

 Avoid scanning strings twice, once with strchr() and then with
 strlen(), by using strchrnul(). Update the conditional expressions
 involving the return value of strchrnul() with a check for '\0'.

 Signed-off-by: Rohit Mani rohit.m...@outlook.com
 ---

Nicely done.  I am not sure if you need to say the update the
conditional..., which is a logical consequence of such a conversion
and goes without saying, though.

  cache-tree.c |   16 +++-

This part may overlap with other topics in flight, but I expect the
conflict resolution would be trivial.

 diff --git a/cache-tree.c b/cache-tree.c
 index 0bbec43..21a13cf 100644
 --- a/cache-tree.c
 +++ b/cache-tree.c
 @@ -121,11 +121,11 @@ void cache_tree_invalidate_path(struct cache_tree *it, 
 const char *path)
  
   if (!it)
   return;
 - slash = strchr(path, '/');
 + slash = strchrnul(path, '/');
   it-entry_count = -1;
 - if (!slash) {
 + if (*slash == '\0') {

Let's just say

if (!*slash)

instead; it is more idiomatic (I won't repeat this for other hunks).

   int pos;
 - namelen = strlen(path);
 + namelen = slash - path;

After this if (!*slash), we compute namelen = slash-path.
Perhaps we can lose this assignment and the other one by hoisting it
up before if (!*slash)?

 @@ -564,10 +562,10 @@ static struct cache_tree *cache_tree_find(struct 
 cache_tree *it, const char *pat
 + if (*slash == '\0' || !*slash)

Huh?  The byte pointed at by 'slash' is NUL, or it is NUL???

Other than that, looks good to me.

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] t3200-branch: test setting branch as own upstream

2014-03-06 Thread Jeff King
On Wed, Mar 05, 2014 at 04:31:55PM +0900, Brian Gesiak wrote:

 No test asserts that git branch -u refs/heads/my-branch my-branch
 emits a warning. Add a test that does so.
 
 Signed-off-by: Brian Gesiak modoca...@gmail.com

Thanks, this looks good. Two minor points that may or may not be worth
addressing:

 +test_expect_success '--set-upstream-to shows warning if used to set branch 
 as own upstream' '
 + git branch --set-upstream-to refs/heads/my13 my13 2actual 
 + cat expected EOF 
 +warning: Not setting branch my13 as its own upstream.
 +EOF

If you spell the EOF marker as:

cat expect -\EOF

then:

  1. The shell does not interpolate the contents (it does not matter
 here, but it is a good habit to be in, so we typically do it unless
 there is a need to interpolate).

  2. Using - will strip leading tabs, so the content can be indented
 properly along with the rest of the test.

 + test_i18ncmp expected actual 
 + test_must_fail git config branch.my13.remote 
 + test_must_fail git config branch.my13.merge

I think we could tighten these to:

  test_expect_code 1 git config branch.my13.remote

to eliminate a false-positive success on other config errors. It's
highly improbable for it to ever matter, though (and it looks like we
are not so careful in most other places that call git config looking
for a missing entry, either).

-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 0/6] fix hunk editing with 'commit -p -m'

2014-03-06 Thread Junio C Hamano
Benoit Pierre benoit.pie...@gmail.com writes:

 This patch fixes the fact that hunk editing with 'commit -p -m' does not work:
 GIT_EDITOR is set to ':' to indicate to hooks that no editor will be launched,
 which result in the 'hunk edit' option not launching the editor (and selecting
 the whole hunk).

 The fix consists in deferring the GIT_EDITOR override to the hook subprocess,
 like it's already done for GIT_INDEX_FILE:
 - modify 'run_hook' so the first parameter is the environment to set
 - add a 'run_hook_v' variant that take a va_list
 - add a new 'run_commit_hook' helper (to set both GIT_EDITOR and 
 GIT_INDEX_FILE)

I sense that this is in line with one of the leftover bits items I
keep in http://git-blame.blogspot.com/p/leftover-bits.html,
especially 
http://thread.gmane.org/gmane.comp.version-control.git/192669/focus=192806
;-)

--
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] Halt during fetch on MacOS

2014-03-06 Thread Jeff King
On Thu, Mar 06, 2014 at 10:24:49AM -0800, Junio C Hamano wrote:

  OK, I've tried using my own build from master, and I still get the same 
  results.
 
  I've done a little more investigation and discovered it always hangs at:
  `atexit(notify_parent);` in `run-command.c:start_command`
  when running:
  trace: run_command: 'git-remote-https' 'aosp'
  'https://android.googlesource.com/platform/external/tinyxml2'
 
  Could this have to do with the atexit implementation?  (eg. limit on
  the number of functions that can be registered, etc)
 
 Thanks.
 
 An interesting theory indeed.  I read that an implementation is
 supposed to take at least ATEXIT_MAX (32) calls to atexit(3); while
 I do think we register functions with atexit(3) from multiple places
 in our code, I doubt we would be making that many.

It seems awfully weird that it would _hang_ in such a case, though. That
sounds more like hitting a mutex that's internal to atexit(), or
something similar.

Conley, can you see if dropping that atexit clears up the problem (you
should be OK without it; git will just fail to notice the child's
exec failure with as much detail).

-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] git-prompt.sh: make '+' work for unborn branches

2014-03-06 Thread Maurice Bos
I have no clue why git diff --cached isn't used instead of git
diff-index. I was wondering about it, but I decided I don't know
enough about git and there are probably valid reasons for doing it
this way. Though, replacing it with with git diff --cached seems to
have the exact same behaviour, as far as I tested. That would make the
patch a little prettier, as it doesn't contain the empty tree id any
more:

@@ -407,12 +407,11 @@ __git_ps1 ()
 if [ -n ${GIT_PS1_SHOWDIRTYSTATE-} ] 
[ $(git config --bool bash.showDirtyState) != false ]
 then
-git diff --no-ext-diff --quiet --exit-code || w=*
-if [ -n $short_sha ]; then
-git diff-index --cached --quiet HEAD -- || i=+
-else
+if [ -z $short_sha ]; then
 i=#
 fi
+git diff --no-ext-diff --quiet --exit-code || w=*
+git diff --no-ext-diff --quiet --exit-code --cached || i=$i+
 fi
 if [ -n ${GIT_PS1_SHOWSTASHSTATE-} ] 
[ -r $g/refs/stash ]; then


Unfortunately, I don't know much about git diff-files, so I don't know
whether it could be used instead.

In another version I used myself, I indeed used 'git status
--porcelain' and used regexes /^\w/ /^.\w/ and /\?/ on the output. It
seemed to work fine, but it's a bit stupid that it lists all the files
when it could stop almost directly. An
--extremly-short-porcelain-or-whatever-you-would-call-this option that
would just output whether any file is dirty and/or indexed or
something might be useful, though maybe a bit too specific.
(--summarized ?)

-Maurice-


 2014-03-06 21:40 GMT+01:00 Jeff King p...@peff.net:

 On Thu, Mar 06, 2014 at 12:05:24AM +0100, Maurice Bos wrote:

  For unborn branches, it now compares the index against the empty tree.
  (Just like git status does.)

 Sounds sensible, although...

  - git diff --no-ext-diff --quiet --exit-code || w=*
  - if [ -n $short_sha ]; then
  - git diff-index --cached --quiet HEAD -- || 
  i=+
  - else

 I notice the old code uses git diff immediately above. If we used git
 diff --cached here, too, I think it already knows about this empty-tree
 magic.

 That being said, it seems odd that we are using git diff in the first
 place, and not git diff-files. This seems to blame all the way back to
 738a94a, when the functionality was added in the first place. Am I
 missing some reason we can't use diff-files (maybe we want the
 index-refreshing side effect)?

 -Peff

 PS I thought at first that this could just use git status --porcelain,
which also knows the empty-tree trick.  But that command has no way
to quit early on the first change.
--
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] commit: fix patch hunk editing with commit -p -m

2014-03-06 Thread Junio C Hamano
Benoit Pierre benoit.pie...@gmail.com writes:

 +int run_commit_hook(int editor_is_used, const char *index_file, const char 
 *name, ...)
 +{
 + const char *hook_env[3] =  { NULL };
 + char index[PATH_MAX];
 + va_list args;
 + int ret;
 +
 + snprintf(index, sizeof(index), GIT_INDEX_FILE=%s, index_file);
 + hook_env[0] = index;
 +
 + /*
 +  * Let the hook know that no editor will be launched.
 +  */
 + if (!editor_is_used)
 + hook_env[1] = GIT_EDITOR=:;
 +
 + va_start(args, name);
 + ret = run_hook_v(hook_env, name, args);

 diff --git a/run-command.c b/run-command.c
 index 3914d9c..4e9be12 100644
 --- a/run-command.c
 +++ b/run-command.c
 @@ -760,13 +760,11 @@ char *find_hook(const char *name)
   return path;
  }
  
 -int run_hook(const char *index_file, const char *name, ...)
 +int run_hook_v(const char *const *env, const char *name, va_list args)
  {

I think you named it as foo_v() for this takes va_list in a way
similar to the v in execv(), but this also takes environment, so
perhaps we want to say ve instead?

Other than that, I like it---I admit that I am biased that I
essentially did the same earlier but with a _le variant ;-)

 +int run_hook(const char *const *env, const char *name, ...)
 +{

I'd rather not to see this changed in the same commit, so that any
other topic in-flight that adds a new call to run_hook() that expects
to pass the index file as its first parameter will not be broken.

Name it run_hook_le() (name modelled after execle()), and call it in
your change where you add new calls to this function, and add a thin
wrapper run_hook() that preserves the traditional We can pass only
the index-file for new callers we do not even know about on the
topics in flight.

Later we can eradicate callers of run_hook() that treats the index-file
specially, which was a grave mistake in a public API.
--
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 5/6] merge hook tests: fix missing '' in test

2014-03-06 Thread Junio C Hamano
Benoit Pierre benoit.pie...@gmail.com writes:

 Signed-off-by: Benoit Pierre benoit.pie...@gmail.com
 ---

Please have these preparatory fix-ups (i.e. the changes that would
be immediately useful even if it turns out that the main body of the
series were not ready for inclusion) early in the series, not late
as 5th patch of a 6 patch series.

Thanks.

  t/t7505-prepare-commit-msg-hook.sh | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)

 diff --git a/t/t7505-prepare-commit-msg-hook.sh 
 b/t/t7505-prepare-commit-msg-hook.sh
 index ae7b2db..604c06e 100755
 --- a/t/t7505-prepare-commit-msg-hook.sh
 +++ b/t/t7505-prepare-commit-msg-hook.sh
 @@ -189,7 +189,7 @@ test_expect_success 'with failing hook (merge)' '
   git add file 
   rm -f $HOOK 
   git commit -m other 
 - write_script $HOOK -EOF
 + write_script $HOOK -EOF 
   exit 1
   EOF
   git checkout - 
--
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] diff: simplify cpp funcname regex

2014-03-06 Thread Jeff King
On Wed, Mar 05, 2014 at 08:58:26AM +0100, Johannes Sixt wrote:

 Here is a patch that I'm carrying around since... a while.
 What do you think?
 
 The pattern I chose also catches variable definition, not just
 functions. That is what I need, but it hurts grep --function-context
 That's the reason I didn't forward the patch, yet.

If by variable definition you mean:

   struct foo bar = {
  -   old
  +   new
   };

I'd think that would be covered by the existing struct|class|enum.
Though I think we'd want to also allow keywords in front of it, like
static. I suspect the original was more meant to find:

   struct foo {
  -old
  +new
   };

 The parts of the pattern have the following flaws:
 
 - The first part matches an identifier followed immediately by a colon and
   arbitrary text and is intended to reject goto labels and C++ access
   specifiers (public, private, protected). But this pattern also rejects
   C++ constructs, which look like this:
 
 MyClass::MyClass()
 MyClass::~MyClass()
 MyClass::Item MyClass::Find(...

Makes sense. I noticed your fix is to look for end-of-line or comments
afterwards.  Would it be simpler to just check for a non-colon, like:

  !^[ \t]*[A-Za-z_][A-Za-z_0-9]*:($|[^:])

 - The second part matches an identifier followed by a list of qualified
   names (i.e. identifiers separated by the C++ scope operator '::')
 [...]

A tried to keep the looks like a function definition bit in mine, and
yours loosens this quite a bit more. I think that may be OK. That is, I
do not think there is any reason for somebody to do:

void foo() {
call_to_bar();
   -old
   +new
}

That is, nobody would put a function _call_ without indentation. If
something has alphanumerics at the left-most column, then it is probably
interesting no matter what.

 - The third part of the pattern finally matches compound definitions. But
   it forgets about unions and namespaces, and also skips single-line
   definitions
 
 struct random_iterator_tag {};
 
   because no semicolon can occur on the line.

I don't see how that is an interesting line. The point is to find a
block that is surrounding the changes, but that is not surrounding
the lines below.

 Notice that all interesting anchor points begin with an identifier or
 keyword. But since there is a large variety of syntactical constructs after
 the first word, the simplest is to require only this word and accept
 everything else. Therefore, this boils down to a line that begins with a
 letter or underscore (optionally preceded by the C++ scope operator '::'
 to accept functions returning a type anchored at the global namespace).
 Replace the second and third part by a single pattern that picks such a
 line.

Yeah, this bit makes sense to me.

Both yours and mine will find the first line here in things like:

   void foo(void);
  -void bar(void);
  +void bar(int arg);

but I think that is OK. There _isn't_ any interesting surrounding
context here. The current code will sometimes come up with an empty
funcline (which is good), but it may just as easily come up with a
totally bogus funcline in a case like:

   void unrelated(void)
   {
   }

   void foo(void);
  -void bar(void);
  +void bar(int arg);

So trying to be very restrictive and say that doesn't look like a
function does not really buy us anything (and it creates tons of false
negatives, as you documented, because C++ syntax has all kinds of crazy
stuff).

_If_ the backwards search learned to terminate (e.g., seeing the ^}
line and saying well, we can't be inside a function), then such
negative lines might be useful for coming up with an empty funcname
rather than the bogus void foo(void);. But we do not do that
currently, and I do not think it is that useful (the funcname above is
arguably just as or more useful than an empty one).

-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 6/6] merge hook tests: use 'test_must_fail' instead of '!'

2014-03-06 Thread Junio C Hamano
Benoit Pierre benoit.pie...@gmail.com writes:

 Signed-off-by: Benoit Pierre benoit.pie...@gmail.com
 ---
  t/t7505-prepare-commit-msg-hook.sh | 4 ++--
  1 file changed, 2 insertions(+), 2 deletions(-)

 diff --git a/t/t7505-prepare-commit-msg-hook.sh 
 b/t/t7505-prepare-commit-msg-hook.sh
 index 604c06e..1be6cec 100755
 --- a/t/t7505-prepare-commit-msg-hook.sh
 +++ b/t/t7505-prepare-commit-msg-hook.sh
 @@ -167,7 +167,7 @@ test_expect_success 'with failing hook' '
   head=`git rev-parse HEAD` 
   echo more  file 
   git add file 
 - ! GIT_EDITOR=\\$FAKE_EDITOR\ git commit -c $head
 + test_must_fail env GIT_EDITOR=\\$FAKE_EDITOR\ git commit -c $head

Thanks. It is good that you avoided the common pitfall of attempting

GIT_EDITOR=... test_must_fail git commit -c $head;# WRONG

but do we assume everybody has env?

To be portable, we can do this instead.

(
GIT_EDITOR=... 
export GIT_EDITOR 
test_must_fail git commit -c $head
)

--
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 GSoC idea: git configuration caching (needs co-mentor!)

2014-03-06 Thread Michael Haggerty
On 03/06/2014 08:24 PM, Junio C Hamano wrote:
 Michael Haggerty mhag...@alum.mit.edu writes:
 
 I just wrote up the idea that fell out of the discussion [1] about the
 other configuration features that I proposed.  As far as I am concerned,
 it can be merged as soon as somebody volunteers as a co-mentor.  The
 idea is embodied in a pull request against the git.github.io repository
 [2]; the text is also appended below for your convenience.

 Michael

 [1] http://article.gmane.org/gmane.comp.version-control.git/242952
 [2] https://github.com/git/git.github.io/pull/7

 ### git configuration API improvements

 There are many places in Git that need to read a configuration value.
 Currently, each such site calls `git_config()`, which reads and parses
 the configuration files every time that it is called.  This is
 wasteful, because it results in the configuration files being
 processed multiple times during a single `git` invocation.  It also
 prevents the implementation of potential new features, like adding
 syntax to allow a configuration file to unset a previously-set value.

 This goal of this project is to make configuration work as follows:

 * Read the configuration from files once and cache the results in an
   appropriate data structure in memory.

 * Change `git_config()` to iterate through the pre-read values in
   memory rather than re-reading the configuration files.

 * Add new API calls that allow the cache to be inquired easily and
   efficiently.  Rewrite other functions like `git_config_int()` to be
   cache-aware.
 
 Are you sure about the second sentence of this item is what you
 want?
 
 git_config_type(name, value) are all about parsing value (string
 or NULL) as type, return the parsed value or complain against a
 bad value for name.  They do not care where these name and
 value come from right now, and there is no reason for them to
 start caring about caching.  They will still be the underlying
 helper functions the git_config() callbacks will depend on even
 after the second item in your list happens.

You're right of course.  For some reason I had it in my brain that these
functions retrieved *and* parsed values, as opposed to just parsing them.

I just fixed the text and pushed it live.

Michael

-- 
Michael Haggerty
mhag...@alum.mit.edu
http://softwareswirl.blogspot.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


Trust issues with hooks and config files

2014-03-06 Thread Julian Brost
-BEGIN PGP SIGNED MESSAGE-
Hash: SHA256

Hi,

I've noticed some behavior of git that might lead to some security
issues if the user is not aware of this.

Assume we have an evil user on a system, let's call him eve. He
prepares a repository where he allows other user to push changes to.
If he now adds a post-receive hook, git will happly execute it as
whatever user pushes to this repository:

  root@argon /tmp/git-eve # ls -l /tmp/git-eve/hooks/post-receive
  -rwxr-xr-x 1 eve users [...] /tmp/git-eve/hooks/post-receive
  root@argon /tmp/git-root # cat /tmp/git-eve/hooks/post-receive
  #!/bin/sh
  id
  root@argon /tmp/git-root # git push /tmp/git-eve master
  Counting objects: 3, done.
  Writing objects: 100% (3/3), 185 bytes | 0 bytes/s, done.
  Total 3 (delta 0), reused 0 (delta 0)
  remote: uid=0(root) gid=0(root) groups=0(root),[...]
  To /tmp/git-eve
   * [new branch]  master - master

Something similiar might happen if eve adds some alias to the config
file in the repository and grants any other user read access to the
repository. These aliases will be executed when some other user is
running any git command in this repository. Even though git does not
allow defining aliases for existing commands, you might mistype
something, so adding an alias for lg instead of log might succeed:

  root@argon /tmp/git-eve # ls -l /tmp/git-eve/config
  -rw-r--r-- 1 eve users [...] /tmp/git-eve/config
  root@argon /tmp/git-eve # cat config
  [core]
repositoryformatversion = 0
filemode = true
bare = true
  [alias]
lg = !id
  root@argon /tmp/git-eve # git lg
  uid=0(root) gid=0(root) groups=0(root),[...]

This gets even worse if you know something about the aliases your
victim uses, so for example you can override an alias 'l = log'
defined in the user's config with something malicious in the
repository config file.

I'd suggest taking a similar approach as Mercurial [1], i.e. ignoring
configuration files and hooks owned by another user unless the owner
is explicitly trusted.

Regards,
Julian

[1] http://mercurial.selenic.com/wiki/Trust
-BEGIN PGP SIGNATURE-
Version: GnuPG v2.0.22 (GNU/Linux)

iQIcBAEBCAAGBQJTGOz5AAoJECLcYT6QIdBtJLEP/1VPMyRws5IYOVXJDcLukxkh
87RuL6ZCXE9v66VgEmTYYtJx1Umy18YXCx+ufAuJL2xzo/QH/QhWl/npa+U3ac7D
2A/3rXt1PvdzoQeT3514t5ntO9WyquHE2N8Ix+xdxwFo/T+Ve+nDV8/hra9he1Nb
zdldBccyHBDQdEudBLs6tDoJU9fvQ4TAGCGw7CXHCDV4hhyXHt8Nyf9nNOWxXgYh
5QcDs0sj1MCFm5AdN1SOU7FobiwS//Q8QdKdr9O6L18IoUPnSw2a1S2hGJmwQ/IL
Y1nQMdFuSx+4n6KKgUBtlo4WTi38u98FG4N0MXqZOSX7SKDVEOYfF+1W31Trhtuw
KMtojlwBYXsq0CWrW1OQ4Oed91lDGBtLLzF8MSCN1NoG4+Eb/V+RueLzulC5lWU/
IpDr3d14vFBEydHzYY+35P57Rf2Fl5HkXLQzQ0UmROeAmhUVCnduRj4dn35nb47Z
G/73UdgX1FMB4lOD8kD9KX0Sov3XLz4n5u706h+lElapd24wBXlaysWVpsmImuW0
xPLSpX0Dfrtj0sOCvqM0oX40z3bCJ1ibqZOmPGwF0P66DJOOq9sqDYfHlgnvt/qU
pCqsy0+FyCUuGP17UliEWcFAfdzXrUhxkRneQXC8ieX8YSoP4OtjzIPHrsc54s/2
7VR0wCTxaHvd05T8WruK
=kc4p
-END PGP SIGNATURE-
--
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: Re: [PATCH/RFC] git-gui: Add a 'recursive' checkbox in the clone menu.

2014-03-06 Thread Heiko Voigt
On Thu, Mar 06, 2014 at 08:35:48PM +0100, Jens Lehmann wrote:
 Am 06.03.2014 01:15, schrieb Henri GEIST:
  Le mercredi 05 mars 2014 à 19:00 +0100, Jens Lehmann a écrit :
  Am 05.03.2014 00:01, schrieb Henri GEIST:
  - Wouldn't it be easier to pass the '--recurse-submodules
option to the git clone call for the superproject instead
of adding the _do_clone_submodules() function doing a
subsequent git submodule update --init --recursive? That
is also be more future proof with respect to the autoclone
config option we have in mind (which would add that behavior
for git clone itself, making the call you added redundant).
  
  That is what I planned to do at beginning.
  But git-gui never call git clone anywhere.
  It make the clone step by step with a long and complicated list of
  commands just like a Tcl rewrite of git-clone.
  Have a look on the function _do_clone2 in choose_repository.tcl.
 
 You're right, it does fetch followed by read-tree ... so my
 proposal doesn't make much sense here, sorry for bothering you
 without checking the source first.
 
  As I suspect there should be a good reason for this that I did not
  understand I have choose to not refactoring it.
 
 That makes sense. Shawn, could you shed some light on why clone
 is coded again using plumbing in git gui instead of just calling
 the clone command?

I think because git gui is using plumbing everywhere, it is supposed to
be just another porcelain. And I guess that was an intended decision
because porcelain might change its output and break git gui. At least
thats what I inferred.

Cheers Heiko
--
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/6] test patch hunk editing with commit -p -m

2014-03-06 Thread Eric Sunshine
On Thu, Mar 6, 2014 at 9:50 AM, Benoit Pierre benoit.pie...@gmail.com wrote:
 Add (failing) test: with commit changing the environment to let hooks
 now that no editor will be used (by setting GIT_EDITOR to :), the
 edit hunk functionality does not work (no editor is launched and the
 whole hunk is committed).

 Signed-off-by: Benoit Pierre benoit.pie...@gmail.com
 ---
  t/t7513-commit_-p_-m_hunk_edit.sh | 37 +
  1 file changed, 37 insertions(+)
  create mode 100755 t/t7513-commit_-p_-m_hunk_edit.sh

A rather unusual filename.

 diff --git a/t/t7513-commit_-p_-m_hunk_edit.sh 
 b/t/t7513-commit_-p_-m_hunk_edit.sh
 new file mode 100755
 index 000..e0ad905
 --- /dev/null
 +++ b/t/t7513-commit_-p_-m_hunk_edit.sh
 @@ -0,0 +1,37 @@
 +#!/bin/sh
 +
 +test_description='hunk edit with commit -p -m'
 +. ./test-lib.sh
 +
 +if ! test_have_prereq PERL
 +then
 +   skip_all=skipping '$test_description' tests, perl not available
 +   test_done
 +fi
 +
 +test_expect_success 'setup (initial)' '
 +   echo line1 file 
 +   git add file 
 +   git commit -m commit1

Broken -chain.

 +   echo line3 file
 +'
 +
 +test_expect_success 'setup expected' '
 +cat expected EOF
 +diff --git a/file b/file
 +index a29bdeb..c0d0fb4 100644
 +--- a/file
  b/file
 +@@ -1 +1,2 @@
 + line1
 ++line2
 +EOF
 +'

If you use -EOF, you can indent the content you're dumping into
'expected', which can enhance readability. Even better, use -\EOF to
indicate that you don't want interpolation done within the content.

 +test_expect_failure 'edit hunk commit -p -m message' '
 +   echo e | env GIT_EDITOR=sed s/+line3\$/+line2/ -i git commit -p -m 
 commit2 file 
 +   git diff HEAD^ HEAD diff 
 +   test_cmp expected diff
 +'

If you ever add more tests, is it likely that they will be using the
same 'expected' file used by this test? If not, perhaps it makes sense
to move creation of 'expected' into the test itself.

 +test_done
 --
 1.9.0
--
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] submodule : Add --no-separate-git-dir option to add and update command.

2014-03-06 Thread Henri GEIST
Le jeudi 06 mars 2014 à 21:51 +0100, Jens Lehmann a écrit :
 Am 06.03.2014 21:15, schrieb Henri GEIST:
  Le jeudi 06 mars 2014 à 20:48 +0100, Jens Lehmann a écrit :
  Am 06.03.2014 02:25, schrieb Henri GEIST:
  Le mercredi 05 mars 2014 à 19:13 +0100, Jens Lehmann a écrit :
  Am 03.03.2014 21:34, schrieb Henri GEIST:
- I use an other patch which I plane to send later which enable 
  multiple
  level of superproject to add a gitlink to the same submodule.
  And in this case the superproject containing the separate gitdir 
  will be
  arbitrary and depend on the processing order of the
  'git submodule update --recursive' command.
 
  I don't understand that. How is that different from using different
  names (and thus different separate gitdirs) for that duplicated
  submodule? After all, the .git directory is just moved somewhere
  else in the superproject's work tree, and as the name defaults to
  the path of the submodule ...
 
  I think I should give an example.
  If I have a hierarchy like this :
 
  superproject/submodule/subsubmodule
 
  What I often do is:
 
  superproject -- submodule -- subsubmodule
   | ^
   '-'
 
  Where '--' is a gitlink.
 
 
  That mean .gitmodules and index of the superproject contain both 
  submodule and
  submodule/subsubmodule.
 
  Wow, that shouldn't even work (as everything inside submodule
  shouldn't be part of the superproject but must be contained in
  the submodule itself). Do the git submodule script and other
  git commands like git status work for you in such setups?
  
  As I stated above it is the purpose of the other patch that I have not 
  already send
  to implement this behavior. And that is why it work.
 
 Ok.
 
  Everything including 'git submodule' and 'git status' work perfectly.
  The intent of this patch is only to permit this for gitlinks. Not for 
  regular files.
 
 But I still believe that this shouldn't be permitted at all,
 no matter if files or submodules are concerned. The pitfalls
 files face in such a scenario are pretty much the same for
 submodules too.


May be you have a good argument for this belief ?

As for the difference between submodules and regular files
the only difference is in the meaning.
Technically directory are just a special kind of file.
But there day to day use is drastically different of
the use of files which are not directories.
I am not against enabling it for files as well.
I am just unable to imagine a case where it make sens.
A possible solution when someone try to do it is to issue a warning.
We are not able to see any good reason to do this are sure (y/n) ?

  and also mean (and that is the point) subsubmodule is a direct 'child' of 
  both
  superproject and submodule.
 
  Which I think should not be possible. If that works with current
  Git I suspect we have a bug to fix ... or does your other patch
  make this work?
  
  You have no bug on this point without my modification this is not possible.
 
 Glad to hear that.
 
  In this case where should the separate gitdir of subsubmodule be placed ?
- In superproject/modules/submodule/subsubmodule ?
- In superproject/submodule/modules/subsubmodule ?
- Depending on the 'git submodule update' command order ?
- Or both ?
 
  It should be placed in .git/modules/submodule/modules/subsubmodule
  of the superproject (assuming the subsubmodule is part of the first
  level submodule). But in your example that would live in
  .git/modules/submodule/subsubmodule (but as mentioned above, I do
  not consider this a valid setup because then two repositories would
  be responsible for the data inside subsubmodule, which will lead to
  lots of trouble).
  
  That is why a had proposed an option '--no-separate-git-dir'
  for 'git submodule add|update' then no repository is responsible for the 
  data
  in subsubmodule except subsubmodule itself.
 
 As I mentioned in my other email, it doesn't matter at all for
 the setup you're describing if the git directory lives under
 .git/modules of the superproject or in a .git directory in the
 submodule. The problem you're creating with your future patch
 is related to the work tree, not the GIT_DIR: subsubmodule
 could also be added to and tracked by submodule (as that is
 completely unaware of subsubmodule already being tracked by
 the superproject). Then you would end up in real trouble, as
 superproject and submodule could have differing SHA-1s
 recorded for subsubmodule. Don't go there, for just the same
 reasons we do not allow that for files.
 

In fact it mater.
Because multiples checkout of superproject and submodules in versions
where subsubmodule is present and not.
subsubmodule could have been clone one time by submodule and one time
by superproject.
And then if they are cloned with --separate-gitdir subsubmodule can
have two gitdirs in superproject/modules/submodule/subsubmodule and
in superproject/submodule/modules/subsubmodule.
Only 

gc/repack has no option to lose grafted parents

2014-03-06 Thread Martin Langhoff
Back in 
http://git.661346.n2.nabble.com/PATCH-0-2-Make-git-gc-more-robust-with-regard-to-grafts-td3310281.html
we got gc/repack to be safer for users who might be shooting
themselves in the foot.

Would a patch be welcome to add --discard-grafted-objects ? or
--keep-real-parents=idontthinkso ?

cheers,



m
-- 
 martin.langh...@gmail.com
 -  ask interesting questions
 - don't get distracted with shiny stuff  - working code first
 ~ http://docs.moodle.org/en/User:Martin_Langhoff
--
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/6] test patch hunk editing with commit -p -m

2014-03-06 Thread Junio C Hamano
Eric Sunshine sunsh...@sunshineco.com writes:

 +test_expect_failure 'edit hunk commit -p -m message' '
 +   echo e | env GIT_EDITOR=sed s/+line3\$/+line2/ -i git commit -p -m 
 commit2 file 
 +   git diff HEAD^ HEAD diff 
 +   test_cmp expected diff
 +'

 If you ever add more tests, is it likely that they will be using the
 same 'expected' file used by this test? If not, perhaps it makes sense
 to move creation of 'expected' into the test itself.

All good points.  Also, I think we try to use expect (not
expected) vs actual (not diff) in most of the tests.

--
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] Halt during fetch on MacOS

2014-03-06 Thread Conley Owens
On Thu, Mar 6, 2014 at 1:16 PM, Jeff King p...@peff.net wrote:
 On Thu, Mar 06, 2014 at 10:24:49AM -0800, Junio C Hamano wrote:

  OK, I've tried using my own build from master, and I still get the same 
  results.
 
  I've done a little more investigation and discovered it always hangs at:
  `atexit(notify_parent);` in `run-command.c:start_command`
  when running:
  trace: run_command: 'git-remote-https' 'aosp'
  'https://android.googlesource.com/platform/external/tinyxml2'
 
  Could this have to do with the atexit implementation?  (eg. limit on
  the number of functions that can be registered, etc)

 Thanks.

 An interesting theory indeed.  I read that an implementation is
 supposed to take at least ATEXIT_MAX (32) calls to atexit(3); while
 I do think we register functions with atexit(3) from multiple places
 in our code, I doubt we would be making that many.

 It seems awfully weird that it would _hang_ in such a case, though. That
 sounds more like hitting a mutex that's internal to atexit(), or
 something similar.

You are correct that it's a mutex internal to atexit.  The crazy thing
is that there is only one thread sitting and waiting for it.

(gdb) thread apply all bt

Thread 1 (process 71053):
#0  0x7fff8cb67122 in __psynch_mutexwait ()
#1  0x7fff833d0dcd in pthread_mutex_lock ()
#2  0x7fff8d4a77e0 in LockHelper::LockHelper ()
#3  0x7fff8d4a8d0a in dladdr ()
#4  0x7fff83412260 in atexit ()
#5  0x00010597b35e in start_command (cmd=0x7fe1cd801b30) at
run-command.c:374
#6  0x000105998959 in get_helper (transport=value temporarily
unavailable, due to optimizations) at transport-helper.c:142
#7  0x0001059970bd in get_refs_list (transport=0x7fe1cd801370,
for_push=0) at transport-helper.c:954
#8  0x00010599635d in transport_get_remote_refs
(transport=0x7fe1cd801370) at transport.c:1227
#9  0x0001058b7469 in get_ref_map [inlined] () at
/Users/android-build/cco3/master/git/builtin/fetch.c:278
#10 0x0001058b7469 in fetch_one (remote=value temporarily
unavailable, due to optimizations, argc=value temporarily
unavailable, due to optimizations, argv=0x7fff) at
builtin/fetch.c:862
#11 0x0001058b6f22 in cmd_fetch (argc=value temporarily
unavailable, due to optimizations, argv=value temporarily
unavailable, due to optimizations, prefix=0x0) at
builtin/fetch.c:1158
#12 0x000105890acc in run_builtin [inlined] () at
/Users/android-build/cco3/master/git/git.c:314
#13 0x000105890acc in handle_builtin (argc=3, argv=0x7fff5a370648)
at git.c:487
#14 0x0001058906c1 in main (argc=3, av=value temporarily
unavailable, due to optimizations) at git.c:533
===


 Conley, can you see if dropping that atexit clears up the problem (you
 should be OK without it; git will just fail to notice the child's
 exec failure with as much detail).

Yes, I'm unable to reproduce the issue after dropping atexit.


 -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 v3] upload-pack: send shallow info over stdin to pack-objects

2014-03-06 Thread Duy Nguyen
On Fri, Mar 7, 2014 at 1:37 AM, Junio C Hamano gits...@pobox.com wrote:
 I like what I see in this patch, but I wonder if we can essentially
 revert that temporary shallow file patch and replace it with the
 same (or a similar) mechanism uniformly?

Using --shallow-file is uniform.The only downside is temporary file.
Without it you'll need to think of a way (probably different way for
each command) to feed shallow info to.

 On the receive-pack side, the comment at the bottom of
 preprare_shallow_update() makes it clear that, if we wanted to use
 hooks, we cannot avoid having the proposed new shallow-file in a
 temporary file, which is unfortunate.  Do we have a similar issue on
 hooks on the upload-pack side?

No. I don't think we have hooks on upload-pack.

  builtin/pack-objects.c   |  7 +++
  shallow.c|  2 ++
  t/t5537-fetch-shallow.sh | 13 +
  upload-pack.c| 21 -
  4 files changed, 34 insertions(+), 9 deletions(-)

 Nothing for Documentation/ anywhere?

Heh git-pack-objects.txt never described stdin format. At least I
searched for --not in it and found none. So I gladly accepted the
situation and skipped doc update :D
-- 
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] *.sh: drop useless use of env

2014-03-06 Thread Junio C Hamano
In a bourne shell script, VAR=VAL command is sufficient to run
'command' with environment variable VAR set to value VAL without
affecting the environment of the shell itself; there is no reason to
say env VAR=VAL command.

Signed-off-by: Junio C Hamano gits...@pobox.com
---

 * Just something I noticed while reading existing tests...

 t/t1020-subdirectory.sh | 2 +-
 t/t9001-send-email.sh   | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/t/t1020-subdirectory.sh b/t/t1020-subdirectory.sh
index 1e2945e..6902320 100755
--- a/t/t1020-subdirectory.sh
+++ b/t/t1020-subdirectory.sh
@@ -148,7 +148,7 @@ test_expect_success 'GIT_PREFIX for built-ins' '
(
cd dir 
printf change two 
-   env GIT_EXTERNAL_DIFF=./diff git diff ../actual
+   GIT_EXTERNAL_DIFF=./diff git diff ../actual
git checkout -- two
) 
test_cmp expect actual
diff --git a/t/t9001-send-email.sh b/t/t9001-send-email.sh
index 3119c8c..1ecdacb 100755
--- a/t/t9001-send-email.sh
+++ b/t/t9001-send-email.sh
@@ -409,7 +409,7 @@ test_expect_success $PREREQ 'Valid In-Reply-To when 
prompting' '
(echo From Example f...@example.com
 echo To Example t...@example.com
 echo 
-   ) | env GIT_SEND_EMAIL_NOTTY=1 git send-email \
+   ) | GIT_SEND_EMAIL_NOTTY=1 git send-email \
--smtp-server=$(pwd)/fake.sendmail \
$patches 2errors 
! grep ^In-Reply-To:  * msgtxt1



--
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: gc/repack has no option to lose grafted parents

2014-03-06 Thread Junio C Hamano
Martin Langhoff martin.langh...@gmail.com writes:

 Back in 
 http://git.661346.n2.nabble.com/PATCH-0-2-Make-git-gc-more-robust-with-regard-to-grafts-td3310281.html
 we got gc/repack to be safer for users who might be shooting
 themselves in the foot.

 Would a patch be welcome to add --discard-grafted-objects ? or
 --keep-real-parents=idontthinkso ?

 cheers,

Given that we in general frown upon long-term use of grafts (or
replace for that matter), I am not sure if we want to go in that
direction.

Just a knee-jerk reaction, though.
--
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] disable grafts during fetch/push/bundle

2014-03-06 Thread Michael Haggerty
On 03/07/2014 12:01 AM, Philip Oakley wrote:
 From: Jeff King p...@peff.net
 On Thu, Mar 06, 2014 at 05:41:27PM +0100, Michael Haggerty wrote:

  We can wrap that in git replace --convert-grafts, but I do not 
 think
  grafts are so common that there would be a big demand for it.

 It's probably easier to wrap it than to explain to Windows users what
 they have to do.

 How would Windows users get a graft file in the first-place? There's no
 GUI for it! ;)
 
 Now, now... It's dead easy using the git-gui and Notepad++, you can see
 and confirm the sha1's, copy and paste, and the graft file is a very
 easy format, so even wimps (windows, icons, menus, pointers aka mouse)
 folks can do it. (It worked for me when I needed it ;-)

I didn't mean to insult all Windows users in general.  I was only
referring to the fact that since the default Windows command line is not
a POSIX shell, even an experienced Windows user might have trouble
figuring out how to execute a shell loop.  Putting this functionality in
a git command or script, by contrast, would make it work universally, no
fuss, no muss.

Michael

-- 
Michael Haggerty
mhag...@alum.mit.edu
http://softwareswirl.blogspot.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


Re: gc/repack has no option to lose grafted parents

2014-03-06 Thread Martin Langhoff
On Thu, Mar 6, 2014 at 6:26 PM, Junio C Hamano gits...@pobox.com wrote:
 Given that we in general frown upon long-term use of grafts (or
 replace for that matter), I am not sure if we want to go in that
 direction.

 Just a knee-jerk reaction, though.

Fair enough.

If I state my actual goals -- discarding old, uninteresting history,
in a rolling fashion? (periodically using a script that says forget
anything older than one month) -- is there a better way?

The repository is not standalone, it receives pushes from hundreds of
clients, and gets pulled from a couple of clients. All clients are in
sync, in that will be pulling every hour (vs a time window of one
month).

At this stage, and with careful management (ie: custom gc scripts) git
makes for an excellent async log/report transfer tool. We specially
appreciate that it has deep buffer.

cheers,



m
-- 
 martin.langh...@gmail.com
 -  ask interesting questions
 - don't get distracted with shiny stuff  - working code first
 ~ http://docs.moodle.org/en/User:Martin_Langhoff
--
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] disable grafts during fetch/push/bundle

2014-03-06 Thread Junio C Hamano
Michael Haggerty mhag...@alum.mit.edu writes:

 I didn't mean to insult all Windows users in general.  I was only
 referring to the fact that since the default Windows command line is not
 a POSIX shell, even an experienced Windows user might have trouble
 figuring out how to execute a shell loop.  Putting this functionality in
 a git command or script, by contrast, would make it work universally, no
 fuss, no muss.

;-)

Be it graft or replace, I do not think we want to invite people to
use these mechansims too lightly to locally rewrite their history
willy-nilly without fixing their mistakes at the object layer with
commit --amend, rebase, bfg, etc. in the longer term.  So in
that sense, adding a command to make it easy is not something I am
enthusiastic about.

On the other hand, if the user does need to use graft or replace
(perhaps to prepare for casting the fixed history in stone with
filter-branch), it would be good to help them avoid making mistakes
while doing so and tool support may be a way to do so.

So, ... I am of two minds.

--
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] disable grafts during fetch/push/bundle

2014-03-06 Thread Philip Oakley

From: Michael Haggerty mhag...@alum.mit.edu

On 03/07/2014 12:01 AM, Philip Oakley wrote:

From: Jeff King p...@peff.net

On Thu, Mar 06, 2014 at 05:41:27PM +0100, Michael Haggerty wrote:

 We can wrap that in git replace --convert-grafts, but I do not 
  

think
 grafts are so common that there would be a big demand for it.

It's probably easier to wrap it than to explain to Windows users 
what

they have to do.


How would Windows users get a graft file in the first-place? There's 
no

GUI for it! ;)


Now, now... It's dead easy using the git-gui and Notepad++, you can 
see

and confirm the sha1's, copy and paste, and the graft file is a very
easy format, so even wimps (windows, icons, menus, pointers aka 
mouse)

folks can do it. (It worked for me when I needed it ;-)


I didn't mean to insult all Windows users in general.  I was only
referring to the fact that since the default Windows command line is 
not

a POSIX shell, even an experienced Windows user might have trouble
figuring out how to execute a shell loop.


I'd missed that aspect about the shell loop. I was mainly pointing out 
current awkwardness of creating the replace object, relative to grafts - 
There was an initial attempt by Christian, but it became quite hard to 
make it robust to sha1's embedded in commit messages.



 Putting this functionality in
a git command or script, by contrast, would make it work universally, 
no

fuss, no muss.

Michael

--
Michael Haggerty
mhag...@alum.mit.edu
http://softwareswirl.blogspot.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


Re: [PATCH 6/6] merge hook tests: use 'test_must_fail' instead of '!'

2014-03-06 Thread Junio C Hamano
Junio C Hamano gits...@pobox.com writes:

 Benoit Pierre benoit.pie...@gmail.com writes:

 Signed-off-by: Benoit Pierre benoit.pie...@gmail.com
 ---
  t/t7505-prepare-commit-msg-hook.sh | 4 ++--
  1 file changed, 2 insertions(+), 2 deletions(-)

 diff --git a/t/t7505-prepare-commit-msg-hook.sh 
 b/t/t7505-prepare-commit-msg-hook.sh
 index 604c06e..1be6cec 100755
 --- a/t/t7505-prepare-commit-msg-hook.sh
 +++ b/t/t7505-prepare-commit-msg-hook.sh
 @@ -167,7 +167,7 @@ test_expect_success 'with failing hook' '
  head=`git rev-parse HEAD` 
  echo more  file 
  git add file 
 -! GIT_EDITOR=\\$FAKE_EDITOR\ git commit -c $head
 +test_must_fail env GIT_EDITOR=\\$FAKE_EDITOR\ git commit -c $head

 Thanks. It is good that you avoided the common pitfall of attempting

   GIT_EDITOR=... test_must_fail git commit -c $head;# WRONG

 but do we assume everybody has env?

It turns out that the answer to this question seems to be yes, we
already do.; so the patch is probably OK as-is.

Thanks.

 To be portable, we can do this instead.

   (
   GIT_EDITOR=... 
   export GIT_EDITOR 
 test_must_fail git commit -c $head
   )
--
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: gc/repack has no option to lose grafted parents

2014-03-06 Thread Duy Nguyen
On Fri, Mar 7, 2014 at 6:36 AM, Martin Langhoff
martin.langh...@gmail.com wrote:
 On Thu, Mar 6, 2014 at 6:26 PM, Junio C Hamano gits...@pobox.com wrote:
 Given that we in general frown upon long-term use of grafts (or
 replace for that matter), I am not sure if we want to go in that
 direction.

 Just a knee-jerk reaction, though.

 Fair enough.

 If I state my actual goals -- discarding old, uninteresting history,
 in a rolling fashion? (periodically using a script that says forget
 anything older than one month) -- is there a better way?

Convert it to a shallow repository? Either you clone it and do fetch
--depth=XXX  prune, or you manipulate $GIT_DIR/shallow directly
then prune (no worse than editing grafts, I think).
-- 
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


[micro] Use 'env' on test_must_fail as appropriate

2014-03-06 Thread Junio C Hamano
Because VAR=VAL command is sufficient to run 'command' with
environment variable VAR set to value VAL without affecting the
environment of the shell itself, but we cannot do the same with a
shell function (most notably, test_must_fail), we have subshell
invocations with multiple lines like this:

... 
(
VAR=VAL 
export VAR 
test_must_fail git command
) 
...

which could be expressed as

... 
test_must_fail env VAR=VAL git comand 
...

Find and shorten such constructs in existing test scripts.

Note that I am not 100% convinced myself that it is a good idea to
do this, so please do not add this to the list without seeing it
discussed.

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 v3] upload-pack: send shallow info over stdin to pack-objects

2014-03-06 Thread Duy Nguyen
On Thu, Mar 6, 2014 at 3:49 PM, Nguyễn Thái Ngọc Duy pclo...@gmail.com wrote:
 diff --git a/t/t5537-fetch-shallow.sh b/t/t5537-fetch-shallow.sh
 index 3ae9092..a980574 100755
 --- a/t/t5537-fetch-shallow.sh
 +++ b/t/t5537-fetch-shallow.sh
 @@ -173,4 +173,17 @@ EOF
 )
  '

 +test_expect_success POSIXPERM,SANITY 'shallow fetch from a read-only repo' '
 +   cp -R .git read-only.git 
 +   find read-only.git -print | xargs chmod -w 
 +   test_when_finished find read-only.git -type d -print | xargs chmod 
 +w 
 +   git clone --no-local --depth=2 read-only.git from-read-only 
 +   git --git-dir=from-read-only/.git log --format=%s actual 
 +   cat expect EOF 
 +add-1-back
 +4
 +EOF
 +   test_cmp expect actual
 +'
 +
  test_done

It's a separate issue, but maybe we should add a similar test case for
non-shallow clone from a read-only repo too. Are there any other
operations that should work well on read-only repos?
-- 
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] show_ident_date: fix always-false conditional

2014-03-06 Thread Eric Sunshine
1dca155fe3fa (log: handle integer overflow in timestamps, 2014-02-24)
assigns the result of strtol() to an 'int' and then checks it against
LONG_MIN and LONG_MAX, indicating underflow or overflow, even though
'int' may not be large enough to represent those values.

On Mac, the compiler complains:

warning: comparison of constant 9223372036854775807 with
  expression of type 'int' is always false
  [-Wtautological-constant-out-of-range-compare]
  if (tz == LONG_MAX || tz == LONG_MIN)

Similarly for the LONG_MIN case. Fix this.

Signed-off-by: Eric Sunshine sunsh...@sunshineco.com
---

Alternately, the result of strtol() could be assigned temporarily to a
'long', compared against LONG_MIN and LONG_MAX, and then assigned to the
'int' tz variable. I chose the 'errno' approach instead because its
dead obvious, even to the most casual reader who hasn't checked the
strtol() man page, that it's handling a conversion failure. However, I
could go either way.

This patch is atop 'next'.

 pretty.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/pretty.c b/pretty.c
index 3b811ed..8903116 100644
--- a/pretty.c
+++ b/pretty.c
@@ -403,10 +403,10 @@ static const char *show_ident_date(const struct 
ident_split *ident,
date = strtoul(ident-date_begin, NULL, 10);
if (date_overflows(date))
date = 0;
-   else {
-   if (ident-tz_begin  ident-tz_end)
-   tz = strtol(ident-tz_begin, NULL, 10);
-   if (tz == LONG_MAX || tz == LONG_MIN)
+   else if (ident-tz_begin  ident-tz_end) {
+   errno = 0;
+   tz = strtol(ident-tz_begin, NULL, 10);
+   if (errno)
tz = 0;
}
return show_date(date, tz, mode);
-- 
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


Microproject idea: new OPT_* macros for PARSE_OPT_NONEG

2014-03-06 Thread Duy Nguyen
Currently in order to avoid --[no]-xxx form we have to resort to
declare full struct option. It'd be nice to have a set of OPT_* macros
with PARSE_OPT_NONEG set. Find and update all struct option []
declarations with the new macros (including ones that should never
accept --no- form, but do anyway).
-- 
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: [RFC/PATCH 4/4] replace: add --edit option

2014-03-06 Thread Eric Sunshine
On Thu, Mar 6, 2014 at 12:51 PM, Jeff King p...@peff.net wrote:
 This allows you to run:

 git replace --edit SHA1

 to get dumped in an editor with the contents of the object
 for SHA1. The result is then read back in and used as a
 replace object for SHA1. The writing/reading is
 type-aware, so you get to edit ls-tree output rather than
 the binary tree format.

 Signed-off-by: Jeff King p...@peff.net
 ---
 diff --git a/builtin/replace.c b/builtin/replace.c
 index a090302..3ed5f75 100644
 --- a/builtin/replace.c
 +++ b/builtin/replace.c
 @@ -176,6 +177,105 @@ static int replace_object(const char *object_ref, const 
 char *replace_ref, int f
 return replace_object_sha1(object_ref, object, replace_ref, repl, 
 force);
  }

 +/*
 + * Read a previously-exported (and possibly edited) object back from 
 filename,
 + * interpreting it as type, and writing the result to the object database.
 + * The sha1 of the written object is returned via sha1.
 + */
 +static void import_object(unsigned char *sha1, enum object_type type,
 + const char *filename)
 +{
 +   int fd;
 +
 +   fd = open(filename, O_RDONLY);
 +   if (fd  0)
 +   die_errno(unable to open %s for reading, filename);
 +
 +   if (type == OBJ_TREE) {
 +   const char *argv[] = { mktree, NULL };
 +   struct child_process cmd = { argv };
 +   struct strbuf result = STRBUF_INIT;
 +
 +   cmd.argv = argv;
 +   cmd.git_cmd = 1;
 +   cmd.in = fd;
 +   cmd.out = -1;
 +
 +   if (start_command(cmd))
 +   die(unable to spawn mktree);
 +
 +   if (strbuf_read(result, cmd.out, 41)  0)
 +   die_errno(unable to read from mktree);
 +   close(cmd.out);
 +
 +   if (finish_command(cmd))
 +   die(mktree reported failure);
 +   if (get_sha1_hex(result.buf, sha1)  0)
 +   die(mktree did not return an object name);

strbuf_release(result);

 +   } else {
 +   struct stat st;
 +   int flags = HASH_FORMAT_CHECK | HASH_WRITE_OBJECT;
 +
 +   if (fstat(fd, st)  0)
 +   die_errno(unable to fstat %s, filename);
 +   if (index_fd(sha1, fd, st, type, NULL, flags)  0)
 +   die(unable to write object to database);
 +   /* index_fd close()s fd for us */
 +   }
 +
 +   /*
 +* No need to close(fd) here; both run-command and index-fd
 +* will have done it for us.
 +*/
 +}
 --
 1.8.5.2.500.g8060133
--
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 v5] Replace memcpy with hashcpy when dealing hash copy globally

2014-03-06 Thread Sun He
We invented hashcpy() to keep the abstraction of object
name behind it. Use it instead of calling memcpy() with
hard-coded 20-byte length when moving object names between
pieces of memory.

Leave ppc/sha1.c as it is, because the function is about the
SHA-1 hash algorithm whose output is and will always be 20-byte.

Helped-by: Michael Haggerty mhag...@alum.mit.edu
Helped-by: Duy Nguyen pclo...@gmail.com
Helped-by: Junio C Hamano gits...@pobox.com
Signed-off-by: Sun He sunheeh...@gmail.com
---

PATCH v5 changed the reason why should take this patch as tutored by
Junio C Hamano.
 Thanks to Junio C Hamano again. :-)

PATCH v5 move the two line behind the ---
  We can benefit from it, when we switch to another hash algorithm,
  eg. MD5, by just updating the hashcpy().

PATCH v4 changed the reason why should take this patch as tutored by
Junio C Hamano.
 Thanks to Junio C Hamano

PATCH v3 delete the one-space indentation on each line of commit message
as is suggested by Eric Sunshine.
 Thanks to Eric Sunshine.

PATCH v2 leave ppc/sha1.c alone.

The general rule is if cache.h or git-compat-util.h is included,
it is the first #include, and system includes will be always in
git-compat-tuil.h.
via Duy Nguyen

The change in PATCH v1 is not proper because I placed cache.h
in the end.
And adding it to the head is not a good way to achieve the goal,
as is said above ---.
 Thanks to Duy Nguyen.

Find the potential places with memcpy by the bash command:
 $ git grep 'memcpy.*20'
 Thanks to Junio C Hamano

 bundle.c| 2 +-
 grep.c  | 2 +-
 pack-bitmap-write.c | 2 +-
 reflog-walk.c   | 4 ++--
 refs.c  | 2 +-
 5 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/bundle.c b/bundle.c
index e99065c..7809fbb 100644
--- a/bundle.c
+++ b/bundle.c
@@ -19,7 +19,7 @@ static void add_to_ref_list(const unsigned char *sha1, const 
char *name,
list-list = xrealloc(list-list,
list-alloc * sizeof(list-list[0]));
}
-   memcpy(list-list[list-nr].sha1, sha1, 20);
+   hashcpy(list-list[list-nr].sha1, sha1);
list-list[list-nr].name = xstrdup(name);
list-nr++;
 }
diff --git a/grep.c b/grep.c
index c668034..f5101f7 100644
--- a/grep.c
+++ b/grep.c
@@ -1650,7 +1650,7 @@ void grep_source_init(struct grep_source *gs, enum 
grep_source_type type,
break;
case GREP_SOURCE_SHA1:
gs-identifier = xmalloc(20);
-   memcpy(gs-identifier, identifier, 20);
+   hashcpy(gs-identifier, identifier);
break;
case GREP_SOURCE_BUF:
gs-identifier = NULL;
diff --git a/pack-bitmap-write.c b/pack-bitmap-write.c
index 1218bef..5f1791a 100644
--- a/pack-bitmap-write.c
+++ b/pack-bitmap-write.c
@@ -530,7 +530,7 @@ void bitmap_writer_finish(struct pack_idx_entry **index,
header.version = htons(default_version);
header.options = htons(flags | options);
header.entry_count = htonl(writer.selected_nr);
-   memcpy(header.checksum, writer.pack_checksum, 20);
+   hashcpy(header.checksum, writer.pack_checksum);
 
sha1write(f, header, sizeof(header));
dump_bitmap(f, writer.commits);
diff --git a/reflog-walk.c b/reflog-walk.c
index b2fbdb2..d490f7d 100644
--- a/reflog-walk.c
+++ b/reflog-walk.c
@@ -32,8 +32,8 @@ static int read_one_reflog(unsigned char *osha1, unsigned 
char *nsha1,
sizeof(struct reflog_info));
}
item = array-items + array-nr;
-   memcpy(item-osha1, osha1, 20);
-   memcpy(item-nsha1, nsha1, 20);
+   hashcpy(item-osha1, osha1);
+   hashcpy(item-nsha1, nsha1);
item-email = xstrdup(email);
item-timestamp = timestamp;
item-tz = tz;
diff --git a/refs.c b/refs.c
index 89228e2..f90b7ea 100644
--- a/refs.c
+++ b/refs.c
@@ -1222,7 +1222,7 @@ static int resolve_gitlink_packed_ref(struct ref_cache 
*refs,
if (ref == NULL)
return -1;
 
-   memcpy(sha1, ref-u.value.sha1, 20);
+   hashcpy(sha1, ref-u.value.sha1);
return 0;
 }
 
-- 
1.9.0.138.g2de3478.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 v4 02/27] Convert git_snpath() to strbuf_git_path()

2014-03-06 Thread Duy Nguyen
On Mon, Mar 3, 2014 at 7:15 AM, Duy Nguyen pclo...@gmail.com wrote:
 On Mon, Mar 3, 2014 at 7:02 AM, Eric Sunshine sunsh...@sunshineco.com wrote:
 On Sat, Mar 1, 2014 at 7:12 AM, Nguyễn Thái Ngọc Duy pclo...@gmail.com 
 wrote:
 In the previous patch, git_snpath() is modified to allocate a new
 strbuf buffer because vsnpath() needs that. But that makes it awkward
 because git_snpath() receives a pre-allocated buffer from outside and
 has to copy data back. Rename it to strbuf_git_path() and make it
 receive strbuf directly.

 The conversion from git_snpath() to git_path() in
 update_refs_for_switch() is safe because that function does not keep
 any pointer to the round-robin buffer pool allocated by
 get_pathname().

 Signed-off-by: Nguyễn Thái Ngọc Duy pclo...@gmail.com
 ---
 diff --git a/refs.c b/refs.c
 index 89228e2..434bd5e 100644
 --- a/refs.c
 +++ b/refs.c
 @@ -2717,17 +2729,19 @@ static int copy_msg(char *buf, const char *msg)
 return cp - buf;
  }

 -int log_ref_setup(const char *refname, char *logfile, int bufsize)
 +int log_ref_setup(const char *refname, struct strbuf *sb_logfile)
  {
 int logfd, oflags = O_APPEND | O_WRONLY;
 +   const char *logfile;

 -   git_snpath(logfile, bufsize, logs/%s, refname);
 +   strbuf_git_path(sb_logfile, logs/%s, refname);
 +   logfile = sb_logfile-buf;
 if (log_all_ref_updates 
 (starts_with(refname, refs/heads/) ||
  starts_with(refname, refs/remotes/) ||
  starts_with(refname, refs/notes/) ||
  !strcmp(refname, HEAD))) {
 -   if (safe_create_leading_directories(logfile)  0)
 +   if (safe_create_leading_directories(sb_logfile-buf)  0)

 At this point, 'logfile' is still 'sb_logfile-buf', so do you really
 need this change?

 Junio made the same comment last time and I missed it. Will update.

No I will not :-) safe_create_leading_directories takes an editable
string, but logfile is now a const string. We could use
s_c_l_d_const() but that one will make a copy of the string
unncessarily. Will make a note in the commit message though.
-- 
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 v4 02/27] Convert git_snpath() to strbuf_git_path()

2014-03-06 Thread Eric Sunshine
On Fri, Mar 7, 2014 at 12:03 AM, Duy Nguyen pclo...@gmail.com wrote:
 On Mon, Mar 3, 2014 at 7:15 AM, Duy Nguyen pclo...@gmail.com wrote:
 On Mon, Mar 3, 2014 at 7:02 AM, Eric Sunshine sunsh...@sunshineco.com 
 wrote:
 On Sat, Mar 1, 2014 at 7:12 AM, Nguyễn Thái Ngọc Duy pclo...@gmail.com 
 wrote:
 In the previous patch, git_snpath() is modified to allocate a new
 strbuf buffer because vsnpath() needs that. But that makes it awkward
 because git_snpath() receives a pre-allocated buffer from outside and
 has to copy data back. Rename it to strbuf_git_path() and make it
 receive strbuf directly.

 The conversion from git_snpath() to git_path() in
 update_refs_for_switch() is safe because that function does not keep
 any pointer to the round-robin buffer pool allocated by
 get_pathname().

 Signed-off-by: Nguyễn Thái Ngọc Duy pclo...@gmail.com
 ---
 diff --git a/refs.c b/refs.c
 index 89228e2..434bd5e 100644
 --- a/refs.c
 +++ b/refs.c
 @@ -2717,17 +2729,19 @@ static int copy_msg(char *buf, const char *msg)
 return cp - buf;
  }

 -int log_ref_setup(const char *refname, char *logfile, int bufsize)
 +int log_ref_setup(const char *refname, struct strbuf *sb_logfile)
  {
 int logfd, oflags = O_APPEND | O_WRONLY;
 +   const char *logfile;

 -   git_snpath(logfile, bufsize, logs/%s, refname);
 +   strbuf_git_path(sb_logfile, logs/%s, refname);
 +   logfile = sb_logfile-buf;
 if (log_all_ref_updates 
 (starts_with(refname, refs/heads/) ||
  starts_with(refname, refs/remotes/) ||
  starts_with(refname, refs/notes/) ||
  !strcmp(refname, HEAD))) {
 -   if (safe_create_leading_directories(logfile)  0)
 +   if (safe_create_leading_directories(sb_logfile-buf)  0)

 At this point, 'logfile' is still 'sb_logfile-buf', so do you really
 need this change?

 Junio made the same comment last time and I missed it. Will update.

 No I will not :-) safe_create_leading_directories takes an editable
 string, but logfile is now a const string. We could use
 s_c_l_d_const() but that one will make a copy of the string
 unncessarily. Will make a note in the commit message though.

Rather than explaining it in the commit message, it might be better
eliminate the source of confusion by taking one of these approaches:

1. Drop the 'const char *logfile' variable altogether; rename the
strbuf argument to 'logfile'; and just use logfile-buf everywhere
'logfile' is used in the current code. This makes the diff a bit more
noisy, but eliminates confusion of reviewers reading the patch.

2. Keep the 'const char *logfile' but assign it just before its first
(real) use in 'logfd = open(logfile...)'. (There's one earlier use in
a diagnostic, but sb_logfile-buf could suffice there.)

3. Just declare it 'char *logfile' and use it everywhere in the
function. This is a bit ugly since it's not obvious to the reviewer
that it is non-const only for the sake of
safe_create_leading_directories().

I fiind myself favoring #1 in this particular 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 v6 02/11] trailer: process trailers from stdin and arguments

2014-03-06 Thread Christian Couder
On Wed, Mar 5, 2014 at 11:52 PM, Junio C Hamano gits...@pobox.com wrote:

 This round is marked as the sixth, but I still see quite a many
 style issues, which I expect not to see from long timers without
 being told.  Somewhat disappointing...

Yeah, I don't know why, but these days I find it very hard to review
style issues in my own code without being distracted.
And by the way is there a good script to check them?

Thanks,
Christian.
--
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 v7 03/11] trailer: read and process config information

2014-03-06 Thread Christian Couder
This patch implements reading the configuration
to get trailer information, and then processing
it and storing it in a doubly linked list.

The config information is stored in the list
whose first item is pointed to by:

static struct trailer_item *first_conf_item;

Signed-off-by: Christian Couder chrisc...@tuxfamily.org
---
 trailer.c | 134 ++
 1 file changed, 134 insertions(+)

diff --git a/trailer.c b/trailer.c
index 52108c2..7a6d35d 100644
--- a/trailer.c
+++ b/trailer.c
@@ -25,6 +25,8 @@ struct trailer_item {
struct conf_info conf;
 };
 
+static struct trailer_item *first_conf_item;
+
 static int same_token(struct trailer_item *a, struct trailer_item *b, int 
alnum_len)
 {
return !strncasecmp(a-token, b-token, alnum_len);
@@ -245,3 +247,135 @@ static void process_trailers_lists(struct trailer_item 
**in_tok_first,
apply_arg_if_missing(in_tok_first, in_tok_last, arg_tok);
}
 }
+
+static int set_where(struct conf_info *item, const char *value)
+{
+   if (!strcasecmp(after, value))
+   item-where = WHERE_AFTER;
+   else if (!strcasecmp(before, value))
+   item-where = WHERE_BEFORE;
+   else
+   return 1;
+   return 0;
+}
+
+static int set_if_exists(struct conf_info *item, const char *value)
+{
+   if (!strcasecmp(addIfDifferent, value))
+   item-if_exists = EXISTS_ADD_IF_DIFFERENT;
+   else if (!strcasecmp(addIfDifferentNeighbor, value))
+   item-if_exists = EXISTS_ADD_IF_DIFFERENT_NEIGHBOR;
+   else if (!strcasecmp(add, value))
+   item-if_exists = EXISTS_ADD;
+   else if (!strcasecmp(overwrite, value))
+   item-if_exists = EXISTS_OVERWRITE;
+   else if (!strcasecmp(doNothing, value))
+   item-if_exists = EXISTS_DO_NOTHING;
+   else
+   return 1;
+   return 0;
+}
+
+static int set_if_missing(struct conf_info *item, const char *value)
+{
+   if (!strcasecmp(doNothing, value))
+   item-if_missing = MISSING_DO_NOTHING;
+   else if (!strcasecmp(add, value))
+   item-if_missing = MISSING_ADD;
+   else
+   return 1;
+   return 0;
+}
+
+enum trailer_info_type { TRAILER_KEY, TRAILER_COMMAND, TRAILER_WHERE,
+TRAILER_IF_EXISTS, TRAILER_IF_MISSING };
+
+static int set_name_and_type(const char *conf_key, const char *suffix,
+enum trailer_info_type type,
+char **pname, enum trailer_info_type *ptype)
+{
+   int ret = ends_with(conf_key, suffix);
+   if (ret) {
+   *pname = xstrndup(conf_key, strlen(conf_key) - strlen(suffix));
+   *ptype = type;
+   }
+   return ret;
+}
+
+static struct trailer_item *get_conf_item(const char *name)
+{
+   struct trailer_item *item;
+   struct trailer_item *previous;
+
+   /* Look up item with same name */
+   for (previous = NULL, item = first_conf_item;
+item;
+previous = item, item = item-next) {
+   if (!strcasecmp(item-conf.name, name))
+   return item;
+   }
+
+   /* Item does not already exists, create it */
+   item = xcalloc(sizeof(struct trailer_item), 1);
+   item-conf.name = xstrdup(name);
+
+   if (!previous)
+   first_conf_item = item;
+   else {
+   previous-next = item;
+   item-previous = previous;
+   }
+
+   return item;
+}
+
+static int git_trailer_config(const char *conf_key, const char *value, void 
*cb)
+{
+   if (starts_with(conf_key, trailer.)) {
+   const char *orig_conf_key = conf_key;
+   struct trailer_item *item;
+   struct conf_info *conf;
+   char *name;
+   enum trailer_info_type type;
+
+   conf_key += 8;
+   if (!set_name_and_type(conf_key, .key, TRAILER_KEY, name, 
type) 
+   !set_name_and_type(conf_key, .command, TRAILER_COMMAND, 
name, type) 
+   !set_name_and_type(conf_key, .where, TRAILER_WHERE, 
name, type) 
+   !set_name_and_type(conf_key, .ifexists, 
TRAILER_IF_EXISTS, name, type) 
+   !set_name_and_type(conf_key, .ifmissing, 
TRAILER_IF_MISSING, name, type))
+   return 0;
+
+   item = get_conf_item(name);
+   conf = item-conf;
+   free(name);
+
+   switch (type) {
+   case TRAILER_KEY:
+   if (conf-key)
+   warning(_(more than one %s), orig_conf_key);
+   conf-key = xstrdup(value);
+   break;
+   case TRAILER_COMMAND:
+   if (conf-command)
+   warning(_(more than one %s), orig_conf_key);
+   

[PATCH v7 00/11] Add interpret-trailers builtin

2014-03-06 Thread Christian Couder
This patch series implements a new command:

git interpret-trailers

and an infrastructure to process trailers that can be reused,
for example in commit.c.

1) Rationale:

This command should help with RFC 822 style headers, called
trailers, that are found at the end of commit messages.

(Note that these headers do not follow and are not intended to
follow many rules that are in RFC 822. For example they do not
follow the line breaking rules, the encoding rules and probably
many other rules.)

For a long time, these trailers have become a de facto standard
way to add helpful information into commit messages.

Until now git commit has only supported the well known
Signed-off-by:  trailer, that is used by many projects like
the Linux kernel and Git.

It is better to implement features for these trailers first in a
new command rather than in builtin/commit.c, because this way the
prepare-commit-msg and commit-msg hooks can reuse this command.

2) Current state:

Currently the usage string of this command is:

git interpret-trailers [--trim-empty] [(token[(=|:)value])...]

The following features are implemented:

- the result is printed on stdout
- the [token[=value]] arguments are interpreted
- a commit message read from stdin is interpreted
- the trailer.token.key options in the config are interpreted
- the trailer.token.where options are interpreted
- the trailer.token.ifExist options are interpreted
- the trailer.token.ifMissing options are interpreted
- the trailer.token.command config works
- $ARG can be used in commands
- there are some tests
- there is some documentation

The following features are planned but not yet implemented:
- add more tests related to commands
- add examples in documentation
- integration with git commit

Possible improvements:
- support GIT_COMMIT_PROTO env variable in commands

3) Changes since version 6, thanks to Junio and Ramsey:

* many style fixes
* clearer and nicer setup tests
* trailer.h is included at the beginning of trailer.c


Christian Couder (11):
  Add data structures and basic functions for commit trailers
  trailer: process trailers from stdin and arguments
  trailer: read and process config information
  trailer: process command line trailer arguments
  trailer: parse trailers from stdin
  trailer: put all the processing together and print
  trailer: add interpret-trailers command
  trailer: add tests for git interpret-trailers
  trailer: execute command from 'trailer.name.command'
  trailer: add tests for commands in config file
  Documentation: add documentation for 'git interpret-trailers'

 .gitignore   |   1 +
 Documentation/git-interpret-trailers.txt | 123 ++
 Makefile |   2 +
 builtin.h|   1 +
 builtin/interpret-trailers.c |  33 ++
 git.c|   1 +
 t/t7513-interpret-trailers.sh| 261 
 trailer.c| 667 +++
 trailer.h|   6 +
 9 files changed, 1095 insertions(+)
 create mode 100644 Documentation/git-interpret-trailers.txt
 create mode 100644 builtin/interpret-trailers.c
 create mode 100755 t/t7513-interpret-trailers.sh
 create mode 100644 trailer.c
 create mode 100644 trailer.h

-- 
1.8.5.2.204.gcfe299d.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 v7 08/11] trailer: add tests for git interpret-trailers

2014-03-06 Thread Christian Couder
Signed-off-by: Christian Couder chrisc...@tuxfamily.org
---
 t/t7513-interpret-trailers.sh | 214 ++
 1 file changed, 214 insertions(+)
 create mode 100755 t/t7513-interpret-trailers.sh

diff --git a/t/t7513-interpret-trailers.sh b/t/t7513-interpret-trailers.sh
new file mode 100755
index 000..1c5ed81
--- /dev/null
+++ b/t/t7513-interpret-trailers.sh
@@ -0,0 +1,214 @@
+#!/bin/sh
+#
+# Copyright (c) 2013 Christian Couder
+#
+
+test_description='git interpret-trailers'
+
+. ./test-lib.sh
+
+test_expect_success 'setup 1' '
+   cat basic_message -\EOF
+   subject
+
+   body
+   EOF
+'
+
+test_expect_success 'setup 2' '
+   cat complex_message_body -\EOF
+   my subject
+
+   my body which is long
+   and contains some special
+   chars like : = ? !
+
+   EOF
+'
+
+# We want one trailing space at the end of each line.
+# Let's use sed to make sure that these spaces are not removed
+# by any automatic tool.
+test_expect_success 'setup 3' '
+   sed -e s/ Z\$/ / complex_message_trailers -\EOF
+   Fixes: Z
+   Acked-by: Z
+   Reviewed-by: Z
+   Signed-off-by: Z
+   EOF
+'
+
+test_expect_success 'without config' '
+   printf ack: Peff\nReviewed-by: \nAcked-by: Johan\n expected 
+   git interpret-trailers ack = Peff Reviewed-by Acked-by: Johan 
actual 
+   test_cmp expected actual
+'
+
+test_expect_success '--trim-empty without config' '
+   printf ack: Peff\nAcked-by: Johan\n expected 
+   git interpret-trailers --trim-empty ack = Peff Reviewed-by 
Acked-by: Johan sob: actual 
+   test_cmp expected actual
+'
+
+test_expect_success 'with config setup' '
+   git config trailer.ack.key Acked-by:  
+   printf Acked-by: Peff\n expected 
+   git interpret-trailers --trim-empty ack = Peff actual 
+   test_cmp expected actual 
+   git interpret-trailers --trim-empty Acked-by = Peff actual 
+   test_cmp expected actual 
+   git interpret-trailers --trim-empty Acked-by :Peff actual 
+   test_cmp expected actual
+'
+
+test_expect_success 'with config setup and = sign' '
+   git config trailer.ack.key Acked-by=  
+   printf Acked-by= Peff\n expected 
+   git interpret-trailers --trim-empty ack = Peff actual 
+   test_cmp expected actual 
+   git interpret-trailers --trim-empty Acked-by= Peff actual 
+   test_cmp expected actual 
+   git interpret-trailers --trim-empty Acked-by : Peff actual 
+   test_cmp expected actual
+'
+
+test_expect_success 'with config setup and # sign' '
+   git config trailer.bug.key Bug # 
+   printf Bug #42\n expected 
+   git interpret-trailers --trim-empty bug = 42 actual 
+   test_cmp expected actual
+'
+
+test_expect_success 'with commit basic message' '
+   git interpret-trailers basic_message actual 
+   test_cmp basic_message actual
+'
+
+test_expect_success 'with commit complex message' '
+   cat complex_message_body complex_message_trailers complex_message 
+   cat complex_message_body expected 
+   printf Fixes: \nAcked-by= \nReviewed-by: \nSigned-off-by: \n 
expected 
+   git interpret-trailers complex_message actual 
+   test_cmp expected actual
+'
+
+test_expect_success 'with commit complex message and args' '
+   cat complex_message_body expected 
+   printf Fixes: \nAcked-by= \nAcked-by= Peff\nReviewed-by: 
\nSigned-off-by: \nBug #42\n expected 
+   git interpret-trailers ack: Peff bug: 42 complex_message actual 
+   test_cmp expected actual
+'
+
+test_expect_success 'with commit complex message, args and --trim-empty' '
+   cat complex_message_body expected 
+   printf Acked-by= Peff\nBug #42\n expected 
+   git interpret-trailers --trim-empty ack: Peff bug: 42 
complex_message actual 
+   test_cmp expected actual
+'
+
+test_expect_success 'using where = before' '
+   git config trailer.bug.where before 
+   cat complex_message_body expected 
+   printf Bug #42\nFixes: \nAcked-by= \nAcked-by= Peff\nReviewed-by: 
\nSigned-off-by: \n expected 
+   git interpret-trailers ack: Peff bug: 42 complex_message actual 
+   test_cmp expected actual
+'
+
+test_expect_success 'using where = before for a token in the middle of the 
message' '
+   git config trailer.review.key Reviewed-by: 
+   git config trailer.review.where before 
+   cat complex_message_body expected 
+   printf Bug #42\nFixes: \nAcked-by= \nAcked-by= Peff\nReviewed-by: 
Johan\nReviewed-by: \nSigned-off-by: \n expected 
+   git interpret-trailers ack: Peff bug: 42 review: Johan 
complex_message actual 
+   test_cmp expected actual
+'
+
+test_expect_success 'using where = before and --trim-empty' '
+   cat complex_message_body expected 
+   printf Bug #46\nBug #42\nAcked-by= Peff\nReviewed-by: Johan\n 
expected 
+   git 

[PATCH v7 05/11] trailer: parse trailers from stdin

2014-03-06 Thread Christian Couder
Read trailers from stdin, parse them and put the result into a doubly linked
list.

Signed-off-by: Christian Couder chrisc...@tuxfamily.org
---
 trailer.c | 76 +++
 1 file changed, 76 insertions(+)

diff --git a/trailer.c b/trailer.c
index 43cbf10..910eddb 100644
--- a/trailer.c
+++ b/trailer.c
@@ -50,6 +50,14 @@ static size_t alnum_len(const char *buf, size_t len)
return len;
 }
 
+static inline int contains_only_spaces(const char *str)
+{
+   const char *s = str;
+   while (*s  isspace(*s))
+   s++;
+   return !*s;
+}
+
 static void free_trailer_item(struct trailer_item *item)
 {
free(item-conf.name);
@@ -476,3 +484,71 @@ static struct trailer_item *process_command_line_args(int 
argc, const char **arg
 
return arg_tok_first;
 }
+
+static struct strbuf **read_stdin(void)
+{
+   struct strbuf **lines;
+   struct strbuf sb = STRBUF_INIT;
+
+   if (strbuf_read(sb, fileno(stdin), 0)  0)
+   die_errno(_(could not read from stdin));
+
+   lines = strbuf_split(sb, '\n');
+
+   strbuf_release(sb);
+
+   return lines;
+}
+
+/*
+ * Return the the (0 based) index of the first trailer line
+ * or the line count if there are no trailers.
+ */
+static int find_trailer_start(struct strbuf **lines)
+{
+   int start, empty = 1, count = 0;
+
+   /* Get the line count */
+   while (lines[count])
+   count++;
+
+   /*
+* Get the start of the trailers by looking starting from the end
+* for a line with only spaces before lines with one ':'.
+*/
+   for (start = count - 1; start = 0; start--) {
+   if (contains_only_spaces(lines[start]-buf)) {
+   if (empty)
+   continue;
+   return start + 1;
+   }
+   if (strchr(lines[start]-buf, ':')) {
+   if (empty)
+   empty = 0;
+   continue;
+   }
+   return count;
+   }
+
+   return empty ? count : start + 1;
+}
+
+static void process_stdin(struct trailer_item **in_tok_first,
+ struct trailer_item **in_tok_last)
+{
+   struct strbuf **lines = read_stdin();
+   int start = find_trailer_start(lines);
+   int i;
+
+   /* Print non trailer lines as is */
+   for (i = 0; lines[i]  i  start; i++)
+   printf(%s, lines[i]-buf);
+
+   /* Parse trailer lines */
+   for (i = start; lines[i]; i++) {
+   struct trailer_item *new = create_trailer_item(lines[i]-buf);
+   add_trailer_item(in_tok_first, in_tok_last, new);
+   }
+
+   strbuf_list_free(lines);
+}
-- 
1.8.5.2.204.gcfe299d.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 v7 10/11] trailer: add tests for commands in config file

2014-03-06 Thread Christian Couder
Signed-off-by: Christian Couder chrisc...@tuxfamily.org
---
 t/t7513-interpret-trailers.sh | 47 +++
 1 file changed, 47 insertions(+)

diff --git a/t/t7513-interpret-trailers.sh b/t/t7513-interpret-trailers.sh
index 1c5ed81..07e1b60 100755
--- a/t/t7513-interpret-trailers.sh
+++ b/t/t7513-interpret-trailers.sh
@@ -211,4 +211,51 @@ test_expect_success 'using ifMissing = doNothing' '
test_cmp expected actual
 '
 
+test_expect_success 'with simple command' '
+   git config trailer.sign.key Signed-off-by:  
+   git config trailer.sign.where after 
+   git config trailer.sign.ifExists addIfDifferentNeighbor 
+   git config trailer.sign.command echo \A U Thor 
aut...@example.com\ 
+   cat complex_message_body expected 
+   printf Fixes: \nAcked-by= \nReviewed-by: \nSigned-off-by: 
\nSigned-off-by: A U Thor aut...@example.com\n expected 
+   git interpret-trailers review: fix=22 complex_message actual 
+   test_cmp expected actual
+'
+
+test_expect_success 'with command using commiter information' '
+   git config trailer.sign.ifExists addIfDifferent 
+   git config trailer.sign.command echo \\$GIT_COMMITTER_NAME 
\$GIT_COMMITTER_EMAIL\ 
+   cat complex_message_body expected 
+   printf Fixes: \nAcked-by= \nReviewed-by: \nSigned-off-by: 
\nSigned-off-by: C O Mitter commit...@example.com\n expected 
+   git interpret-trailers review: fix=22 complex_message actual 
+   test_cmp expected actual
+'
+
+test_expect_success 'with command using author information' '
+   git config trailer.sign.key Signed-off-by:  
+   git config trailer.sign.where after 
+   git config trailer.sign.ifExists addIfDifferentNeighbor 
+   git config trailer.sign.command echo \\$GIT_AUTHOR_NAME 
\$GIT_AUTHOR_EMAIL\ 
+   cat complex_message_body expected 
+   printf Fixes: \nAcked-by= \nReviewed-by: \nSigned-off-by: 
\nSigned-off-by: A U Thor aut...@example.com\n expected 
+   git interpret-trailers review: fix=22 complex_message actual 
+   test_cmp expected actual
+'
+
+test_expect_success 'setup a commit' '
+   echo Content of the first commit.  a.txt 
+   git add a.txt 
+   git commit -m Add file a.txt
+'
+
+test_expect_success 'with command using $ARG' '
+   git config trailer.fix.ifExists overwrite 
+   git config trailer.fix.command git log -1 --oneline --format=\%h 
(%s)\ --abbrev-commit --abbrev=14 \$ARG 
+   FIXED=$(git log -1 --oneline --format=%h (%s) --abbrev-commit 
--abbrev=14 HEAD) 
+   cat complex_message_body expected 
+   printf Fixes: $FIXED\nAcked-by= \nReviewed-by: \nSigned-off-by: 
\nSigned-off-by: A U Thor aut...@example.com\n expected 
+   git interpret-trailers review: fix=HEAD complex_message actual 
+   test_cmp expected actual
+'
+
 test_done
-- 
1.8.5.2.204.gcfe299d.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 v7 06/11] trailer: put all the processing together and print

2014-03-06 Thread Christian Couder
This patch adds the process_trailers() function that
calls all the previously added processing functions
and then prints the results on the standard output.

Signed-off-by: Christian Couder chrisc...@tuxfamily.org
---
 trailer.c | 49 +
 trailer.h |  6 ++
 2 files changed, 55 insertions(+)
 create mode 100644 trailer.h

diff --git a/trailer.c b/trailer.c
index 910eddb..cc87918 100644
--- a/trailer.c
+++ b/trailer.c
@@ -1,4 +1,5 @@
 #include cache.h
+#include trailer.h
 /*
  * Copyright (c) 2013, 2014 Christian Couder chrisc...@tuxfamily.org
  */
@@ -68,6 +69,26 @@ static void free_trailer_item(struct trailer_item *item)
free(item);
 }
 
+static void print_tok_val(const char *tok, const char *val)
+{
+   char c = tok[strlen(tok) - 1];
+   if (isalnum(c))
+   printf(%s: %s\n, tok, val);
+   else if (isspace(c) || c == '#')
+   printf(%s%s\n, tok, val);
+   else
+   printf(%s %s\n, tok, val);
+}
+
+static void print_all(struct trailer_item *first, int trim_empty)
+{
+   struct trailer_item *item;
+   for (item = first; item; item = item-next) {
+   if (!trim_empty || strlen(item-value)  0)
+   print_tok_val(item-token, item-value);
+   }
+}
+
 static void add_arg_to_input_list(struct trailer_item *in_tok,
  struct trailer_item *arg_tok)
 {
@@ -552,3 +573,31 @@ static void process_stdin(struct trailer_item 
**in_tok_first,
 
strbuf_list_free(lines);
 }
+
+static void free_all(struct trailer_item **first)
+{
+   while (*first) {
+   struct trailer_item *item = remove_first(first);
+   free_trailer_item(item);
+   }
+}
+
+void process_trailers(int trim_empty, int argc, const char **argv)
+{
+   struct trailer_item *in_tok_first = NULL;
+   struct trailer_item *in_tok_last = NULL;
+   struct trailer_item *arg_tok_first;
+
+   git_config(git_trailer_config, NULL);
+
+   /* Print the non trailer part of stdin */
+   process_stdin(in_tok_first, in_tok_last);
+
+   arg_tok_first = process_command_line_args(argc, argv);
+
+   process_trailers_lists(in_tok_first, in_tok_last, arg_tok_first);
+
+   print_all(in_tok_first, trim_empty);
+
+   free_all(in_tok_first);
+}
diff --git a/trailer.h b/trailer.h
new file mode 100644
index 000..9323b1e
--- /dev/null
+++ b/trailer.h
@@ -0,0 +1,6 @@
+#ifndef TRAILER_H
+#define TRAILER_H
+
+void process_trailers(int trim_empty, int argc, const char **argv);
+
+#endif /* TRAILER_H */
-- 
1.8.5.2.204.gcfe299d.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 v7 09/11] trailer: execute command from 'trailer.name.command'

2014-03-06 Thread Christian Couder
Let the user specify a command that will give on its standard output
the value to use for the specified trailer.

Signed-off-by: Christian Couder chrisc...@tuxfamily.org
---
 trailer.c | 63 +++
 1 file changed, 63 insertions(+)

diff --git a/trailer.c b/trailer.c
index cc87918..97a0fe7 100644
--- a/trailer.c
+++ b/trailer.c
@@ -1,4 +1,5 @@
 #include cache.h
+#include run-command.h
 #include trailer.h
 /*
  * Copyright (c) 2013, 2014 Christian Couder chrisc...@tuxfamily.org
@@ -13,11 +14,14 @@ struct conf_info {
char *name;
char *key;
char *command;
+   unsigned command_uses_arg : 1;
enum action_where where;
enum action_if_exists if_exists;
enum action_if_missing if_missing;
 };
 
+#define TRAILER_ARG_STRING $ARG
+
 struct trailer_item {
struct trailer_item *previous;
struct trailer_item *next;
@@ -59,6 +63,13 @@ static inline int contains_only_spaces(const char *str)
return !*s;
 }
 
+static inline void strbuf_replace(struct strbuf *sb, const char *a, const char 
*b)
+{
+   const char *ptr = strstr(sb-buf, a);
+   if (ptr)
+   strbuf_splice(sb, ptr - sb-buf, strlen(a), b, strlen(b));
+}
+
 static void free_trailer_item(struct trailer_item *item)
 {
free(item-conf.name);
@@ -389,6 +400,7 @@ static int git_trailer_config(const char *conf_key, const 
char *value, void *cb)
if (conf-command)
warning(_(more than one %s), orig_conf_key);
conf-command = xstrdup(value);
+   conf-command_uses_arg = !!strstr(conf-command, 
TRAILER_ARG_STRING);
break;
case TRAILER_WHERE:
if (set_where(conf, value))
@@ -423,6 +435,44 @@ static void parse_trailer(struct strbuf *tok, struct 
strbuf *val, const char *tr
}
 }
 
+static int read_from_command(struct child_process *cp, struct strbuf *buf)
+{
+   if (run_command(cp))
+   return error(running trailer command '%s' failed, 
cp-argv[0]);
+   if (strbuf_read(buf, cp-out, 1024)  1)
+   return error(reading from trailer command '%s' failed, 
cp-argv[0]);
+   strbuf_trim(buf);
+   return 0;
+}
+
+static const char *apply_command(const char *command, const char *arg)
+{
+   struct strbuf cmd = STRBUF_INIT;
+   struct strbuf buf = STRBUF_INIT;
+   struct child_process cp;
+   const char *argv[] = {NULL, NULL};
+   const char *result = ;
+
+   strbuf_addstr(cmd, command);
+   if (arg)
+   strbuf_replace(cmd, TRAILER_ARG_STRING, arg);
+
+   argv[0] = cmd.buf;
+   memset(cp, 0, sizeof(cp));
+   cp.argv = argv;
+   cp.env = local_repo_env;
+   cp.no_stdin = 1;
+   cp.out = -1;
+   cp.use_shell = 1;
+
+   if (read_from_command(cp, buf))
+   strbuf_release(buf);
+   else
+   result = strbuf_detach(buf, NULL);
+
+   strbuf_release(cmd);
+   return result;
+}
 
 static void duplicate_conf(struct conf_info *dst, struct conf_info *src)
 {
@@ -445,6 +495,10 @@ static struct trailer_item *new_trailer_item(struct 
trailer_item *conf_item,
duplicate_conf(new-conf, conf_item-conf);
new-token = xstrdup(conf_item-conf.key);
free(tok);
+   if (conf_item-conf.command_uses_arg || !val) {
+   new-value = apply_command(conf_item-conf.command, 
val);
+   free(val);
+   }
} else
new-token = tok;
 
@@ -497,12 +551,21 @@ static struct trailer_item *process_command_line_args(int 
argc, const char **arg
int i;
struct trailer_item *arg_tok_first = NULL;
struct trailer_item *arg_tok_last = NULL;
+   struct trailer_item *item;
 
for (i = 0; i  argc; i++) {
struct trailer_item *new = create_trailer_item(argv[i]);
add_trailer_item(arg_tok_first, arg_tok_last, new);
}
 
+   /* Add conf commands that don't use $ARG */
+   for (item = first_conf_item; item; item = item-next) {
+   if (item-conf.command  !item-conf.command_uses_arg) {
+   struct trailer_item *new = new_trailer_item(item, NULL, 
NULL);
+   add_trailer_item(arg_tok_first, arg_tok_last, new);
+   }
+   }
+
return arg_tok_first;
 }
 
-- 
1.8.5.2.204.gcfe299d.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 v7 04/11] trailer: process command line trailer arguments

2014-03-06 Thread Christian Couder
Parse the trailer command line arguments and put
the result into an arg_tok doubly linked list.

Signed-off-by: Christian Couder chrisc...@tuxfamily.org
---
 trailer.c | 97 +++
 1 file changed, 97 insertions(+)

diff --git a/trailer.c b/trailer.c
index 7a6d35d..43cbf10 100644
--- a/trailer.c
+++ b/trailer.c
@@ -379,3 +379,100 @@ static int git_trailer_config(const char *conf_key, const 
char *value, void *cb)
}
return 0;
 }
+
+static void parse_trailer(struct strbuf *tok, struct strbuf *val, const char 
*trailer)
+{
+   size_t len = strcspn(trailer, =:);
+   if (len  strlen(trailer)) {
+   strbuf_add(tok, trailer, len);
+   strbuf_trim(tok);
+   strbuf_addstr(val, trailer + len + 1);
+   strbuf_trim(val);
+   } else {
+   strbuf_addstr(tok, trailer);
+   strbuf_trim(tok);
+   }
+}
+
+
+static void duplicate_conf(struct conf_info *dst, struct conf_info *src)
+{
+   *dst = *src;
+   if (src-name)
+   dst-name = xstrdup(src-name);
+   if (src-key)
+   dst-key = xstrdup(src-key);
+   if (src-command)
+   dst-command = xstrdup(src-command);
+}
+
+static struct trailer_item *new_trailer_item(struct trailer_item *conf_item,
+char *tok, char *val)
+{
+   struct trailer_item *new = xcalloc(sizeof(*new), 1);
+   new-value = val;
+
+   if (conf_item) {
+   duplicate_conf(new-conf, conf_item-conf);
+   new-token = xstrdup(conf_item-conf.key);
+   free(tok);
+   } else
+   new-token = tok;
+
+   return new;
+}
+
+static struct trailer_item *create_trailer_item(const char *string)
+{
+   struct strbuf tok = STRBUF_INIT;
+   struct strbuf val = STRBUF_INIT;
+   struct trailer_item *item;
+   int tok_alnum_len;
+
+   parse_trailer(tok, val, string);
+
+   tok_alnum_len = alnum_len(tok.buf, tok.len);
+
+   /* Lookup if the token matches something in the config */
+   for (item = first_conf_item; item; item = item-next) {
+   if (!strncasecmp(tok.buf, item-conf.key, tok_alnum_len) ||
+   !strncasecmp(tok.buf, item-conf.name, tok_alnum_len)) {
+   strbuf_release(tok);
+   return new_trailer_item(item,
+   NULL,
+   strbuf_detach(val, NULL));
+   }
+   }
+
+   return new_trailer_item(NULL,
+   strbuf_detach(tok, NULL),
+   strbuf_detach(val, NULL));
+}
+
+static void add_trailer_item(struct trailer_item **first,
+struct trailer_item **last,
+struct trailer_item *new)
+{
+   if (!*last) {
+   *first = new;
+   *last = new;
+   } else {
+   (*last)-next = new;
+   new-previous = *last;
+   *last = new;
+   }
+}
+
+static struct trailer_item *process_command_line_args(int argc, const char 
**argv)
+{
+   int i;
+   struct trailer_item *arg_tok_first = NULL;
+   struct trailer_item *arg_tok_last = NULL;
+
+   for (i = 0; i  argc; i++) {
+   struct trailer_item *new = create_trailer_item(argv[i]);
+   add_trailer_item(arg_tok_first, arg_tok_last, new);
+   }
+
+   return arg_tok_first;
+}
-- 
1.8.5.2.204.gcfe299d.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 v7 11/11] Documentation: add documentation for 'git interpret-trailers'

2014-03-06 Thread Christian Couder
Signed-off-by: Christian Couder chrisc...@tuxfamily.org
---
 Documentation/git-interpret-trailers.txt | 123 +++
 1 file changed, 123 insertions(+)
 create mode 100644 Documentation/git-interpret-trailers.txt

diff --git a/Documentation/git-interpret-trailers.txt 
b/Documentation/git-interpret-trailers.txt
new file mode 100644
index 000..75ae386
--- /dev/null
+++ b/Documentation/git-interpret-trailers.txt
@@ -0,0 +1,123 @@
+git-interpret-trailers(1)
+=
+
+NAME
+
+git-interpret-trailers - help add stuctured information into commit messages
+
+SYNOPSIS
+
+[verse]
+'git interpret-trailers' [--trim-empty] [(token[(=|:)value])...]
+
+DESCRIPTION
+---
+Help add RFC 822-like headers, called 'trailers', at the end of the
+otherwise free-form part of a commit message.
+
+This command is a filter. It reads the standard input for a commit
+message and applies the `token` arguments, if any, to this
+message. The resulting message is emited on the standard output.
+
+Some configuration variables control the way the `token` arguments are
+applied to the message and the way any existing trailer in the message
+is changed. They also make it possible to automatically add some
+trailers.
+
+By default, a 'token=value' or 'token:value' argument will be added
+only if no trailer with the same (token, value) pair is already in the
+message. The 'token' and 'value' parts will be trimmed to remove
+starting and trailing whitespace, and the resulting trimmed 'token'
+and 'value' will appear in the message like this:
+
+
+token: value
+
+
+By default, if there are already trailers with the same 'token', the
+new trailer will appear just after the last trailer with the same
+'token'. Otherwise it will appear at the end of the message.
+
+Note that 'trailers' do not follow and are not intended to follow many
+rules that are in RFC 822. For example they do not follow the line
+breaking rules, the encoding rules and probably many other rules.
+
+OPTIONS
+---
+--trim-empty::
+   If the 'value' part of any trailer contains only whitespace,
+   the whole trailer will be removed from the resulting message.
+
+CONFIGURATION VARIABLES
+---
+
+trailer.token.key::
+   This 'key' will be used instead of 'token' in the
+   trailer. After some alphanumeric characters, it can contain
+   some non alphanumeric characters like ':', '=' or '#' that will
+   be used instead of ':' to separate the token from the value in
+   the trailer, though the default ':' is more standard.
+
+trailer.token.where::
+   This can be either `after`, which is the default, or
+   `before`. If it is `before`, then a trailer with the specified
+   token, will appear before, instead of after, other trailers
+   with the same token, or otherwise at the beginning, instead of
+   at the end, of all the trailers.
+
+trailer.token.ifexist::
+   This option makes it possible to choose what action will be
+   performed when there is already at least one trailer with the
+   same token in the message.
++
+The valid values for this option are: `addIfDifferent` (this is the
+default), `addIfDifferentNeighbor`, `add`, `overwrite` or `doNothing`.
++
+With `addIfDifferent`, a new trailer will be added only if no trailer
+with the same (token, value) pair is already in the message.
++
+With `addIfDifferentNeighbor`, a new trailer will be added only if no
+trailer with the same (token, value) pair is above or below the line
+where the new trailer will be added.
++
+With `add`, a new trailer will be added, even if some trailers with
+the same (token, value) pair are already in the message.
++
+With `overwrite`, the new trailer will overwrite an existing trailer
+with the same token.
++
+With `doNothing`, nothing will be done, that is no new trailer will be
+added if there is already one with the same token in the message.
+
+trailer.token.ifmissing::
+   This option makes it possible to choose what action will be
+   performed when there is not yet any trailer with the same
+   token in the message.
++
+The valid values for this option are: `add` (this is the default) and
+`doNothing`.
++
+With `add`, a new trailer will be added.
++
+With `doNothing`, nothing will be done.
+
+trailer.token.command::
+   This option can be used to specify a shell command that will
+   be used to automatically add or modify a trailer with the
+   specified 'token'.
++
+When this option is specified, it is like if a special 'token=value'
+argument is added at the end of the command line, where 'value' will
+be given by the standard output of the specified command.
++
+If the command contains the `$ARG` string, this string will be
+replaced with the 'value' part of an existing trailer with the same
+token, if any, before the command 

[PATCH v7 02/11] trailer: process trailers from stdin and arguments

2014-03-06 Thread Christian Couder
Implement the logic to process trailers from stdin and arguments.

At the beginning trailers from stdin are in their own in_tok
doubly linked list, and trailers from arguments are in their own
arg_tok doubly linked list.

The lists are traversed and when an arg_tok should be applied,
it is removed from its list and inserted into the in_tok list.

Signed-off-by: Christian Couder chrisc...@tuxfamily.org
---
 trailer.c | 198 ++
 1 file changed, 198 insertions(+)

diff --git a/trailer.c b/trailer.c
index db93a63..52108c2 100644
--- a/trailer.c
+++ b/trailer.c
@@ -47,3 +47,201 @@ static size_t alnum_len(const char *buf, size_t len)
len--;
return len;
 }
+
+static void free_trailer_item(struct trailer_item *item)
+{
+   free(item-conf.name);
+   free(item-conf.key);
+   free(item-conf.command);
+   free((char *)item-token);
+   free((char *)item-value);
+   free(item);
+}
+
+static void add_arg_to_input_list(struct trailer_item *in_tok,
+ struct trailer_item *arg_tok)
+{
+   if (arg_tok-conf.where == WHERE_AFTER) {
+   arg_tok-next = in_tok-next;
+   in_tok-next = arg_tok;
+   arg_tok-previous = in_tok;
+   if (arg_tok-next)
+   arg_tok-next-previous = arg_tok;
+   } else {
+   arg_tok-previous = in_tok-previous;
+   in_tok-previous = arg_tok;
+   arg_tok-next = in_tok;
+   if (arg_tok-previous)
+   arg_tok-previous-next = arg_tok;
+   }
+}
+
+static int check_if_different(struct trailer_item *in_tok,
+ struct trailer_item *arg_tok,
+ int alnum_len, int check_all)
+{
+   enum action_where where = arg_tok-conf.where;
+   do {
+   if (!in_tok)
+   return 1;
+   if (same_trailer(in_tok, arg_tok, alnum_len))
+   return 0;
+   /*
+* if we want to add a trailer after another one,
+* we have to check those before this one
+*/
+   in_tok = (where == WHERE_AFTER) ? in_tok-previous : 
in_tok-next;
+   } while (check_all);
+   return 1;
+}
+
+static void apply_arg_if_exists(struct trailer_item *in_tok,
+   struct trailer_item *arg_tok,
+   int alnum_len)
+{
+   switch (arg_tok-conf.if_exists) {
+   case EXISTS_DO_NOTHING:
+   free_trailer_item(arg_tok);
+   break;
+   case EXISTS_OVERWRITE:
+   free((char *)in_tok-value);
+   in_tok-value = xstrdup(arg_tok-value);
+   free_trailer_item(arg_tok);
+   break;
+   case EXISTS_ADD:
+   add_arg_to_input_list(in_tok, arg_tok);
+   break;
+   case EXISTS_ADD_IF_DIFFERENT:
+   if (check_if_different(in_tok, arg_tok, alnum_len, 1))
+   add_arg_to_input_list(in_tok, arg_tok);
+   else
+   free_trailer_item(arg_tok);
+   break;
+   case EXISTS_ADD_IF_DIFFERENT_NEIGHBOR:
+   if (check_if_different(in_tok, arg_tok, alnum_len, 0))
+   add_arg_to_input_list(in_tok, arg_tok);
+   else
+   free_trailer_item(arg_tok);
+   break;
+   }
+}
+
+static void remove_from_list(struct trailer_item *item,
+struct trailer_item **first)
+{
+   if (item-next)
+   item-next-previous = item-previous;
+   if (item-previous)
+   item-previous-next = item-next;
+   else
+   *first = item-next;
+}
+
+static struct trailer_item *remove_first(struct trailer_item **first)
+{
+   struct trailer_item *item = *first;
+   *first = item-next;
+   if (item-next) {
+   item-next-previous = NULL;
+   item-next = NULL;
+   }
+   return item;
+}
+
+static void process_input_token(struct trailer_item *in_tok,
+   struct trailer_item **arg_tok_first,
+   enum action_where where)
+{
+   struct trailer_item *arg_tok;
+   struct trailer_item *next_arg;
+
+   int after = where == WHERE_AFTER;
+   int tok_alnum_len = alnum_len(in_tok-token, strlen(in_tok-token));
+
+   for (arg_tok = *arg_tok_first; arg_tok; arg_tok = next_arg) {
+   next_arg = arg_tok-next;
+   if (!same_token(in_tok, arg_tok, tok_alnum_len))
+   continue;
+   if (arg_tok-conf.where != where)
+   continue;
+   remove_from_list(arg_tok, arg_tok_first);
+   apply_arg_if_exists(in_tok, arg_tok, tok_alnum_len);
+   /*
+* If arg has 

[PATCH v7 01/11] Add data structures and basic functions for commit trailers

2014-03-06 Thread Christian Couder
We will use a doubly linked list to store all information
about trailers and their configuration.

This way we can easily remove or add trailers to or from
trailer lists while traversing the lists in either direction.

Signed-off-by: Christian Couder chrisc...@tuxfamily.org
---
 Makefile  |  1 +
 trailer.c | 49 +
 2 files changed, 50 insertions(+)
 create mode 100644 trailer.c

diff --git a/Makefile b/Makefile
index b4af1e2..ec90feb 100644
--- a/Makefile
+++ b/Makefile
@@ -871,6 +871,7 @@ LIB_OBJS += submodule.o
 LIB_OBJS += symlinks.o
 LIB_OBJS += tag.o
 LIB_OBJS += trace.o
+LIB_OBJS += trailer.o
 LIB_OBJS += transport.o
 LIB_OBJS += transport-helper.o
 LIB_OBJS += tree-diff.o
diff --git a/trailer.c b/trailer.c
new file mode 100644
index 000..db93a63
--- /dev/null
+++ b/trailer.c
@@ -0,0 +1,49 @@
+#include cache.h
+/*
+ * Copyright (c) 2013, 2014 Christian Couder chrisc...@tuxfamily.org
+ */
+
+enum action_where { WHERE_AFTER, WHERE_BEFORE };
+enum action_if_exists { EXISTS_ADD_IF_DIFFERENT, 
EXISTS_ADD_IF_DIFFERENT_NEIGHBOR,
+   EXISTS_ADD, EXISTS_OVERWRITE, EXISTS_DO_NOTHING };
+enum action_if_missing { MISSING_ADD, MISSING_DO_NOTHING };
+
+struct conf_info {
+   char *name;
+   char *key;
+   char *command;
+   enum action_where where;
+   enum action_if_exists if_exists;
+   enum action_if_missing if_missing;
+};
+
+struct trailer_item {
+   struct trailer_item *previous;
+   struct trailer_item *next;
+   const char *token;
+   const char *value;
+   struct conf_info conf;
+};
+
+static int same_token(struct trailer_item *a, struct trailer_item *b, int 
alnum_len)
+{
+   return !strncasecmp(a-token, b-token, alnum_len);
+}
+
+static int same_value(struct trailer_item *a, struct trailer_item *b)
+{
+   return !strcasecmp(a-value, b-value);
+}
+
+static int same_trailer(struct trailer_item *a, struct trailer_item *b, int 
alnum_len)
+{
+   return same_token(a, b, alnum_len)  same_value(a, b);
+}
+
+/* Get the length of buf from its beginning until its last alphanumeric 
character */
+static size_t alnum_len(const char *buf, size_t len)
+{
+   while (len  0  !isalnum(buf[len - 1]))
+   len--;
+   return len;
+}
-- 
1.8.5.2.204.gcfe299d.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 v7 07/11] trailer: add interpret-trailers command

2014-03-06 Thread Christian Couder
This patch adds the git interpret-trailers command.
This command uses the previously added process_trailers()
function in trailer.c.

Signed-off-by: Christian Couder chrisc...@tuxfamily.org
---
 .gitignore   |  1 +
 Makefile |  1 +
 builtin.h|  1 +
 builtin/interpret-trailers.c | 33 +
 git.c|  1 +
 5 files changed, 37 insertions(+)
 create mode 100644 builtin/interpret-trailers.c

diff --git a/.gitignore b/.gitignore
index b5f9def..c870ada 100644
--- a/.gitignore
+++ b/.gitignore
@@ -74,6 +74,7 @@
 /git-index-pack
 /git-init
 /git-init-db
+/git-interpret-trailers
 /git-instaweb
 /git-log
 /git-ls-files
diff --git a/Makefile b/Makefile
index ec90feb..a91465e 100644
--- a/Makefile
+++ b/Makefile
@@ -935,6 +935,7 @@ BUILTIN_OBJS += builtin/hash-object.o
 BUILTIN_OBJS += builtin/help.o
 BUILTIN_OBJS += builtin/index-pack.o
 BUILTIN_OBJS += builtin/init-db.o
+BUILTIN_OBJS += builtin/interpret-trailers.o
 BUILTIN_OBJS += builtin/log.o
 BUILTIN_OBJS += builtin/ls-files.o
 BUILTIN_OBJS += builtin/ls-remote.o
diff --git a/builtin.h b/builtin.h
index d4afbfe..30f4c30 100644
--- a/builtin.h
+++ b/builtin.h
@@ -71,6 +71,7 @@ extern int cmd_hash_object(int argc, const char **argv, const 
char *prefix);
 extern int cmd_help(int argc, const char **argv, const char *prefix);
 extern int cmd_index_pack(int argc, const char **argv, const char *prefix);
 extern int cmd_init_db(int argc, const char **argv, const char *prefix);
+extern int cmd_interpret_trailers(int argc, const char **argv, const char 
*prefix);
 extern int cmd_log(int argc, const char **argv, const char *prefix);
 extern int cmd_log_reflog(int argc, const char **argv, const char *prefix);
 extern int cmd_ls_files(int argc, const char **argv, const char *prefix);
diff --git a/builtin/interpret-trailers.c b/builtin/interpret-trailers.c
new file mode 100644
index 000..0c8ca72
--- /dev/null
+++ b/builtin/interpret-trailers.c
@@ -0,0 +1,33 @@
+/*
+ * Builtin git interpret-trailers
+ *
+ * Copyright (c) 2013, 2014 Christian Couder chrisc...@tuxfamily.org
+ *
+ */
+
+#include cache.h
+#include builtin.h
+#include parse-options.h
+#include trailer.h
+
+static const char * const git_interpret_trailers_usage[] = {
+   N_(git interpret-trailers [--trim-empty] 
[(token[(=|:)value])...]),
+   NULL
+};
+
+int cmd_interpret_trailers(int argc, const char **argv, const char *prefix)
+{
+   int trim_empty = 0;
+
+   struct option options[] = {
+   OPT_BOOL(0, trim-empty, trim_empty, N_(trim empty 
trailers)),
+   OPT_END()
+   };
+
+   argc = parse_options(argc, argv, prefix, options,
+git_interpret_trailers_usage, 0);
+
+   process_trailers(trim_empty, argc, argv);
+
+   return 0;
+}
diff --git a/git.c b/git.c
index 3799514..1420b58 100644
--- a/git.c
+++ b/git.c
@@ -383,6 +383,7 @@ static void handle_internal_command(int argc, const char 
**argv)
{ index-pack, cmd_index_pack, RUN_SETUP_GENTLY },
{ init, cmd_init_db },
{ init-db, cmd_init_db },
+   { interpret-trailers, cmd_interpret_trailers, RUN_SETUP },
{ log, cmd_log, RUN_SETUP },
{ ls-files, cmd_ls_files, RUN_SETUP },
{ ls-remote, cmd_ls_remote, RUN_SETUP_GENTLY },
-- 
1.8.5.2.204.gcfe299d.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 v4 26/27] gc: support prune --repos

2014-03-06 Thread Eric Sunshine
On Sat, Mar 1, 2014 at 7:13 AM, Nguyễn Thái Ngọc Duy pclo...@gmail.com wrote:
 Signed-off-by: Nguyễn Thái Ngọc Duy pclo...@gmail.com
 ---
  Documentation/config.txt |  6 ++
  builtin/gc.c | 17 +
  2 files changed, 23 insertions(+)

 diff --git a/Documentation/config.txt b/Documentation/config.txt
 index 313d4b3..438b213 100644
 --- a/Documentation/config.txt
 +++ b/Documentation/config.txt
 @@ -1183,6 +1183,12 @@ gc.pruneexpire::
 now may be used to disable this  grace period and always prune
 unreachable objects immediately.

 +gc.prunereposexpire::
 +   When 'git gc' is run, it will call 'prune --repos --expire 
 3.months.ago'.
 +   Override the grace period with this config variable.  The value
 +   now may be used to disable this  grace period and always prune

Extra space between this and grace. However, the grace period
sounds a bit better.

 +   $GIT_DIR/repos immediately.
 +
  gc.reflogexpire::
  gc.pattern.reflogexpire::
 'git reflog expire' removes reflog entries older than
 diff --git a/builtin/gc.c b/builtin/gc.c
 index 39d9b27..85c3c0c 100644
 --- a/builtin/gc.c
 +++ b/builtin/gc.c
 @@ -30,11 +30,13 @@ static int aggressive_window = 250;
  static int gc_auto_threshold = 6700;
  static int gc_auto_pack_limit = 50;
  static const char *prune_expire = 2.weeks.ago;
 +static const char *prune_repos_expire = 3.months.ago;

  static struct argv_array pack_refs_cmd = ARGV_ARRAY_INIT;
  static struct argv_array reflog = ARGV_ARRAY_INIT;
  static struct argv_array repack = ARGV_ARRAY_INIT;
  static struct argv_array prune = ARGV_ARRAY_INIT;
 +static struct argv_array prune_repos = ARGV_ARRAY_INIT;
  static struct argv_array rerere = ARGV_ARRAY_INIT;

  static char *pidfile;
 @@ -81,6 +83,14 @@ static int gc_config(const char *var, const char *value, 
 void *cb)
 }
 return git_config_string(prune_expire, var, value);
 }
 +   if (!strcmp(var, gc.prunereposexpire)) {
 +   if (value  strcmp(value, now)) {
 +   unsigned long now = approxidate(now);
 +   if (approxidate(value) = now)
 +   return error(_(Invalid %s: '%s'), var, 
 value);
 +   }
 +   return git_config_string(prune_repos_expire, var, value);
 +   }
 return git_default_config(var, value, cb);
  }

 @@ -274,6 +284,7 @@ int cmd_gc(int argc, const char **argv, const char 
 *prefix)
 argv_array_pushl(reflog, reflog, expire, --all, NULL);
 argv_array_pushl(repack, repack, -d, -l, NULL);
 argv_array_pushl(prune, prune, --expire, NULL);
 +   argv_array_pushl(prune_repos, prune, --repos, --expire, NULL);
 argv_array_pushl(rerere, rerere, gc, NULL);

 git_config(gc_config, NULL);
 @@ -334,6 +345,12 @@ int cmd_gc(int argc, const char **argv, const char 
 *prefix)
 return error(FAILED_RUN, prune.argv[0]);
 }

 +   if (prune_repos_expire) {
 +   argv_array_push(prune_repos, prune_repos_expire);
 +   if (run_command_v_opt(prune_repos.argv, RUN_GIT_CMD))
 +   return error(FAILED_RUN, prune_repos.argv[0]);
 +   }
 +
 if (run_command_v_opt(rerere.argv, RUN_GIT_CMD))
 return error(FAILED_RUN, rerere.argv[0]);

 --
 1.9.0.40.gaa8c3ea

 --
 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
--
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] disable grafts during fetch/push/bundle

2014-03-06 Thread Christian Couder
On Fri, Mar 7, 2014 at 12:39 AM, Junio C Hamano gits...@pobox.com wrote:
 Michael Haggerty mhag...@alum.mit.edu writes:

 I didn't mean to insult all Windows users in general.  I was only
 referring to the fact that since the default Windows command line is not
 a POSIX shell, even an experienced Windows user might have trouble
 figuring out how to execute a shell loop.  Putting this functionality in
 a git command or script, by contrast, would make it work universally, no
 fuss, no muss.

 ;-)

 Be it graft or replace, I do not think we want to invite people to
 use these mechansims too lightly to locally rewrite their history
 willy-nilly without fixing their mistakes at the object layer with
 commit --amend, rebase, bfg, etc. in the longer term.  So in
 that sense, adding a command to make it easy is not something I am
 enthusiastic about.

 On the other hand, if the user does need to use graft or replace
 (perhaps to prepare for casting the fixed history in stone with
 filter-branch), it would be good to help them avoid making mistakes
 while doing so and tool support may be a way to do so.

 So, ... I am of two minds.


Maybe if we add a new command (or maybe a script) with a name long and
cryptic-looking enough like git create-replacement-object it will
scare casual users from touching it, while power users will be happy
to benefit from it.
--
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] diff: simplify cpp funcname regex

2014-03-06 Thread Johannes Sixt
Am 3/6/2014 22:28, schrieb Jeff King:
 On Wed, Mar 05, 2014 at 08:58:26AM +0100, Johannes Sixt wrote:
 The pattern I chose also catches variable definition, not just
 functions. That is what I need, but it hurts grep --function-context
 That's the reason I didn't forward the patch, yet.
 
 If by variable definition you mean:
 
struct foo bar = {
   -   old
   +   new
};
 
 I'd think that would be covered by the existing struct|class|enum.
 Though I think we'd want to also allow keywords in front of it, like
 static. I suspect the original was more meant to find:
 
struct foo {
   -old
   +new
};

No, I meant lines like

static double var;
   -static int old;
   +static int new;

The motivation is to show hints where in a file the change is located:
Anything that could be of significance for the author should be picked up.

But that does not necessarily help grep --function-context. For example,
when there is a longish block of global variable definitions and there is
a match in the middle, then --function-context would provide no context
because the line itself would be regarded as the beginning of a
function, i.e., the context, and the next line (which also matches the
pattern) would be the beginning of the *next* function, and would not be
in the context anymore.

 
 The parts of the pattern have the following flaws:

 - The first part matches an identifier followed immediately by a colon and
   arbitrary text and is intended to reject goto labels and C++ access
   specifiers (public, private, protected). But this pattern also rejects
   C++ constructs, which look like this:

 MyClass::MyClass()
 MyClass::~MyClass()
 MyClass::Item MyClass::Find(...
 
 Makes sense. I noticed your fix is to look for end-of-line or comments
 afterwards.  Would it be simpler to just check for a non-colon, like:
 
   !^[ \t]*[A-Za-z_][A-Za-z_0-9]*:($|[^:])

I want to match [[:space:]] after the label's colon, because I have lot's
of C++ files with CRLF, and I need to match the CR. Your more liberal
pattern would fit as well, although it would pick up a bit field as in

   struct foo {
  unsigned
flag: 1;
   -old
   +new

I would not mind ignoring this case (garbage in, garbage out ;-).

 - The second part matches an identifier followed by a list of qualified
   names (i.e. identifiers separated by the C++ scope operator '::')
 [...]
 
 A tried to keep the looks like a function definition bit in mine, and
 yours loosens this quite a bit more. I think that may be OK. That is, I
 do not think there is any reason for somebody to do:
 
 void foo() {
 call_to_bar();
-old
+new
 }
 
 That is, nobody would put a function _call_ without indentation. If
 something has alphanumerics at the left-most column, then it is probably
 interesting no matter what.
 
 - The third part of the pattern finally matches compound definitions. But
   it forgets about unions and namespaces, and also skips single-line
   definitions

 struct random_iterator_tag {};

   because no semicolon can occur on the line.
 
 I don't see how that is an interesting line. The point is to find a
 block that is surrounding the changes, but that is not surrounding
 the lines below.

I more often than not want to have an answer to the question where?, not
wherein? Then anything that helps locate a hunk is useful.

(The particular example, an empty struct, looks strange for C programmers,
of course, but it's a common idiom in C++ when it comes to template
meta-programming.)

 Notice that all interesting anchor points begin with an identifier or
 keyword. But since there is a large variety of syntactical constructs after
 the first word, the simplest is to require only this word and accept
 everything else. Therefore, this boils down to a line that begins with a
 letter or underscore (optionally preceded by the C++ scope operator '::'
 to accept functions returning a type anchored at the global namespace).
 Replace the second and third part by a single pattern that picks such a
 line.
 
 Yeah, this bit makes sense to me.
 
 Both yours and mine will find the first line here in things like:
 
void foo(void);
   -void bar(void);
   +void bar(int arg);
 
 but I think that is OK. There _isn't_ any interesting surrounding
 context here. The current code will sometimes come up with an empty
 funcline (which is good), but it may just as easily come up with a
 totally bogus funcline in a case like:
 
void unrelated(void)
{
}
 
void foo(void);
   -void bar(void);
   +void bar(int arg);
 
 So trying to be very restrictive and say that doesn't look like a
 function does not really buy us anything (and it creates tons of false
 negatives, as you documented, because C++ syntax has all kinds of crazy
 stuff).
 
 _If_ the backwards search learned to terminate (e.g., seeing the ^}
 line and saying well, we can't be inside a function), then such
 negative lines might be useful for coming up with 

Re: Microproject idea: new OPT_* macros for PARSE_OPT_NONEG

2014-03-06 Thread Michael Haggerty
On 03/07/2014 02:38 AM, Duy Nguyen wrote:
 Currently in order to avoid --[no]-xxx form we have to resort to
 declare full struct option. It'd be nice to have a set of OPT_* macros
 with PARSE_OPT_NONEG set. Find and update all struct option []
 declarations with the new macros (including ones that should never
 accept --no- form, but do anyway).

I added this to the list, with the following warning:

This is more a milliproject than a microproject

because to me it feels considerably more involved than the other
microprojects.  To  complete it, the student will have to understand at
least part of the parse_options() API, which is more than a 15 minute
job by itself.

Thanks,
Michael

-- 
Michael Haggerty
mhag...@alum.mit.edu
http://softwareswirl.blogspot.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/RFC] Documentation: Say that submodule clones use a separate gitdirs.

2014-03-06 Thread Henri GEIST
Adding a note in the submodule documentation signaling that the
automatically cloned missing submodules are cloned with a separate
gitdir. And where it is put.

Signed-off-by: Henri GEIST geist.he...@laposte.net
---
 Documentation/git-submodule.txt |5 +
 1 file changed, 5 insertions(+)

diff --git a/Documentation/git-submodule.txt b/Documentation/git-submodule.txt
index 21cb59a..ea837fd 100644
--- a/Documentation/git-submodule.txt
+++ b/Documentation/git-submodule.txt
@@ -64,6 +64,11 @@ using the 'status' subcommand and get a detailed overview of 
the
 difference between the index and checkouts using the 'summary'
 subcommand.
 
+*NOTE*: when submodule add or submodule update commands clone a missing
+submodule, the option --separate-git-dir is passed to the clone command
+and the gitdir of the submodule is placed outside of its working
+directory in the .git/module of the current repository.
+
 
 COMMANDS
 
-- 
1.7.9.3.369.gd715.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


  1   2   >