Re: git feature-branch

2014-07-25 Thread Sitaram Chamarty
On 07/25/2014 11:10 AM, Sheldon Els wrote:
 It is just a shell script yes, and a man page to make things a bit
 more discoverable for git help feature-branch.
 
 The brew command comes from homebrew, a popular OSX package manager.
 My platform of choice.

You might want to at least add these instructions are for people using
macs.  Otherwise it seems like you assume everyone is using macs, and
nothing else exists in the world as far as you are concerned.

 Perhaps I can get support for an easy install for your platform. Do

When I said more generic I meant it's just *one* shell script; put it
somewhere on your $PATH.  That should be sufficient for something like
this (at the risk of going a bit off-topic for the list).

 you think a Makefile that installs to /usr/local/bin and
 /usr/local/share/man would fit, or are you on windows?

Ouch.  That hurt.

 On 25 July 2014 05:11, Sitaram Chamarty sitar...@gmail.com wrote:
 On 07/25/2014 03:45 AM, Sheldon Els wrote:
 Hi

 A small tool I wrote that is useful for some workflows. I thought it'd
 be worth sharing. https://github.com/sheldon/git-feature-branch/

 As far as I can tell it's just a shell script; does it really need
 installation instructions, and if so can they not be more generic than
 brew install?  Speaking for myself I have NO clue what that is.

--
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: `ab | (cd cd git apply -)' fails with v2.0.0

2014-07-25 Thread Michael J Gruber
Junio C Hamano venit, vidit, dixit 24.07.2014 19:19:
 Michael J Gruber g...@drmicha.warpmail.net writes:
 
 Steffen Nurpmeso venit, vidit, dixit 24.07.2014 15:29:
 Hello (again, psst, after a long time),

 it happened yesterday that i needed to do

   $ git diff HEAD:FILE COMMIT:SAME-FILE |
(cd src  git apply -) 
 ...

 Ah little more context would help. Are you diffing files in the subdir
 src, or a file at the root which happens to be present in the subdir src
 as well?
 
 As the treeish:path form is not meant to produce git apply
 applicable patch in the first place, I am not sure what the OP is
 trying to achieve in the first place.  Not just how many leading
 levels to strip? but which file is being modified? does not
 appear in a usable form.  For example, here is what you would see:
 
 $ git diff HEAD:GIT-VERSION-GEN maint:GIT-VERSION-GEN
 diff --git a/HEAD:GIT-VERSION-GEN b/maint:GIT-VERSION-GEN
 index 40adbf7..0d1a86c 100755
 --- a/HEAD:GIT-VERSION-GEN
 +++ b/maint:GIT-VERSION-GEN
 @@ -1,7 +1,7 @@
 ...
 
 and neither HEAD:GIT-VERSION-GEN nor maint:GIT-VERSION-GEN is
 the file being modified (GIT-VERSION-GEN is).

I thought git apply knows how to strip the rev part.

 I would understand if the upstream of the pipe were
 
 $ git diff HEAD maint -- GIT-VERSION-GEN | ...
 
 though.
 
 Needless to say, if the place cd goes is not a worktree controlled
 by git, then git apply would not know where the top-level of the
 target tree is, so even though the input with the corrected command
 on the upstream side of the pipe tells it which file is being
 modified, it needs to be told with the proper -pn parameter how
 many leading levels to strip.

I think it's a common mistake to think of git apply as some sort of
magic extension of patch which can do anything that patch does and
more, and can be fed anything that git diff produces, figuring out by
itself what to do with it :)

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


Re: [PATCH 3/5] checkout --to: no auto-detach if the ref is already checked out

2014-07-25 Thread Michael J Gruber
Junio C Hamano venit, vidit, dixit 24.07.2014 23:30:
 Duy Nguyen pclo...@gmail.com writes:
 
 On Wed, Jul 23, 2014 at 8:48 PM, Michael J Gruber
 g...@drmicha.warpmail.net wrote:
 Nguyễn Thái Ngọc Duy venit, vidit, dixit 23.07.2014 13:43:
 + if (advice_checkout_to)
 + die(_(%s is already checked out at %s.\n
 +   Either use --detach or -b together with --to 
 +   or switch branch in the the other checkout.),

 or switch to a different branch in the other checkout. But maybe we
 can be even more helpful, like:

 %s is already checked out at %s.\n
 Either checkout the detached head of branch %s using\n
 git checkout --detach --to %s %s\n
 or checkout a new branch based off %s using\n
 git checkout --to %s -b %s newbranch %s\n
 or switch to a different branch in the other checkout.

 if we can figure out the appropriate arguments at this point in the code.

 We would not be able to construct the exact command that the user has
 entered, so perhaps

   git checkout --detach more options %s
   git checkout -b new branch more options %s

 ?

 Note that this does not only occur when --to is given. If you have two
 checkouts associated to the same repo, git checkout foo on one
 checkout when foo is held by another checkout would cause the same
 error. I'll need to think of a better name than advice.checkoutTo.
 
 I am not sure if we need to say anything more than the first line of
 the message you have in your patch.  To fork a new branch at the
 commit the user is interested in to check it out, or not bothering
 with the branch and detach, are both very normal parts of user's Git
 toolchest, nothing particularly special.  As long as the most
 important point, i.e. in the new world order, unlike the
 contrib/workdir hack, you cannot check out the same branch at two
 different places, is clearly conveyed and understood, everything
 else should follow naturally, no?

As an error message that is completely sufficient.

The advice messages are meant to teach the user about the normal parts
of the toolchest to use in a situation of conflict, aren't they? Maybe
we should ask someone who hasn't turned them off...

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


Re: [PATCH 5/7] enforce `xfuncname` precedence over `funcname`

2014-07-25 Thread Matthieu Moy
Tanay Abhra tanay...@gmail.com writes:

 On 7/25/2014 2:52 AM, Ramsay Jones wrote:
 However, I think it you could create a list of pointer to hash-table
 entry, string-list index pairs in the config_set and use that to do
 the iteration. A bit ugly, but it should work.

 Thanks for the advice, that is exactly what I am doing.

I'd just replace list with array and use
Documentation/technical/api-allocation-growing.txt.

But I can't think of a better way.

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


Re: [PATCH] git-svn: Initialize SVN::Client with svn config instead of, auth for git svn branch.

2014-07-25 Thread Monard Vong
Thanks for your reply, I updated commit message and subject, hoping it 
would be clearer.
However I messed up message-id so it appear as a new message and not 
in the current thread.

Sorry, still learning.


Le 24/07/2014 00:33, Eric Wong a écrit :

Monard Vong travelingsou...@gmail.com wrote:

If a client certificate is required to connect to svn, git svn branch
always prompt the user for the certificate location and password,
even though those parameters are stored in svn file server
located in svn config dir (generally ~/.subversion).
On the opposite, git svn info/init/dcommit read the config dir
and do not prompt if the parameters are set.

This commit initializes for git svn branch, the SVN::Client with
the 'config'
option instead of 'auth'. As decribed in the SVN documentation,
http://search.cpan.org/~mschwern/Alien-SVN-v1.7.17.1/src/subversion/subversion/bindings/swig/perl/native/Client.pm#METHODS
the SVN::Client will then read cached authentication options.

Signed-off-by: Monard Vong travelingsou...@gmail.com

Thanks, I do not have a good way to test this, but the idea seems
correct.

Your patch is whitespace mangled, and the commit message and subject
needs to be improved (see Documentation/SubmittingPatches on how to
describe your changes and how to send them without whitespace mangling.)

Thanks again.


--
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/4] Consolidate ref parsing code

2014-07-25 Thread Nguyễn Thái Ngọc Duy
On Thu, Jul 24, 2014 at 4:16 AM, Junio C Hamano gits...@pobox.com wrote:
  -  three places now knows what a
textual symref looks like (i.e. begins with ref:, zero or more
whitespaces, the target ref and then zero or more trailing
whitespaces).  Perhaps we need to consolidate the code further,
so that this knowledge does not leak out of refs.c?

I started on top of nd/multiple-work-trees but it conflicts badly with
rs/ref-transaction-0 because this is basically code move. So I think
we should make it a separate topic instead, based on latest 'master'.
Junio, you still hit conflicts when merging this with nd/multiple-work-trees,
but that's simpler to resolve (git_snpath - strbuf_git_path). I
promise to replace the ref: code in checkout.c later when both
topics graduate.

So.. first cut. The end result looks nice.

Nguyễn Thái Ngọc Duy (4):
  strbuf.c: keep errno in strbuf_read_file()
  refs.c: refactor resolve_ref_unsafe() to use strbuf internally
  refs.c: move ref parsing code out of resolve_ref()
  refs.c: rewrite resolve_gitlink_ref() to use parse_ref()

 cache.h  |  12 +++
 refs.c   | 332 ---
 strbuf.c |   7 +-
 3 files changed, 188 insertions(+), 163 deletions(-)

-- 
1.9.1.346.ga2b5940

--
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/4] refs.c: refactor resolve_ref_unsafe() to use strbuf internally

2014-07-25 Thread Nguyễn Thái Ngọc Duy
In the beginning, we had resolve_ref() that returns a buffer owned by
this function. Then we started to move away from that direction because
the buffer could be overwritten by the next resolve_ref() call and
introduced two new functions: resolve_ref_unsafe() and resolve_refdup().
The static buffer is still kept internally.

This patch makes the core of resolve_ref use a strbuf instead of static
buffer. Which makes resolve_refdup() more efficient (no need to copy
from the static buffer to a new buffer). It also removes the (random?)
256 char limit. In future, resolve_ref() could be used directly without
going through resolve_refdup() wrapper.

A minor bonus. resolve_ref(dup) are now more thread-friendly (although I'm
not 100% sure if they are thread-safe yet).

Signed-off-by: Nguyễn Thái Ngọc Duy pclo...@gmail.com
---
 cache.h |   1 +
 refs.c  | 122 +++-
 2 files changed, 68 insertions(+), 55 deletions(-)

diff --git a/cache.h b/cache.h
index fcb511d..5ffbafb 100644
--- a/cache.h
+++ b/cache.h
@@ -1002,6 +1002,7 @@ extern int read_ref(const char *refname, unsigned char 
*sha1);
  */
 extern const char *resolve_ref_unsafe(const char *ref, unsigned char *sha1, 
int reading, int *flag);
 extern char *resolve_refdup(const char *ref, unsigned char *sha1, int reading, 
int *flag);
+extern int resolve_ref(const char *refname, struct strbuf *result, unsigned 
char *sha1, int reading, int *flag);
 
 extern int dwim_ref(const char *str, int len, unsigned char *sha1, char **ref);
 extern int dwim_log(const char *str, int len, unsigned char *sha1, char **ref);
diff --git a/refs.c b/refs.c
index 84b9070..bec2bb1 100644
--- a/refs.c
+++ b/refs.c
@@ -1506,10 +1506,10 @@ static struct ref_entry *get_packed_ref(const char 
*refname)
  * A loose ref file doesn't exist; check for a packed ref.  The
  * options are forwarded from resolve_safe_unsafe().
  */
-static const char *handle_missing_loose_ref(const char *refname,
-   unsigned char *sha1,
-   int reading,
-   int *flag)
+static int handle_missing_loose_ref(const char *refname,
+   unsigned char *sha1,
+   int reading,
+   int *flag)
 {
struct ref_entry *entry;
 
@@ -1522,45 +1522,53 @@ static const char *handle_missing_loose_ref(const char 
*refname,
hashcpy(sha1, entry-u.value.sha1);
if (flag)
*flag |= REF_ISPACKED;
-   return refname;
+   return 0;
}
/* The reference is not a packed reference, either. */
if (reading) {
-   return NULL;
+   return -1;
} else {
hashclr(sha1);
-   return refname;
+   return 0;
}
 }
 
-/* This function needs to return a meaningful errno on failure */
-const char *resolve_ref_unsafe(const char *refname, unsigned char *sha1, int 
reading, int *flag)
+/*
+ * 'result' content will be destroyed. Its value may be undefined if
+ * resolve_ref returns -1.
+ *
+ * This function needs to return a meaningful errno on failure
+ */
+int resolve_ref(const char *refname, struct strbuf *result,
+   unsigned char *sha1, int reading, int *flag)
 {
+   struct strbuf buffer = STRBUF_INIT;
int depth = MAXDEPTH;
-   ssize_t len;
-   char buffer[256];
-   static char refname_buffer[256];
+   int ret = -1;
 
if (flag)
*flag = 0;
 
if (check_refname_format(refname, REFNAME_ALLOW_ONELEVEL)) {
errno = EINVAL;
-   return NULL;
+   return -1;
}
 
+   strbuf_reset(result);
+   strbuf_addstr(result, refname);
+
for (;;) {
char path[PATH_MAX];
+   const char *ref = result-buf;
struct stat st;
-   char *buf;
-   int fd;
+   const char *buf;
 
if (--depth  0) {
errno = ELOOP;
-   return NULL;
+   break;
}
 
-   git_snpath(path, sizeof(path), %s, refname);
+   git_snpath(path, sizeof(path), %s, ref);
 
/*
 * We might have to loop back here to avoid a race
@@ -1574,27 +1582,25 @@ const char *resolve_ref_unsafe(const char *refname, 
unsigned char *sha1, int rea
stat_ref:
if (lstat(path, st)  0) {
if (errno == ENOENT)
-   return handle_missing_loose_ref(refname, sha1,
-   reading, flag);
-   else
-   return NULL;
+   ret = 

[PATCH 4/4] refs.c: rewrite resolve_gitlink_ref() to use parse_ref()

2014-07-25 Thread Nguyễn Thái Ngọc Duy
resolve_gitlink_ref_recursive() is less strict than the old
resolve_ref_unsafe() (which is now parse_ref()). It also has another
random limit 128 bytes for symrefs.

This brings MAXREFLEN check to resolve_ref* family. It looks like an
arbitrary limit though (added in 0ebde32 (Add 'resolve_gitlink_ref()'
helper function - 2007-04-09)

Signed-off-by: Nguyễn Thái Ngọc Duy pclo...@gmail.com
---
 refs.c | 68 +-
 1 file changed, 26 insertions(+), 42 deletions(-)

diff --git a/refs.c b/refs.c
index 2769f20..24503e5 100644
--- a/refs.c
+++ b/refs.c
@@ -1436,48 +1436,11 @@ static int resolve_gitlink_packed_ref(struct ref_cache 
*refs,
return 0;
 }
 
-static int resolve_gitlink_ref_recursive(struct ref_cache *refs,
-const char *refname, unsigned char 
*sha1,
-int recursion)
-{
-   int fd, len;
-   char buffer[128], *p;
-   char *path;
-
-   if (recursion  MAXDEPTH || strlen(refname)  MAXREFLEN)
-   return -1;
-   path = *refs-name
-   ? git_path_submodule(refs-name, %s, refname)
-   : git_path(%s, refname);
-   fd = open(path, O_RDONLY);
-   if (fd  0)
-   return resolve_gitlink_packed_ref(refs, refname, sha1);
-
-   len = read(fd, buffer, sizeof(buffer)-1);
-   close(fd);
-   if (len  0)
-   return -1;
-   while (len  isspace(buffer[len-1]))
-   len--;
-   buffer[len] = 0;
-
-   /* Was it a detached head or an old-fashioned symlink? */
-   if (!get_sha1_hex(buffer, sha1))
-   return 0;
-
-   /* Symref? */
-   if (strncmp(buffer, ref:, 4))
-   return -1;
-   p = buffer + 4;
-   while (isspace(*p))
-   p++;
-
-   return resolve_gitlink_ref_recursive(refs, p, sha1, recursion+1);
-}
-
 int resolve_gitlink_ref(const char *path, const char *refname, unsigned char 
*sha1)
 {
-   int len = strlen(path), retval;
+   struct strbuf result = STRBUF_INIT;
+   int len = strlen(path), retval = 0;
+   int depth = MAXDEPTH;
char *submodule;
struct ref_cache *refs;
 
@@ -1489,8 +1452,24 @@ int resolve_gitlink_ref(const char *path, const char 
*refname, unsigned char *sh
refs = get_ref_cache(submodule);
free(submodule);
 
-   retval = resolve_gitlink_ref_recursive(refs, refname, sha1, 0);
-   return retval;
+   strbuf_addstr(result, refname);
+   while (!retval) {
+   if (--depth  0) {
+   errno = ELOOP;
+   retval = -1;
+   break;
+   }
+   path = *refs-name
+   ? git_path_submodule(refs-name, %s, result.buf)
+   : git_path(%s, result.buf);
+   retval = parse_ref(path, result, sha1, NULL);
+   if (retval == -2) {
+   retval = resolve_gitlink_packed_ref(refs, result.buf, 
sha1);
+   retval = retval ? -1 : 1;
+   }
+   }
+   strbuf_release(result);
+   return retval  0 ? 0 : -1;
 }
 
 /*
@@ -1540,6 +1519,11 @@ int parse_ref(const char *path, struct strbuf *ref,
struct stat st;
const char *buf;
 
+   if (ref-len  MAXREFLEN) {
+   errno = ENAMETOOLONG;
+   return -1;
+   }
+
/*
 * We might have to loop back here to avoid a race condition:
 * first we lstat() the file, then we try to read it as a link
-- 
1.9.1.346.ga2b5940

--
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/4] refs.c: move ref parsing code out of resolve_ref()

2014-07-25 Thread Nguyễn Thái Ngọc Duy
Signed-off-by: Nguyễn Thái Ngọc Duy pclo...@gmail.com
---
 cache.h |  11 
 refs.c  | 204 ++--
 2 files changed, 120 insertions(+), 95 deletions(-)

diff --git a/cache.h b/cache.h
index 5ffbafb..40a63d9 100644
--- a/cache.h
+++ b/cache.h
@@ -1003,6 +1003,17 @@ extern int read_ref(const char *refname, unsigned char 
*sha1);
 extern const char *resolve_ref_unsafe(const char *ref, unsigned char *sha1, 
int reading, int *flag);
 extern char *resolve_refdup(const char *ref, unsigned char *sha1, int reading, 
int *flag);
 extern int resolve_ref(const char *refname, struct strbuf *result, unsigned 
char *sha1, int reading, int *flag);
+/*
+ * Given a ref in ref and its path, returns
+ *
+ * -2  failed to open with ENOENT, the caller is responsible for
+ * checking missing loose ref (see resolve_ref for example)
+ * -1  if there's an error, ref can no longer be trusted, flag may
+ * be set. errno is valid.
+ *  0  this is a symref, ref now contains the linked ref
+ * +1  normal ref, sha1 is valid
+ */
+extern int parse_ref(const char *path, struct strbuf *ref, unsigned char 
*sha1, int *flag);
 
 extern int dwim_ref(const char *str, int len, unsigned char *sha1, char **ref);
 extern int dwim_log(const char *str, int len, unsigned char *sha1, char **ref);
diff --git a/refs.c b/refs.c
index bec2bb1..2769f20 100644
--- a/refs.c
+++ b/refs.c
@@ -1533,6 +1533,105 @@ static int handle_missing_loose_ref(const char *refname,
}
 }
 
+int parse_ref(const char *path, struct strbuf *ref,
+ unsigned char *sha1, int *flag)
+{
+   struct strbuf buffer = STRBUF_INIT;
+   struct stat st;
+   const char *buf;
+
+   /*
+* We might have to loop back here to avoid a race condition:
+* first we lstat() the file, then we try to read it as a link
+* or as a file.  But if somebody changes the type of the file
+* (file - directory - symlink) between the lstat() and
+* reading, then we don't want to report that as an error but
+* rather try again starting with the lstat().
+*/
+stat_ref:
+   if (lstat(path, st)  0)
+   return errno == ENOENT ? -2 : -1;
+
+   /* Follow normalized - ie refs/.. symlinks by hand */
+   if (S_ISLNK(st.st_mode)) {
+   struct strbuf new_path = STRBUF_INIT;
+   if (strbuf_readlink(new_path, path, 256)  0) {
+   strbuf_release(new_path);
+   if (errno == ENOENT || errno == EINVAL)
+   /* inconsistent with lstat; retry */
+   goto stat_ref;
+   else
+   return -1;
+   }
+   if (starts_with(new_path.buf, refs/) 
+   !check_refname_format(new_path.buf, 0)) {
+   strbuf_reset(ref);
+   strbuf_addbuf(ref, new_path);
+   if (flag)
+   *flag |= REF_ISSYMREF;
+   strbuf_release(new_path);
+   return 0;
+   }
+   strbuf_release(new_path);
+   }
+
+   /* Is it a directory? */
+   if (S_ISDIR(st.st_mode)) {
+   errno = EISDIR;
+   return -1;
+   }
+
+   /*
+* Anything else, just open it and try to use it as
+* a ref
+*/
+   if (strbuf_read_file(buffer, path, 256)  0) {
+   strbuf_release(buffer);
+   if (errno == ENOENT)
+   /* inconsistent with lstat; retry */
+   goto stat_ref;
+   else
+   return -1;
+   }
+   strbuf_rtrim(buffer);
+
+   /*
+* Is it a symbolic ref?
+*/
+   if (!skip_prefix(buffer.buf, ref:, buf)) {
+   int ret;
+   /*
+* Please note that FETCH_HEAD has a second line
+* containing other data.
+*/
+   if (get_sha1_hex(buffer.buf, sha1) ||
+   (buffer.buf[40] != '\0'  !isspace(buffer.buf[40]))) {
+   if (flag)
+   *flag |= REF_ISBROKEN;
+   errno = EINVAL;
+   ret = -1;
+   } else
+   ret = 1;
+   strbuf_release(buffer);
+   return ret;
+   }
+   if (flag)
+   *flag |= REF_ISSYMREF;
+   while (isspace(*buf))
+   buf++;
+   if (check_refname_format(buf, REFNAME_ALLOW_ONELEVEL)) {
+   if (flag)
+   *flag |= REF_ISBROKEN;
+   strbuf_release(buffer);
+   errno = EINVAL;
+   return -1;
+   }
+   strbuf_reset(ref);
+   strbuf_addstr(ref, buf);
+   strbuf_release(buffer);
+   return 0;
+}
+
 /*
  * 'result' content 

[PATCH 1/4] strbuf.c: keep errno in strbuf_read_file()

2014-07-25 Thread Nguyễn Thái Ngọc Duy
This function is used to replaced some code in the next patch that
does this (i.e. keep the errno when read() fails)

Signed-off-by: Nguyễn Thái Ngọc Duy pclo...@gmail.com
---
 strbuf.c | 7 +--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/strbuf.c b/strbuf.c
index 33018d8..61d685d 100644
--- a/strbuf.c
+++ b/strbuf.c
@@ -454,15 +454,18 @@ int strbuf_getwholeline_fd(struct strbuf *sb, int fd, int 
term)
 
 int strbuf_read_file(struct strbuf *sb, const char *path, size_t hint)
 {
-   int fd, len;
+   int fd, len, saved_errno;
 
fd = open(path, O_RDONLY);
if (fd  0)
return -1;
len = strbuf_read(sb, fd, hint);
+   saved_errno = errno;
close(fd);
-   if (len  0)
+   if (len  0) {
+   errno = saved_errno;
return -1;
+   }
 
return len;
 }
-- 
1.9.1.346.ga2b5940

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


MDaemon Notification -- Attachment Removed

2014-07-25 Thread Postmaster
? ? ?  ??, ???  ???:

From  : nore...@vger.kernel.org
To: git@vger.kernel.org
Subject   : Returned mail: Data format error
Message-ID: 

?? ???:
-
mail.zip (mail.doc  

.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: `ab | (cd cd git apply -)' fails with v2.0.0

2014-07-25 Thread Steffen Nurpmeso
Hello and good morning,

Michael J Gruber g...@drmicha.warpmail.net wrote:
 |Junio C Hamano venit, vidit, dixit 24.07.2014 19:19:
 | Michael J Gruber g...@drmicha.warpmail.net writes:
 | Steffen Nurpmeso venit, vidit, dixit 24.07.2014 15:29:
 | Hello (again, psst, after a long time),
 |
 | it happened yesterday that i needed to do
 |
 |   $ git diff HEAD:FILE COMMIT:SAME-FILE |
 | (cd src  git apply -) 
 | ...
 |
 | Ah little more context would help. Are you diffing files in the subdir
 | src, or a file at the root which happens to be present in the subdir src
 | as well?
 | 
 | As the treeish:path form is not meant to produce git apply
 | applicable patch in the first place, I am not sure what the OP is
 | trying to achieve in the first place.  Not just how many leading
 | levels to strip? but which file is being modified? does not
 | appear in a usable form.  For example, here is what you would see:
 | 
 | $ git diff HEAD:GIT-VERSION-GEN maint:GIT-VERSION-GEN
 | diff --git a/HEAD:GIT-VERSION-GEN b/maint:GIT-VERSION-GEN
 | index 40adbf7..0d1a86c 100755
 | --- a/HEAD:GIT-VERSION-GEN
 | +++ b/maint:GIT-VERSION-GEN
 | @@ -1,7 +1,7 @@
 | ...
 | 
 | and neither HEAD:GIT-VERSION-GEN nor maint:GIT-VERSION-GEN is
 | the file being modified (GIT-VERSION-GEN is).
 |
 |I thought git apply knows how to strip the rev part.

That would brighten the sky of the glorious future.  Perfect!

 | I would understand if the upstream of the pipe were
 | 
 | $ git diff HEAD maint -- GIT-VERSION-GEN | ...
 | 
 | though.

Yes, in this case it applies the patch.

 | Needless to say, if the place cd goes is not a worktree controlled
 | by git, then git apply would not know where the top-level of the
 | target tree is, so even though the input with the corrected command
 | on the upstream side of the pipe tells it which file is being
 | modified, it needs to be told with the proper -pn parameter how
 | many leading levels to strip.
 |
 |I think it's a common mistake to think of git apply as some sort of
 |magic extension of patch which can do anything that patch does and
 |more, and can be fed anything that git diff produces, figuring out by
 |itself what to do with it :)

This was indeed my mistake.
But regardless i think the current behaviour sucks:

  ?0[steffen@sherwood x.git]$ git diff HEAD:XY 5d0d74:XY |
   (cd src  patch -p4)
  can't find file to patch at input line 5
  Perhaps you used the wrong -p or --strip option?
  The text leading up to this was:
  ?130[steffen@sherwood x.git]$ git diff HEAD:XY 5d0d74:XY |
   (cd src  git apply -p4)
  ?0[steffen@sherwood x.git]$

and

  ?0[steffen@sherwood groff.git]$ git diff HEAD:XY 5d0d74:XY |
   (cd src  git apply -p2)
  ?0[steffen@sherwood groff.git]$ git diff HEAD:XY 5d0d74:XY |
   (cd src  patch -p2)
  patching file XY
  ?0[steffen@sherwood groff.git]$ 

The number after `?' is the exit status of the last command, btw.
Ciao (and yes, thanks a lot for git(1)!)

--steffen
--
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: What's cooking in git.git (Jul 2014, #04; Tue, 22)

2014-07-25 Thread Duy Nguyen
On Wed, Jul 23, 2014 at 9:17 PM, Karsten Blees karsten.bl...@gmail.com wrote:
 With the version in pu, three tests fail. t7001 is fixed with a newer 'cp'.
 The other two are unrelated (introduced by nd/multiple-work-trees topic).

 * t1501-worktree: failed 1
   As of 5bbcb072 setup.c: support multi-checkout repo setup
   Using $TRASH_DIRECTORY doesn't work on Windows.

 * t2026-prune-linked-checkouts: failed 1
   As of 404a45f1 prune: strategies for linked checkouts
   Dito.

I need your help here. Would saving $(pwd) to a variable and using it
instead of $TRASH_DIRECTORY work? Some tests cd around and $(pwd)
may not be the same as $TRASH_DIRECTORY.
-- 
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


Hello, how are you?

2014-07-25 Thread tel...@telmar.com.tr
Good afternoon, dear!
Are you tired of being alone?
You'll know how dreams come true
All what you need is here
Visit our website, this is something very special!
http://ta.gg/6sk

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


[PATCH v2 2/6] add line number and file name info to `config_set`

2014-07-25 Thread Tanay Abhra
Store file name and line number for each key-value pair in the cache
during parsing of the configuration files.

Signed-off-by: Tanay Abhra tanay...@gmail.com
---
 config.c | 19 ++-
 1 file changed, 18 insertions(+), 1 deletion(-)

diff --git a/config.c b/config.c
index 06257d9..110f9a5 100644
--- a/config.c
+++ b/config.c
@@ -1232,6 +1232,11 @@ int git_config_with_options(config_fn_t fn, void *data,
return ret;
 }
 
+struct key_value_info {
+   const char *filename;
+   int linenr;
+};
+
 int git_config(config_fn_t fn, void *data)
 {
return git_config_with_options(fn, data, NULL, 1);
@@ -1262,6 +1267,9 @@ static struct config_set_element 
*configset_find_element(struct config_set *cs,
 static int configset_add_value(struct config_set *cs, const char *key, const 
char *value)
 {
struct config_set_element *e;
+   struct string_list_item *si;
+   struct key_value_info *kv_info = xmalloc(sizeof(*kv_info));
+
e = configset_find_element(cs, key);
/*
 * Since the keys are being fed by git_config*() callback mechanism, 
they
@@ -1274,7 +1282,16 @@ static int configset_add_value(struct config_set *cs, 
const char *key, const cha
string_list_init(e-value_list, 1);
hashmap_add(cs-config_hash, e);
}
-   string_list_append_nodup(e-value_list, value ? xstrdup(value) : NULL);
+   si = string_list_append_nodup(e-value_list, value ? xstrdup(value) : 
NULL);
+   if (cf) {
+   kv_info-filename = strintern(cf-name);
+   kv_info-linenr = cf-linenr;
+   } else {
+   /* for values read from `git_config_from_parameters()` */
+   kv_info-filename = strintern(parameter);
+   kv_info-linenr = 0;
+   }
+   si-util = kv_info;
 
return 0;
 }
-- 
1.9.0.GIT

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


[PATCH v2 1/6] config.c: fix accuracy of line number in errors

2014-07-25 Thread Tanay Abhra
From: Matthieu Moy matthieu@grenoble-inp.fr

If a callback returns a negative value to `git_config*()` family,
they call `die()` while printing the line number and the file name.
Currently the printed line number is off by one, thus printing the
wrong line number.

Make `linenr` point to the line we just parsed during the call
to callback to get accurate line number in error messages.

Commit-message-by: Tanay Abhra tanay...@gmail.com
Signed-off-by: Tanay Abhra tanay...@gmail.com
---
 config.c | 12 +++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/config.c b/config.c
index 0d799e0..06257d9 100644
--- a/config.c
+++ b/config.c
@@ -244,6 +244,7 @@ static int get_next_char(void)
cf-linenr++;
if (c == EOF) {
cf-eof = 1;
+   cf-linenr++;
c = '\n';
}
return c;
@@ -319,6 +320,7 @@ static int get_value(config_fn_t fn, void *data, struct 
strbuf *name)
 {
int c;
char *value;
+   int ret;
 
/* Get the full name */
for (;;) {
@@ -341,7 +343,15 @@ static int get_value(config_fn_t fn, void *data, struct 
strbuf *name)
if (!value)
return -1;
}
-   return fn(name-buf, value, data);
+   /*
+* We already consumed the \n, but we need linenr to point to
+* the line we just parsed during the call to fn to get
+* accurate line number in error messages.
+*/
+   cf-linenr--;
+   ret = fn(name-buf, value, data);
+   cf-linenr++;
+   return ret;
 }
 
 static int get_extended_base_var(struct strbuf *name, int c)
-- 
1.9.0.GIT

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


[PATCH v2 0/6] Rewrite `git_config()` using config-set API

2014-07-25 Thread Tanay Abhra
[PATCH V2]: All the suggestions in [2] incorporated. git_config() now follows
correct parsing order. Reordered the patches. Removed xfuncname patch
as it was unnecssary.

This series builds on the top of 1d2856f (ta/config-set) in pu or topic[1]
in the mailing list with name git config cache  special querying API utilizing
the cache.

This series aims to do these three things,

* Use the config-set API to rewrite git_config().

* Solve any legacy bugs in the previous system while at it.

* To be feature complete compared to the previous git_config() implementation,
  which I think it is now. (added the line number and file name info just for
  completeness)

Also, I haven't yet checked the exact improvements but still as a teaser,
git status now only rereads the configuration files twice instead of four
times.

[1]: http://thread.gmane.org/gmane.comp.version-control.git/253862
[2]: http://thread.gmane.org/gmane.comp.version-control.git/254101

Tanay Abhra (6):
  config.c: fix accuracy of line number in errors
  add line number and file name info to `config_set`
  rewrite git_config() to use the config-set API
  add a test for semantic errors in config files
  config: add `git_die_config()` to the config-set API
  Add tests for `git_config_get_string()`

 Documentation/technical/api-config.txt |   5 ++
 cache.h|  26 +++
 config.c   | 135 -
 t/t1308-config-set.sh  |  20 +
 test-config.c  |  10 +++
 5 files changed, 175 insertions(+), 21 deletions(-)

-- 
1.9.0.GIT

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


[PATCH v2 4/6] add a test for semantic errors in config files

2014-07-25 Thread Tanay Abhra
Semantic errors (for example, for alias.* variables NULL values are
not allowed) in configuration files cause a die printing the line
number and file name of the offending value.

Add a test documenting that such errors cause a die printing the
accurate line number and file name.

Signed-off-by: Tanay Abhra tanay...@gmail.com
---
 t/t1308-config-set.sh | 11 +++
 1 file changed, 11 insertions(+)

diff --git a/t/t1308-config-set.sh b/t/t1308-config-set.sh
index 7fdf840..35c6ee2 100755
--- a/t/t1308-config-set.sh
+++ b/t/t1308-config-set.sh
@@ -197,4 +197,15 @@ test_expect_success 'proper error on error in custom 
config files' '
test_cmp expect actual
 '
 
+test_expect_success 'check line errors for malformed values' '
+   mv .git/config .git/config.old 
+   test_when_finished mv .git/config.old .git/config 
+   cat .git/config -\EOF 
+   [alias]
+   br
+   EOF
+   test_expect_code 128 git br 2result 
+   grep fatal: bad config file line 2 in .git/config result
+'
+
 test_done
-- 
1.9.0.GIT

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


[PATCH v2 3/6] rewrite git_config() to use the config-set API

2014-07-25 Thread Tanay Abhra
Of all the functions in `git_config*()` family, `git_config()` has the
most invocations in the whole code base. Each `git_config()` invocation
causes config file rereads which can be avoided using the config-set API.

Use the config-set API to rewrite `git_config()` to use the config caching
layer to avoid config file rereads on each invocation during a git process
lifetime. First invocation constructs the cache, and after that for each
successive invocation, `git_config()` feeds values from the config cache
instead of rereading the configuration files.

Signed-off-by: Tanay Abhra tanay...@gmail.com
---
 cache.h  | 25 +
 config.c | 60 +++-
 2 files changed, 76 insertions(+), 9 deletions(-)

diff --git a/cache.h b/cache.h
index 7292aef..11ded5a 100644
--- a/cache.h
+++ b/cache.h
@@ -8,6 +8,7 @@
 #include gettext.h
 #include convert.h
 #include trace.h
+#include string-list.h
 
 #include SHA1_HEADER
 #ifndef git_SHA_CTX
@@ -1351,9 +1352,33 @@ extern int parse_config_key(const char *var,
const char **subsection, int *subsection_len,
const char **key);
 
+struct config_set_element {
+   struct hashmap_entry ent;
+   char *key;
+   struct string_list value_list;
+};
+
+struct configset_list_item {
+   struct config_set_element *e;
+   int value_index;
+};
+
+/*
+ * the contents of the list are ordered according to their
+ * position in the config files and order of parsing the files.
+ * (i.e. key-value pair at the last position of .git/config will
+ * be at the last item of the list)
+ */
+
+struct configset_list {
+   struct configset_list_item *items;
+   unsigned int nr, alloc;
+};
+
 struct config_set {
struct hashmap config_hash;
int hash_initialized;
+   struct configset_list list;
 };
 
 extern void git_configset_init(struct config_set *cs);
diff --git a/config.c b/config.c
index 110f9a5..aa5c0ad 100644
--- a/config.c
+++ b/config.c
@@ -35,12 +35,6 @@ struct config_source {
long (*do_ftell)(struct config_source *c);
 };
 
-struct config_set_element {
-   struct hashmap_entry ent;
-   char *key;
-   struct string_list value_list;
-};
-
 static struct config_source *cf;
 
 static int zlib_compression_seen;
@@ -1237,11 +1231,44 @@ struct key_value_info {
int linenr;
 };
 
-int git_config(config_fn_t fn, void *data)
+static int git_config_raw(config_fn_t fn, void *data)
 {
return git_config_with_options(fn, data, NULL, 1);
 }
 
+static int configset_iter(struct config_set *cs, config_fn_t fn, void *data)
+{
+   int i, value_index;
+   struct string_list *values;
+   struct config_set_element *entry;
+   struct configset_list *list = cs-list;
+   struct key_value_info *kv_info;
+
+   for (i = 0; i  list-nr; i++) {
+   entry = list-items[i].e;
+   value_index = list-items[i].value_index;
+   values = entry-value_list;
+   if (fn(entry-key, values-items[value_index].string, data)  
0) {
+   kv_info = values-items[value_index].util;
+   if (!kv_info-linenr)
+   die(unable to parse command-line config);
+   else
+   die(bad config file line %d in %s,
+   kv_info-linenr,
+   kv_info-filename);
+   }
+   }
+   return 0;
+}
+
+static void git_config_check_init(void);
+
+int git_config(config_fn_t fn, void *data)
+{
+   git_config_check_init();
+   return configset_iter(the_config_set, fn, data);
+}
+
 static struct config_set_element *configset_find_element(struct config_set 
*cs, const char *key)
 {
struct config_set_element k;
@@ -1268,6 +1295,7 @@ static int configset_add_value(struct config_set *cs, 
const char *key, const cha
 {
struct config_set_element *e;
struct string_list_item *si;
+   struct configset_list_item *l_item;
struct key_value_info *kv_info = xmalloc(sizeof(*kv_info));
 
e = configset_find_element(cs, key);
@@ -1283,6 +1311,13 @@ static int configset_add_value(struct config_set *cs, 
const char *key, const cha
hashmap_add(cs-config_hash, e);
}
si = string_list_append_nodup(e-value_list, value ? xstrdup(value) : 
NULL);
+
+   if (cs-list.nr + 1  cs-list.alloc)
+   ALLOC_GROW(cs-list.items, cs-list.nr + 20, cs-list.alloc);
+   l_item = cs-list.items[cs-list.nr++];
+   l_item-e = e;
+   l_item-value_index = e-value_list.nr - 1;
+
if (cf) {
kv_info-filename = strintern(cf-name);
kv_info-linenr = cf-linenr;
@@ -1306,6 +1341,9 @@ void git_configset_init(struct config_set *cs)
 {
hashmap_init(cs-config_hash, (hashmap_cmp_fn)config_set_element_cmp, 
0);
 

[PATCH v2 6/6] Add tests for `git_config_get_string()`

2014-07-25 Thread Tanay Abhra
Add tests for `git_config_get_string()`, check whether it
dies printing the line number and the file name if a NULL
value is retrieved for the given key.

Signed-off-by: Tanay Abhra tanay...@gmail.com
---
 t/t1308-config-set.sh |  9 +
 test-config.c | 10 ++
 2 files changed, 19 insertions(+)

diff --git a/t/t1308-config-set.sh b/t/t1308-config-set.sh
index 35c6ee2..d7cdc6e 100755
--- a/t/t1308-config-set.sh
+++ b/t/t1308-config-set.sh
@@ -119,6 +119,15 @@ test_expect_success 'find integer value for a key' '
check_config get_int lamb.chop 65
 '
 
+test_expect_success 'find string value for a key' '
+   check_config get_string case.baz hask
+'
+
+test_expect_success 'check line error when NULL string is queried' '
+   test_expect_code 128 test-config get_string case.foo 2result 
+   grep fatal: bad config file line 7 in .git/config result
+'
+
 test_expect_success 'find integer if value is non parse-able' '
check_config expect_code 128 get_int lamb.head
 '
diff --git a/test-config.c b/test-config.c
index 9dd1b22..6a77552 100644
--- a/test-config.c
+++ b/test-config.c
@@ -16,6 +16,8 @@
  *
  * get_bool - print bool value for the entered key or die
  *
+ * get_string - print string value for the entered key or die
+ *
  * configset_get_value - returns value with the highest priority for the 
entered key
  * from a config_set constructed from files entered as 
arguments.
  *
@@ -84,6 +86,14 @@ int main(int argc, char **argv)
printf(Value not found for \%s\\n, argv[2]);
goto exit1;
}
+   } else if (argc == 3  !strcmp(argv[1], get_string)) {
+   if (!git_config_get_string_const(argv[2], v)) {
+   printf(%s\n, v);
+   goto exit0;
+   } else {
+   printf(Value not found for \%s\\n, argv[2]);
+   goto exit1;
+   }
} else if (!strcmp(argv[1], configset_get_value)) {
for (i = 3; i  argc; i++) {
int err;
-- 
1.9.0.GIT

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


[PATCH v2 5/6] config: add `git_die_config()` to the config-set API

2014-07-25 Thread Tanay Abhra
Add `git_die_config` that dies printing the line number and the file name
of the highest priority value for the configuration variable `key`.

It has usage in non-callback based config value retrieval where we can
raise an error and die if there is a semantic error.
For example,

if (!git_config_get_value(key, value)) {
/* NULL values not allowed */
if (!value)
git_config_die(key);
else
/* do work */
}

Signed-off-by: Tanay Abhra tanay...@gmail.com
---
 Documentation/technical/api-config.txt |  5 
 cache.h|  1 +
 config.c   | 44 ++
 3 files changed, 40 insertions(+), 10 deletions(-)

diff --git a/Documentation/technical/api-config.txt 
b/Documentation/technical/api-config.txt
index 815c1ee..e7ec7cc 100644
--- a/Documentation/technical/api-config.txt
+++ b/Documentation/technical/api-config.txt
@@ -155,6 +155,11 @@ as well as retrieval for the queried variable, including:
Similar to `git_config_get_string`, but expands `~` or `~user` into
the user's home directory when found at the beginning of the path.
 
+`void git_die_config(const char *key)`::
+
+   Dies printing the line number and the file name of the highest
+   priority value for the configuration variable `key`.
+
 See test-config.c for usage examples.
 
 Value Parsing Helpers
diff --git a/cache.h b/cache.h
index 11ded5a..5c3dd88 100644
--- a/cache.h
+++ b/cache.h
@@ -1407,6 +1407,7 @@ extern int git_config_get_bool(const char *key, int 
*dest);
 extern int git_config_get_bool_or_int(const char *key, int *is_bool, int 
*dest);
 extern int git_config_get_maybe_bool(const char *key, int *dest);
 extern int git_config_get_pathname(const char *key, const char **dest);
+extern void git_die_config(const char *key);
 
 extern int committer_ident_sufficiently_given(void);
 extern int author_ident_sufficiently_given(void);
diff --git a/config.c b/config.c
index aa5c0ad..1e49ae7 100644
--- a/config.c
+++ b/config.c
@@ -1403,11 +1403,12 @@ const struct string_list 
*git_configset_get_value_multi(struct config_set *cs, c
 
 int git_configset_get_string_const(struct config_set *cs, const char *key, 
const char **dest)
 {
-   const char *value;
-   if (!git_configset_get_value(cs, key, value))
-   return git_config_string(dest, key, value);
-   else
-   return 1;
+   int ret;
+   char *value;
+   ret = git_configset_get_string(cs, key, value);
+   if (ret = 0)
+   *dest = (const char*)value;
+   return ret;
 }
 
 int git_configset_get_string(struct config_set *cs, const char *key, char 
**dest)
@@ -1418,8 +1419,7 @@ int git_configset_get_string(struct config_set *cs, const 
char *key, char **dest
return config_error_nonbool(key);
*dest = xstrdup(value);
return 0;
-   }
-   else
+   } else
return 1;
 }
 
@@ -1514,14 +1514,22 @@ const struct string_list 
*git_config_get_value_multi(const char *key)
 
 int git_config_get_string_const(const char *key, const char **dest)
 {
+   int ret;
git_config_check_init();
-   return git_configset_get_string_const(the_config_set, key, dest);
+   ret = git_configset_get_string_const(the_config_set, key, dest);
+   if (ret  0)
+   git_die_config(key);
+   return ret;
 }
 
 int git_config_get_string(const char *key, char **dest)
 {
+   int ret;
git_config_check_init();
-   return git_configset_get_string(the_config_set, key, dest);
+   ret = git_configset_get_string(the_config_set, key, dest);
+   if (ret  0)
+   git_die_config(key);
+   return ret;
 }
 
 int git_config_get_int(const char *key, int *dest)
@@ -1556,8 +1564,24 @@ int git_config_get_maybe_bool(const char *key, int *dest)
 
 int git_config_get_pathname(const char *key, const char **dest)
 {
+   int ret;
git_config_check_init();
-   return git_configset_get_pathname(the_config_set, key, dest);
+   ret = git_configset_get_pathname(the_config_set, key, dest);
+   if (ret  0)
+   git_die_config(key);
+   return ret;
+}
+
+void git_die_config(const char *key)
+{
+   const struct string_list *values;
+   struct key_value_info *kv_info;
+   values = git_config_get_value_multi(key);
+   kv_info = values-items[values-nr - 1].util;
+   if (!kv_info-linenr)
+   die(unable to parse command-line config);
+   else
+   die(bad config file line %d in %s,kv_info-linenr, 
kv_info-filename);
 }
 
 /*
-- 
1.9.0.GIT

--
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/3] commit: advertize config --global --edit on guessed identity

2014-07-25 Thread Matthieu Moy
When the user has no user-wide configuration file, it's faster to use the
newly introduced config file template than to run two commands to set
user.name and user.email. Advise this to the user.

The old advice is kept if the user already has a configuration file since
the template feature would not trigger in this case.

Signed-off-by: Matthieu Moy matthieu@imag.fr
---
 builtin/commit.c | 34 --
 1 file changed, 32 insertions(+), 2 deletions(-)

diff --git a/builtin/commit.c b/builtin/commit.c
index f2d7979..52ef5a8 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -42,7 +42,20 @@ static const char * const builtin_status_usage[] = {
NULL
 };
 
-static const char implicit_ident_advice[] =
+static const char implicit_ident_advice_noconfig[] =
+N_(Your name and email address were configured automatically based\n
+on your username and hostname. Please check that they are accurate.\n
+You can suppress this message by setting them explicitly. Run the\n
+following command and follow the instructions in your editor to edit\n
+your configuration file:\n
+\n
+git config --global --edit\n
+\n
+After doing this, you may fix the identity used for this commit with:\n
+\n
+git commit --amend --reset-author\n);
+
+static const char implicit_ident_advice_config[] =
 N_(Your name and email address were configured automatically based\n
 on your username and hostname. Please check that they are accurate.\n
 You can suppress this message by setting them explicitly:\n
@@ -1403,6 +1416,23 @@ int cmd_status(int argc, const char **argv, const char 
*prefix)
return 0;
 }
 
+static const char *implicit_ident_advice() {
+   char *user_config = NULL;
+   char *xdg_config = NULL;
+   int config_exists;
+
+   home_config_paths(user_config, xdg_config, config);
+   config_exists = file_exists(user_config) || file_exists(xdg_config);
+   free(user_config);
+   free(xdg_config);
+
+   if (config_exists)
+   return _(implicit_ident_advice_config);
+   else
+   return _(implicit_ident_advice_noconfig);
+
+}
+
 static void print_summary(const char *prefix, const unsigned char *sha1,
  int initial_commit)
 {
@@ -1441,7 +1471,7 @@ static void print_summary(const char *prefix, const 
unsigned char *sha1,
strbuf_addbuf_percentquote(format, committer_ident);
if (advice_implicit_identity) {
strbuf_addch(format, '\n');
-   strbuf_addstr(format, _(implicit_ident_advice));
+   strbuf_addstr(format, implicit_ident_advice());
}
}
strbuf_release(author_ident);
-- 
2.0.2.737.gfb43bde

--
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/3] config --global --edit: create a template file if needed

2014-07-25 Thread Matthieu Moy
When the user has no ~/.gitconfig file, git config --global --edit used
to launch an editor on an nonexistant file name.

Instead, create a file with a default content before launching the
editor. The template contains only commented-out entries, to save a few
keystrokes for the user. If the values are guessed properly, the user
will only have to uncomment the entries.

Advanced users teaching newbies can create a minimalistic configuration
faster for newbies. Beginners reading a tutorial advising to run git
config --global --edit as a first step will be slightly more guided for
their first contact with Git.

Signed-off-by: Matthieu Moy matthieu@imag.fr
---
 builtin/config.c | 30 +++---
 cache.h  |  1 +
 ident.c  |  2 +-
 3 files changed, 29 insertions(+), 4 deletions(-)

diff --git a/builtin/config.c b/builtin/config.c
index fcd8474..3821697 100644
--- a/builtin/config.c
+++ b/builtin/config.c
@@ -445,6 +445,20 @@ static int get_urlmatch(const char *var, const char *url)
return 0;
 }
 
+static char *default_user_config()
+{
+   struct strbuf buf = STRBUF_INIT;
+   strbuf_addf(buf,
+   _(# This is Git's user-wide configuration file.\n
+ [core]\n
+ # Please, adapt and uncomment the following lines:\n
+ #user = %s\n
+ #email = %s\n),
+   ident_default_name(),
+   ident_default_email());
+   return strbuf_detach(buf, NULL);
+}
+
 int cmd_config(int argc, const char **argv, const char *prefix)
 {
int nongit = !startup_info-have_repository;
@@ -551,6 +565,8 @@ int cmd_config(int argc, const char **argv, const char 
*prefix)
}
}
else if (actions == ACTION_EDIT) {
+   const char *config_file = given_config_source.file ?
+   given_config_source.file : git_path(config);
check_argc(argc, 0, 0);
if (!given_config_source.file  nongit)
die(not in a git directory);
@@ -559,9 +575,17 @@ int cmd_config(int argc, const char **argv, const char 
*prefix)
if (given_config_source.blob)
die(editing blobs is not supported);
git_config(git_default_config, NULL);
-   launch_editor(given_config_source.file ?
- given_config_source.file : git_path(config),
- NULL, NULL);
+   if (use_global_config) {
+   int fd = open(config_file, O_CREAT | O_EXCL | O_WRONLY, 
0666);
+   if (fd) {
+   char *content = default_user_config();
+   write_str_in_full(fd, content);
+   free(content);
+   }
+   else if (errno != EEXIST)
+   die_errno(_(Cannot create configuration file 
%s), config_file);
+   }
+   launch_editor(config_file, NULL, NULL);
}
else if (actions == ACTION_SET) {
int ret;
diff --git a/cache.h b/cache.h
index 2f63fd1..8c79c0c 100644
--- a/cache.h
+++ b/cache.h
@@ -1061,6 +1061,7 @@ extern const char *git_author_info(int);
 extern const char *git_committer_info(int);
 extern const char *fmt_ident(const char *name, const char *email, const char 
*date_str, int);
 extern const char *fmt_name(const char *name, const char *email);
+extern const char *ident_default_name(void);
 extern const char *ident_default_email(void);
 extern const char *git_editor(void);
 extern const char *git_pager(int stdout_is_tty);
diff --git a/ident.c b/ident.c
index 1d9b6e7..77bc882 100644
--- a/ident.c
+++ b/ident.c
@@ -102,7 +102,7 @@ static void copy_email(const struct passwd *pw, struct 
strbuf *email)
add_domainname(email);
 }
 
-static const char *ident_default_name(void)
+const char *ident_default_name(void)
 {
if (!git_default_name.len) {
copy_gecos(xgetpwuid_self(), git_default_name);
-- 
2.0.2.737.gfb43bde

--
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/3] home_config_path: allow NULL xdg parameter

2014-07-25 Thread Matthieu Moy
This allows a caller to requst the global config file without requesting
the XDG one.

Signed-off-by: Matthieu Moy matthieu@imag.fr
---
This is actually not needed, but I wrote this for a previous version,
and it seems sensible anyway.

 path.c | 10 ++
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/path.c b/path.c
index 3afcdb4..f68df0c 100644
--- a/path.c
+++ b/path.c
@@ -148,10 +148,12 @@ void home_config_paths(char **global, char **xdg, char 
*file)
*global = mkpathdup(%s/.gitconfig, home);
}
 
-   if (!xdg_home)
-   *xdg = NULL;
-   else
-   *xdg = mkpathdup(%s/git/%s, xdg_home, file);
+   if (xdg) {
+   if (!xdg_home)
+   *xdg = NULL;
+   else
+   *xdg = mkpathdup(%s/git/%s, xdg_home, file);
+   }
 
free(to_free);
 }
-- 
2.0.2.737.gfb43bde

--
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 2/3] home_config_path: allow NULL xdg parameter

2014-07-25 Thread Tanay Abhra
On 7/25/2014 7:14 PM, Matthieu Moy wrote:
 This allows a caller to requst the global config file without requesting
nit s/requst/request/
--
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 3/6] rewrite git_config() to use the config-set API

2014-07-25 Thread Matthieu Moy
Tanay Abhra tanay...@gmail.com writes:

 +struct config_set_element {
 + struct hashmap_entry ent;
 + char *key;
 + struct string_list value_list;
 +};
 +
 +struct configset_list_item {
 + struct config_set_element *e;
 + int value_index;
 +};

I originally wondered why you had two levels of pointers, but
config_set_element is not new, just moved. It's OK.

 +/*
 + * the contents of the list are ordered according to their
 + * position in the config files and order of parsing the files.
 + * (i.e. key-value pair at the last position of .git/config will
 + * be at the last item of the list)
 + */
 +
 +struct configset_list {

I wouldn't put a blank line between comment and decl if the comment
applies to the decl.

 -int git_config(config_fn_t fn, void *data)
 +static int git_config_raw(config_fn_t fn, void *data)
  {
   return git_config_with_options(fn, data, NULL, 1);
  }

I would have done this and the new git_config() as a separate patch, but
I do not mind strongly.

  static struct config_set_element *configset_find_element(struct config_set 
 *cs, const char *key)
  {
   struct config_set_element k;
 @@ -1268,6 +1295,7 @@ static int configset_add_value(struct config_set *cs, 
 const char *key, const cha
  {
   struct config_set_element *e;
   struct string_list_item *si;
 + struct configset_list_item *l_item;
   struct key_value_info *kv_info = xmalloc(sizeof(*kv_info));
  
   e = configset_find_element(cs, key);
 @@ -1283,6 +1311,13 @@ static int configset_add_value(struct config_set *cs, 
 const char *key, const cha
   hashmap_add(cs-config_hash, e);
   }
   si = string_list_append_nodup(e-value_list, value ? xstrdup(value) : 
 NULL);
 +
 + if (cs-list.nr + 1  cs-list.alloc)

The if is already in ALLOC_GROW.

 + ALLOC_GROW(cs-list.items, cs-list.nr + 20, cs-list.alloc);

The 20 should be just 1 I guess. You're adding 1 element, and ALLOC_GROW
will take care of allocating more than 1 for you (see alloc_nr and
ALLOC_GROW's defs in cache.h).

 @@ -1318,10 +1356,14 @@ void git_configset_clear(struct config_set *cs)
   hashmap_iter_init(cs-config_hash, iter);
   while ((entry = hashmap_iter_next(iter))) {
   free(entry-key);
 - string_list_clear(entry-value_list, 0);
 + string_list_clear(entry-value_list, 1);

Doesn't this change belong to PATCH 2/6 ?

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


Re: [PATCH v2 5/6] config: add `git_die_config()` to the config-set API

2014-07-25 Thread Matthieu Moy
Tanay Abhra tanay...@gmail.com writes:

 --- a/config.c
 +++ b/config.c
 @@ -1403,11 +1403,12 @@ const struct string_list 
 *git_configset_get_value_multi(struct config_set *cs, c
  
  int git_configset_get_string_const(struct config_set *cs, const char *key, 
 const char **dest)
  {
 - const char *value;
 - if (!git_configset_get_value(cs, key, value))
 - return git_config_string(dest, key, value);
 - else
 - return 1;
 + int ret;
 + char *value;
 + ret = git_configset_get_string(cs, key, value);
 + if (ret = 0)
 + *dest = (const char*)value;
 + return ret;
  }

Isn't this a fixup meant for another series?

  int git_configset_get_string(struct config_set *cs, const char *key, char 
 **dest)
 @@ -1418,8 +1419,7 @@ int git_configset_get_string(struct config_set *cs, 
 const char *key, char **dest
   return config_error_nonbool(key);
   *dest = xstrdup(value);
   return 0;
 - }
 - else
 + } else
   return 1;

Useless churn.

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


Re: [PATCH v2 3/6] rewrite git_config() to use the config-set API

2014-07-25 Thread Tanay Abhra


On 7/25/2014 7:28 PM, Matthieu Moy wrote:
 Tanay Abhra tanay...@gmail.com writes:
 
 +struct config_set_element {
 +struct hashmap_entry ent;
 +char *key;
 +struct string_list value_list;
 +};
 +
 +struct configset_list_item {
 +struct config_set_element *e;
 +int value_index;
 +};
 
 I originally wondered why you had two levels of pointers, but
 config_set_element is not new, just moved. It's OK.
 
 +/*
 + * the contents of the list are ordered according to their
 + * position in the config files and order of parsing the files.
 + * (i.e. key-value pair at the last position of .git/config will
 + * be at the last item of the list)
 + */
 +
 +struct configset_list {
 
 I wouldn't put a blank line between comment and decl if the comment
 applies to the decl.


Noted.

 -int git_config(config_fn_t fn, void *data)
 +static int git_config_raw(config_fn_t fn, void *data)
  {
  return git_config_with_options(fn, data, NULL, 1);
  }
 
 I would have done this and the new git_config() as a separate patch, but
 I do not mind strongly.
 
  static struct config_set_element *configset_find_element(struct config_set 
 *cs, const char *key)
  {
  struct config_set_element k;
 @@ -1268,6 +1295,7 @@ static int configset_add_value(struct config_set *cs, 
 const char *key, const cha
  {
  struct config_set_element *e;
  struct string_list_item *si;
 +struct configset_list_item *l_item;
  struct key_value_info *kv_info = xmalloc(sizeof(*kv_info));
  
  e = configset_find_element(cs, key);
 @@ -1283,6 +1311,13 @@ static int configset_add_value(struct config_set *cs, 
 const char *key, const cha
  hashmap_add(cs-config_hash, e);
  }
  si = string_list_append_nodup(e-value_list, value ? xstrdup(value) : 
 NULL);
 +
 +if (cs-list.nr + 1  cs-list.alloc)
 
 The if is already in ALLOC_GROW.
 
 +ALLOC_GROW(cs-list.items, cs-list.nr + 20, cs-list.alloc);
 
 The 20 should be just 1 I guess. You're adding 1 element, and ALLOC_GROW
 will take care of allocating more than 1 for you (see alloc_nr and
 ALLOC_GROW's defs in cache.h).


Oh, you are are right, I thought alloc grew by one, not by a factor.

 @@ -1318,10 +1356,14 @@ void git_configset_clear(struct config_set *cs)
  hashmap_iter_init(cs-config_hash, iter);
  while ((entry = hashmap_iter_next(iter))) {
  free(entry-key);
 -string_list_clear(entry-value_list, 0);
 +string_list_clear(entry-value_list, 1);
 
 Doesn't this change belong to PATCH 2/6 ?
 

Yup, you are right again.
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 v2 5/6] config: add `git_die_config()` to the config-set API

2014-07-25 Thread Tanay Abhra


On 7/25/2014 7:33 PM, Matthieu Moy wrote:
 Tanay Abhra tanay...@gmail.com writes:
 
 --- a/config.c
 +++ b/config.c
 @@ -1403,11 +1403,12 @@ const struct string_list 
 *git_configset_get_value_multi(struct config_set *cs, c
  
  int git_configset_get_string_const(struct config_set *cs, const char *key, 
 const char **dest)
  {
 -const char *value;
 -if (!git_configset_get_value(cs, key, value))
 -return git_config_string(dest, key, value);
 -else
 -return 1;
 +int ret;
 +char *value;
 +ret = git_configset_get_string(cs, key, value);
 +if (ret = 0)
 +*dest = (const char*)value;
 +return ret;
  }
 
 Isn't this a fixup meant for another series?


Though v12 is in pu, Junio commented that git_configset_get_string_const() 
git_configset_get_string() can be done more concisely, I was trying to do
that but I failed.

  int git_configset_get_string(struct config_set *cs, const char *key, char 
 **dest)
 @@ -1418,8 +1419,7 @@ int git_configset_get_string(struct config_set *cs, 
 const char *key, char **dest
  return config_error_nonbool(key);
  *dest = xstrdup(value);
  return 0;
 -}
 -else
 +} else
  return 1;
 
 Useless churn.
 
--
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 1/3] config --global --edit: create a template file if needed

2014-07-25 Thread Eric Sunshine
On Fri, Jul 25, 2014 at 9:44 AM, Matthieu Moy matthieu@imag.fr wrote:
 When the user has no ~/.gitconfig file, git config --global --edit used
 to launch an editor on an nonexistant file name.

 Instead, create a file with a default content before launching the
 editor. The template contains only commented-out entries, to save a few
 keystrokes for the user. If the values are guessed properly, the user
 will only have to uncomment the entries.

 Advanced users teaching newbies can create a minimalistic configuration
 faster for newbies. Beginners reading a tutorial advising to run git
 config --global --edit as a first step will be slightly more guided for
 their first contact with Git.

 Signed-off-by: Matthieu Moy matthieu@imag.fr
 ---
  builtin/config.c | 30 +++---
  cache.h  |  1 +
  ident.c  |  2 +-
  3 files changed, 29 insertions(+), 4 deletions(-)

 diff --git a/builtin/config.c b/builtin/config.c
 index fcd8474..3821697 100644
 --- a/builtin/config.c
 +++ b/builtin/config.c
 @@ -445,6 +445,20 @@ static int get_urlmatch(const char *var, const char *url)
 return 0;
  }

 +static char *default_user_config()
 +{
 +   struct strbuf buf = STRBUF_INIT;
 +   strbuf_addf(buf,
 +   _(# This is Git's user-wide configuration file.\n
 + [core]\n
 + # Please, adapt and uncomment the following lines:\n
 + #user = %s\n
 + #email = %s\n),

[core], user =, email = should not be translated. Would it make
sense to keep these outside of _()?

 +   ident_default_name(),
 +   ident_default_email());
 +   return strbuf_detach(buf, NULL);
 +}
 +
  int cmd_config(int argc, const char **argv, const char *prefix)
  {
 int nongit = !startup_info-have_repository;
 @@ -551,6 +565,8 @@ int cmd_config(int argc, const char **argv, const char 
 *prefix)
 }
 }
 else if (actions == ACTION_EDIT) {
 +   const char *config_file = given_config_source.file ?
 +   given_config_source.file : git_path(config);
 check_argc(argc, 0, 0);
 if (!given_config_source.file  nongit)
 die(not in a git directory);
 @@ -559,9 +575,17 @@ int cmd_config(int argc, const char **argv, const char 
 *prefix)
 if (given_config_source.blob)
 die(editing blobs is not supported);
 git_config(git_default_config, NULL);
 -   launch_editor(given_config_source.file ?
 - given_config_source.file : git_path(config),
 - NULL, NULL);
 +   if (use_global_config) {
 +   int fd = open(config_file, O_CREAT | O_EXCL | 
 O_WRONLY, 0666);
 +   if (fd) {
 +   char *content = default_user_config();
 +   write_str_in_full(fd, content);

close(fd);

 +   free(content);
 +   }
 +   else if (errno != EEXIST)
 +   die_errno(_(Cannot create configuration file 
 %s), config_file);

Other error messages in this file (including those just above this
block) begin with a lowercase letter.

 +   }
 +   launch_editor(config_file, NULL, NULL);
 }
 else if (actions == ACTION_SET) {
 int ret;
 diff --git a/cache.h b/cache.h
 index 2f63fd1..8c79c0c 100644
 --- a/cache.h
 +++ b/cache.h
 @@ -1061,6 +1061,7 @@ extern const char *git_author_info(int);
  extern const char *git_committer_info(int);
  extern const char *fmt_ident(const char *name, const char *email, const char 
 *date_str, int);
  extern const char *fmt_name(const char *name, const char *email);
 +extern const char *ident_default_name(void);
  extern const char *ident_default_email(void);
  extern const char *git_editor(void);
  extern const char *git_pager(int stdout_is_tty);
 diff --git a/ident.c b/ident.c
 index 1d9b6e7..77bc882 100644
 --- a/ident.c
 +++ b/ident.c
 @@ -102,7 +102,7 @@ static void copy_email(const struct passwd *pw, struct 
 strbuf *email)
 add_domainname(email);
  }

 -static const char *ident_default_name(void)
 +const char *ident_default_name(void)
  {
 if (!git_default_name.len) {
 copy_gecos(xgetpwuid_self(), git_default_name);
 --
 2.0.2.737.gfb43bde
--
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/4] strbuf.c: keep errno in strbuf_read_file()

2014-07-25 Thread Eric Sunshine
On Fri, Jul 25, 2014 at 6:43 AM, Nguyễn Thái Ngọc Duy pclo...@gmail.com wrote:
 This function is used to replaced some code in the next patch that

s/replaced/replace/

 does this (i.e. keep the errno when read() fails)

 Signed-off-by: Nguyễn Thái Ngọc Duy pclo...@gmail.com
 ---
  strbuf.c | 7 +--
  1 file changed, 5 insertions(+), 2 deletions(-)

 diff --git a/strbuf.c b/strbuf.c
 index 33018d8..61d685d 100644
 --- a/strbuf.c
 +++ b/strbuf.c
 @@ -454,15 +454,18 @@ int strbuf_getwholeline_fd(struct strbuf *sb, int fd, 
 int term)

  int strbuf_read_file(struct strbuf *sb, const char *path, size_t hint)
  {
 -   int fd, len;
 +   int fd, len, saved_errno;

 fd = open(path, O_RDONLY);
 if (fd  0)
 return -1;
 len = strbuf_read(sb, fd, hint);
 +   saved_errno = errno;
 close(fd);
 -   if (len  0)
 +   if (len  0) {
 +   errno = saved_errno;
 return -1;
 +   }

 return len;
  }
 --
 1.9.1.346.ga2b5940

 --
 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: [RFC PATCH 3/3] commit: advertize config --global --edit on guessed identity

2014-07-25 Thread Eric Sunshine
On Fri, Jul 25, 2014 at 9:44 AM, Matthieu Moy matthieu@imag.fr wrote:
 commit: advertize config --global --edit on guessed identity

s/advertize/advertise/

 When the user has no user-wide configuration file, it's faster to use the
 newly introduced config file template than to run two commands to set
 user.name and user.email. Advise this to the user.

 The old advice is kept if the user already has a configuration file since
 the template feature would not trigger in this case.

 Signed-off-by: Matthieu Moy matthieu@imag.fr
 ---
  builtin/commit.c | 34 --
  1 file changed, 32 insertions(+), 2 deletions(-)

 diff --git a/builtin/commit.c b/builtin/commit.c
 index f2d7979..52ef5a8 100644
 --- a/builtin/commit.c
 +++ b/builtin/commit.c
 @@ -42,7 +42,20 @@ static const char * const builtin_status_usage[] = {
 NULL
  };

 -static const char implicit_ident_advice[] =
 +static const char implicit_ident_advice_noconfig[] =
 +N_(Your name and email address were configured automatically based\n
 +on your username and hostname. Please check that they are accurate.\n
 +You can suppress this message by setting them explicitly. Run the\n
 +following command and follow the instructions in your editor to edit\n
 +your configuration file:\n
 +\n
 +git config --global --edit\n
 +\n
 +After doing this, you may fix the identity used for this commit with:\n
 +\n
 +git commit --amend --reset-author\n);
 +
 +static const char implicit_ident_advice_config[] =
  N_(Your name and email address were configured automatically based\n
  on your username and hostname. Please check that they are accurate.\n
  You can suppress this message by setting them explicitly:\n
 @@ -1403,6 +1416,23 @@ int cmd_status(int argc, const char **argv, const char 
 *prefix)
 return 0;
  }

 +static const char *implicit_ident_advice() {
 +   char *user_config = NULL;
 +   char *xdg_config = NULL;
 +   int config_exists;
 +
 +   home_config_paths(user_config, xdg_config, config);
 +   config_exists = file_exists(user_config) || file_exists(xdg_config);
 +   free(user_config);
 +   free(xdg_config);
 +
 +   if (config_exists)
 +   return _(implicit_ident_advice_config);
 +   else
 +   return _(implicit_ident_advice_noconfig);
 +
 +}
 +
  static void print_summary(const char *prefix, const unsigned char *sha1,
   int initial_commit)
  {
 @@ -1441,7 +1471,7 @@ static void print_summary(const char *prefix, const 
 unsigned char *sha1,
 strbuf_addbuf_percentquote(format, committer_ident);
 if (advice_implicit_identity) {
 strbuf_addch(format, '\n');
 -   strbuf_addstr(format, _(implicit_ident_advice));
 +   strbuf_addstr(format, implicit_ident_advice());
 }
 }
 strbuf_release(author_ident);
 --
 2.0.2.737.gfb43bde
--
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/4] refs.c: refactor resolve_ref_unsafe() to use strbuf internally

2014-07-25 Thread Eric Sunshine
On Fri, Jul 25, 2014 at 6:43 AM, Nguyễn Thái Ngọc Duy pclo...@gmail.com wrote:
 In the beginning, we had resolve_ref() that returns a buffer owned by
 this function. Then we started to move away from that direction because
 the buffer could be overwritten by the next resolve_ref() call and
 introduced two new functions: resolve_ref_unsafe() and resolve_refdup().
 The static buffer is still kept internally.

 This patch makes the core of resolve_ref use a strbuf instead of static
 buffer. Which makes resolve_refdup() more efficient (no need to copy
 from the static buffer to a new buffer). It also removes the (random?)
 256 char limit. In future, resolve_ref() could be used directly without
 going through resolve_refdup() wrapper.

 A minor bonus. resolve_ref(dup) are now more thread-friendly (although I'm
 not 100% sure if they are thread-safe yet).

 Signed-off-by: Nguyễn Thái Ngọc Duy pclo...@gmail.com
 ---
  cache.h |   1 +
  refs.c  | 122 
 +++-
  2 files changed, 68 insertions(+), 55 deletions(-)

 diff --git a/cache.h b/cache.h
 index fcb511d..5ffbafb 100644
 --- a/cache.h
 +++ b/cache.h
 +const char *resolve_ref_unsafe(const char *refname, unsigned char *sha1, int 
 reading, int *flag)
 +{
 +   static struct strbuf buf = STRBUF_INIT;
 +   if (!resolve_ref(refname, buf, sha1, reading, flag))
 +   return buf.buf;
 +   else
 +   return NULL;
  }

  char *resolve_refdup(const char *ref, unsigned char *sha1, int reading, int 
 *flag)
  {
 -   const char *ret = resolve_ref_unsafe(ref, sha1, reading, flag);
 -   return ret ? xstrdup(ret) : NULL;
 +   struct strbuf buf = STRBUF_INIT;
 +   if (!resolve_ref(ref, buf, sha1, reading, flag))
 +   return buf.buf;

return strbuf_detach(buf, NULL);

 +   else {
 +   strbuf_release(buf);
 +   return NULL;
 +   }
  }

  /* The argument to filter_refs */
 --
 1.9.1.346.ga2b5940
--
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 1/3] config --global --edit: create a template file if needed

2014-07-25 Thread Matthieu Moy
Eric Sunshine sunsh...@sunshineco.com writes:

 +static char *default_user_config()
 +{
 +   struct strbuf buf = STRBUF_INIT;
 +   strbuf_addf(buf,
 +   _(# This is Git's user-wide configuration file.\n
 + [core]\n
 + # Please, adapt and uncomment the following lines:\n
 + #user = %s\n
 + #email = %s\n),

 [core], user =, email = should not be translated. Would it make
 sense to keep these outside of _()?

I would say no, as the code and the string to translate would be much
less readable without core, user and email inline.

Were you suggesting stg like

_(# This is Git's user-wide configuration file.\n
  [%s]\n
  # Please, adapt and uncomment the following lines:\n
  #%s = %s\n
  #%s = %s\n),
  core, name, ..., email, ...

?

 +   if (fd) {
 +   char *content = default_user_config();
 +   write_str_in_full(fd, content);

 close(fd);

Indeed.

 +   free(content);
 +   }
 +   else if (errno != EEXIST)
 +   die_errno(_(Cannot create configuration 
 file %s), config_file);

 Other error messages in this file (including those just above this
 block) begin with a lowercase letter.

Applied.

Thanks,

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


Re: [PATCH 3/4] refs.c: move ref parsing code out of resolve_ref()

2014-07-25 Thread Ronnie Sahlberg
Nice.

On Fri, Jul 25, 2014 at 3:43 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
 ---
  cache.h |  11 
  refs.c  | 204 
 ++--
  2 files changed, 120 insertions(+), 95 deletions(-)

 diff --git a/cache.h b/cache.h
 index 5ffbafb..40a63d9 100644
 --- a/cache.h
 +++ b/cache.h
 @@ -1003,6 +1003,17 @@ extern int read_ref(const char *refname, unsigned char 
 *sha1);
  extern const char *resolve_ref_unsafe(const char *ref, unsigned char *sha1, 
 int reading, int *flag);
  extern char *resolve_refdup(const char *ref, unsigned char *sha1, int 
 reading, int *flag);
  extern int resolve_ref(const char *refname, struct strbuf *result, unsigned 
 char *sha1, int reading, int *flag);
 +/*
 + * Given a ref in ref and its path, returns
 + *
 + * -2  failed to open with ENOENT, the caller is responsible for
 + * checking missing loose ref (see resolve_ref for example)
 + * -1  if there's an error, ref can no longer be trusted, flag may
 + * be set. errno is valid.
 + *  0  this is a symref, ref now contains the linked ref
 + * +1  normal ref, sha1 is valid
 + */
 +extern int parse_ref(const char *path, struct strbuf *ref, unsigned char 
 *sha1, int *flag);

  extern int dwim_ref(const char *str, int len, unsigned char *sha1, char 
 **ref);
  extern int dwim_log(const char *str, int len, unsigned char *sha1, char 
 **ref);
 diff --git a/refs.c b/refs.c
 index bec2bb1..2769f20 100644
 --- a/refs.c
 +++ b/refs.c
 @@ -1533,6 +1533,105 @@ static int handle_missing_loose_ref(const char 
 *refname,
 }
  }

 +int parse_ref(const char *path, struct strbuf *ref,
 + unsigned char *sha1, int *flag)

Can you make this function static?
It is not used by anything outside of this series and thus making it
static avoids growing the public refs api.


 +{
 +   struct strbuf buffer = STRBUF_INIT;
 +   struct stat st;
 +   const char *buf;
 +
 +   /*
 +* We might have to loop back here to avoid a race condition:
 +* first we lstat() the file, then we try to read it as a link
 +* or as a file.  But if somebody changes the type of the file
 +* (file - directory - symlink) between the lstat() and
 +* reading, then we don't want to report that as an error but
 +* rather try again starting with the lstat().
 +*/
 +stat_ref:
 +   if (lstat(path, st)  0)
 +   return errno == ENOENT ? -2 : -1;
 +
 +   /* Follow normalized - ie refs/.. symlinks by hand */
 +   if (S_ISLNK(st.st_mode)) {
 +   struct strbuf new_path = STRBUF_INIT;
 +   if (strbuf_readlink(new_path, path, 256)  0) {
 +   strbuf_release(new_path);
 +   if (errno == ENOENT || errno == EINVAL)
 +   /* inconsistent with lstat; retry */
 +   goto stat_ref;
 +   else
 +   return -1;
 +   }
 +   if (starts_with(new_path.buf, refs/) 
 +   !check_refname_format(new_path.buf, 0)) {
 +   strbuf_reset(ref);
 +   strbuf_addbuf(ref, new_path);
 +   if (flag)
 +   *flag |= REF_ISSYMREF;
 +   strbuf_release(new_path);
 +   return 0;
 +   }
 +   strbuf_release(new_path);
 +   }
 +
 +   /* Is it a directory? */
 +   if (S_ISDIR(st.st_mode)) {
 +   errno = EISDIR;
 +   return -1;
 +   }
 +
 +   /*
 +* Anything else, just open it and try to use it as
 +* a ref
 +*/
 +   if (strbuf_read_file(buffer, path, 256)  0) {
 +   strbuf_release(buffer);
 +   if (errno == ENOENT)
 +   /* inconsistent with lstat; retry */
 +   goto stat_ref;
 +   else
 +   return -1;
 +   }
 +   strbuf_rtrim(buffer);
 +
 +   /*
 +* Is it a symbolic ref?
 +*/
 +   if (!skip_prefix(buffer.buf, ref:, buf)) {
 +   int ret;
 +   /*
 +* Please note that FETCH_HEAD has a second line
 +* containing other data.
 +*/
 +   if (get_sha1_hex(buffer.buf, sha1) ||
 +   (buffer.buf[40] != '\0'  !isspace(buffer.buf[40]))) {
 +   if (flag)
 +   *flag |= REF_ISBROKEN;
 +   errno = EINVAL;
 +   ret = -1;
 +   } else
 +   ret = 1;
 +   strbuf_release(buffer);
 +   return ret;
 +   }
 +   if (flag)
 +   *flag |= REF_ISSYMREF;
 +   while (isspace(*buf))
 +   buf++;
 +   if 

[PATCH 1/5] refs.c: allow passing raw git_committer_info as email to _update_reflog

2014-07-25 Thread Ronnie Sahlberg
In many places in the code we do not have access to the individual fields
in the committer data. Instead we might only have access to prebaked data
such as what is returned by git_committer_info() containing a string
that consists of email, timestamp, zone etc.

This makes it inconvenient to use transaction_update_reflog since it means
you would have to first parse git_committer_info before you can call
update_reflog.

Add a new flag REFLOG_EMAIL_IS_COMMITTER to _update_reflog to tell it
that what we pass in as email is already the fully baked committer string
we can use as-is.

Signed-off-by: Ronnie Sahlberg sahlb...@google.com
---
 refs.c | 20 
 refs.h |  1 +
 2 files changed, 13 insertions(+), 8 deletions(-)

diff --git a/refs.c b/refs.c
index 2662ef6..6c55032 100644
--- a/refs.c
+++ b/refs.c
@@ -3522,14 +3522,18 @@ int transaction_update_reflog(struct ref_transaction 
*transaction,
hashcpy(update-old_sha1, old_sha1);
update-reflog_fd = -1;
if (email) {
-   struct strbuf buf = STRBUF_INIT;
-   char sign = (tz  0) ? '-' : '+';
-   int zone = (tz  0) ? (-tz) : tz;
-
-   strbuf_addf(buf, %s %lu %c%04d, email, timestamp, sign,
-   zone);
-   update-committer = xstrdup(buf.buf);
-   strbuf_release(buf);
+   if (flags  REFLOG_EMAIL_IS_COMMITTER)
+   update-committer = xstrdup(email);
+   else {
+   struct strbuf buf = STRBUF_INIT;
+   char sign = (tz  0) ? '-' : '+';
+   int zone = (tz  0) ? (-tz) : tz;
+
+   strbuf_addf(buf, %s %lu %c%04d, email, timestamp,
+   sign, zone);
+   update-committer = xstrdup(buf.buf);
+   strbuf_release(buf);
+   }
}
if (msg)
update-msg = xstrdup(msg);
diff --git a/refs.h b/refs.h
index 0172f48..eb918a0 100644
--- a/refs.h
+++ b/refs.h
@@ -309,6 +309,7 @@ int transaction_delete_sha1(struct ref_transaction 
*transaction,
  * Flags = 0x100 are reserved for internal use.
  */
 #define REFLOG_TRUNCATE 0x01
+#define REFLOG_EMAIL_IS_COMMITTER 0x02
 /*
  * Append a reflog entry for refname. If the REFLOG_TRUNCATE flag is set
  * this update will first truncate the reflog before writing the entry.
-- 
2.0.1.508.g763ab16

--
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/5] refs.c: update rename_ref to use a transaction

2014-07-25 Thread Ronnie Sahlberg
Change refs.c to use a single transaction to copy/rename both the refs and
its reflog. Since we are no longer using rename() to move the reflog file
we no longer need to disallow rename_ref for refs with a symlink for its
reflog so we can remove that test from the testsuite.

Change the function to return 1 on failure instead of either -1 or 1.

These changes make the rename_ref operation atomic. This also eliminates the
need to use rename() to shift the reflog around via a temporary filename.
As an extension to this, since we no longer use rename() on the reflog file,
we can now safely perform renames even if the reflog is a symbolic link
and thus can remove the check and fail for that condition.

Signed-off-by: Ronnie Sahlberg sahlb...@google.com
---
 refs.c| 192 ++
 t/t3200-branch.sh |   7 --
 2 files changed, 65 insertions(+), 134 deletions(-)

diff --git a/refs.c b/refs.c
index 0d800f1..a5053bf 100644
--- a/refs.c
+++ b/refs.c
@@ -2616,82 +2616,43 @@ int delete_ref(const char *refname, const unsigned char 
*sha1, int delopt)
return 0;
 }
 
-/*
- * People using contrib's git-new-workdir have .git/logs/refs -
- * /some/other/path/.git/logs/refs, and that may live on another device.
- *
- * IOW, to avoid cross device rename errors, the temporary renamed log must
- * live into logs/refs.
- */
-#define TMP_RENAMED_LOG  logs/refs/.tmp-renamed-log
+struct rename_reflog_cb {
+   struct ref_transaction *transaction;
+   const char *refname;
+   struct strbuf *err;
+};
 
-static int rename_tmp_log(const char *newrefname)
+static int rename_reflog_ent(unsigned char *osha1, unsigned char *nsha1,
+const char *email, unsigned long timestamp, int tz,
+const char *message, void *cb_data)
 {
-   int attempts_remaining = 4;
-
- retry:
-   switch (safe_create_leading_directories(git_path(logs/%s, 
newrefname))) {
-   case SCLD_OK:
-   break; /* success */
-   case SCLD_VANISHED:
-   if (--attempts_remaining  0)
-   goto retry;
-   /* fall through */
-   default:
-   error(unable to create directory for %s, newrefname);
-   return -1;
-   }
+   struct rename_reflog_cb *cb = cb_data;
 
-   if (rename(git_path(TMP_RENAMED_LOG), git_path(logs/%s, newrefname))) 
{
-   if ((errno==EISDIR || errno==ENOTDIR)  --attempts_remaining  
0) {
-   /*
-* rename(a, b) when b is an existing
-* directory ought to result in ISDIR, but
-* Solaris 5.8 gives ENOTDIR.  Sheesh.
-*/
-   if (remove_empty_directories(git_path(logs/%s, 
newrefname))) {
-   error(Directory not empty: logs/%s, 
newrefname);
-   return -1;
-   }
-   goto retry;
-   } else if (errno == ENOENT  --attempts_remaining  0) {
-   /*
-* Maybe another process just deleted one of
-* the directories in the path to newrefname.
-* Try again from the beginning.
-*/
-   goto retry;
-   } else {
-   error(unable to move logfile TMP_RENAMED_LOG to 
logs/%s: %s,
-   newrefname, strerror(errno));
-   return -1;
-   }
-   }
-   return 0;
+   return transaction_update_reflog(cb-transaction, cb-refname,
+nsha1, osha1, email, timestamp, tz,
+message, 0, cb-err);
 }
 
-static int write_ref_sha1(struct ref_lock *lock, const unsigned char *sha1,
- const char *logmsg);
-
 int rename_ref(const char *oldrefname, const char *newrefname, const char 
*logmsg)
 {
-   unsigned char sha1[20], orig_sha1[20];
-   int flag = 0, logmoved = 0;
-   struct ref_lock *lock;
-   struct stat loginfo;
-   int log = !lstat(git_path(logs/%s, oldrefname), loginfo);
+   unsigned char sha1[20];
+   int flag = 0, log;
+   struct ref_transaction *transaction = NULL;
+   struct strbuf err = STRBUF_INIT;
const char *symref = NULL;
+   struct rename_reflog_cb cb;
 
-   if (log  S_ISLNK(loginfo.st_mode))
-   return error(reflog for %s is a symlink, oldrefname);
-
-   symref = resolve_ref_unsafe(oldrefname, orig_sha1,
+   symref = resolve_ref_unsafe(oldrefname, sha1,
RESOLVE_REF_READING, flag);
-   if (flag  REF_ISSYMREF)
-   return error(refname %s is a symbolic ref, renaming it is not 
supported,
+   if (flag  REF_ISSYMREF) {
+   error(refname %s is 

[PATCH 5/5] refs.c: rollback the lockfile before we die() in repack_without_refs

2014-07-25 Thread Ronnie Sahlberg
Signed-off-by: Ronnie Sahlberg sahlb...@google.com
---
 refs.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/refs.c b/refs.c
index a5053bf..619725a 100644
--- a/refs.c
+++ b/refs.c
@@ -2570,8 +2570,10 @@ int repack_without_refs(const char **refnames, int n, 
struct strbuf *err)
/* Remove any other accumulated cruft */
do_for_each_entry_in_dir(packed, 0, curate_packed_ref_fn, 
refs_to_delete);
for_each_string_list_item(ref_to_delete, refs_to_delete) {
-   if (remove_entry(packed, ref_to_delete-string) == -1)
+   if (remove_entry(packed, ref_to_delete-string) == -1) {
+   rollback_packed_refs();
die(internal error);
+   }
}
 
/* Write what remains */
-- 
2.0.1.508.g763ab16

--
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/5] refs.c: return error instead of dying when locking fails during transaction

2014-07-25 Thread Ronnie Sahlberg
Change lock_ref_sha1_basic to return an error instead of dying when
we fail to lock a file during a transaction.

Signed-off-by: Ronnie Sahlberg sahlb...@google.com
---
 refs.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/refs.c b/refs.c
index 6c55032..2ea85a8 100644
--- a/refs.c
+++ b/refs.c
@@ -2214,7 +2214,7 @@ static struct ref_lock *lock_ref_sha1_basic(const char 
*refname,
 */
goto retry;
else
-   unable_to_lock_index_die(ref_file, errno);
+   goto error_return;
}
if (bad_ref)
return lock;
-- 
2.0.1.508.g763ab16

--
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/5] ref-transactions-rename

2014-07-25 Thread Ronnie Sahlberg
This patch series adds support for using transactions and atomic renames.
It focuses on what needs to be done in order to support fully atomic
and rollbackable renames that may or may not involve name conflicts.

By performing the actual delete old/create new via a single operation to
the packed refs file this process will also appear as an atomic change for
any external observers.

(While this series is short it contains a very important change where
we start performing ref changes as operations inside a locked packed refs
file instead of as discreete operations of loose ref files.
This approach will be extended in the next patch series where we will start
using it also to make multi-ref creations/updates become fully
atomic for external observers.)


This series is built on iand depend on the previous reflog series:
  * rs/ref-transaction-reflog (2014-07-23) 15 commits
   - refs.c: allow deleting refs with a broken sha1
   - refs.c: remove lock_any_ref_for_update
   - refs.c: make unlock_ref/close_ref/commit_ref static
   - refs.c: rename log_ref_setup to create_reflog
   - reflog.c: use a reflog transaction when writing during expire
   - refs.c: allow multiple reflog updates during a single transaction
   - refs.c: only write reflog update if msg is non-NULL
   - refs.c: add a flag to allow reflog updates to truncate the log
   - refs.c: add a transaction function to append a reflog entry
   - lockfile.c: make hold_lock_file_for_append preserve meaningful errno
   - refs.c: add a function to append a reflog entry to a fd
   - refs.c: add a new update_type field to ref_update
   - refs.c: rename the transaction functions
   - refs.c: make ref_transaction_delete a wrapper for ref_transaction_update
   - refs.c: make ref_transaction_create a wrapper to ref_transaction_update
   (this branch uses rs/ref-transaction and rs/ref-transaction-1.)


Ronnie Sahlberg (5):
  refs.c: allow passing raw git_committer_info as email to
_update_reflog
  refs.c: return error instead of dying when locking fails during
transaction
  refs.c: use packed refs when deleting refs during a transaction
  refs.c: update rename_ref to use a transaction
  refs.c: rollback the lockfile before we die() in repack_without_refs

 builtin/remote.c  |  13 +-
 refs.c| 369 +-
 refs.h|   1 +
 t/t3200-branch.sh |   7 --
 4 files changed, 210 insertions(+), 180 deletions(-)

-- 
2.0.1.508.g763ab16

--
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/5] refs.c: use packed refs when deleting refs during a transaction

2014-07-25 Thread Ronnie Sahlberg
Make the deletion of refs during a transaction more atomic.
Start by first copying all loose refs we will be deleting to the packed
refs file and then commit the packed refs file. Then re-lock the packed refs
file to stop anyone else from modifying these refs and keep it locked until
we are finished.
Since all refs we are about to delete are now safely held in the packed refs
file we can proceed to immediately unlink any corresponding loose refs
and still be fully rollback-able.

The exception is for refs that can not be resolved. Those refs are never
added to the packed refs and will just be un-rollback-ably deleted during
commit.

By deleting all the loose refs at the start of the transaction we make make
it possible to both delete one ref and then re-create a different ref in
the same transaction even if the two refs would normally conflict.

Example: rename m-m/m

In that example we want to delete the file 'm' so that we make room so
that we can create a directory with the same name in order to lock and
write to the ref m/m and its lock-file m/m.lock.

If there is a failure during the commit phase we can rollback without losing
any refs since we have so far only deleted loose refs that that are
guaranteed to also have a corresponding entry in the packed refs file.
Once we have finished all updates for refs and their reflogs we can repack
the packed refs file and remove the to-be-deleted refs from the packed refs,
at which point all the deleted refs will disappear in one atomic rename
operation.

This also means that for an outside observer, deletion of multiple refs
in a single transaction will look atomic instead of one ref being deleted
at a time.

In order to do all this we need to change the semantics for the
repack_without_refs function so that we can lock the packed refs file,
do other stuff, and later be able to call repack_without_refs with the
lock already taken.
This means we need some additional changes in remote.c to reflect the
changes to the repack_without_refs semantics.

Signed-off-by: Ronnie Sahlberg sahlb...@google.com
---
 builtin/remote.c |  13 +++--
 refs.c   | 151 +++
 2 files changed, 128 insertions(+), 36 deletions(-)

diff --git a/builtin/remote.c b/builtin/remote.c
index be8ebac..9a9cc92 100644
--- a/builtin/remote.c
+++ b/builtin/remote.c
@@ -756,6 +756,8 @@ static int remove_branches(struct string_list *branches)
branch_names = xmalloc(branches-nr * sizeof(*branch_names));
for (i = 0; i  branches-nr; i++)
branch_names[i] = branches-items[i].string;
+   if (lock_packed_refs(0))
+   result |= unable_to_lock_error(git_path(packed-refs), errno);
result |= repack_without_refs(branch_names, branches-nr, NULL);
free(branch_names);
 
@@ -1333,9 +1335,14 @@ static int prune_remote(const char *remote, int dry_run)
delete_refs = xmalloc(states.stale.nr * sizeof(*delete_refs));
for (i = 0; i  states.stale.nr; i++)
delete_refs[i] = states.stale.items[i].util;
-   if (!dry_run)
-   result |= repack_without_refs(delete_refs,
- states.stale.nr, NULL);
+   if (!dry_run) {
+   if (lock_packed_refs(0))
+   result |= unable_to_lock_error(
+   git_path(packed-refs), errno);
+   else
+   result |= repack_without_refs(delete_refs,
+   states.stale.nr, NULL);
+   }
free(delete_refs);
}
 
diff --git a/refs.c b/refs.c
index 2ea85a8..0d800f1 100644
--- a/refs.c
+++ b/refs.c
@@ -1330,7 +1330,7 @@ static struct ref_entry *get_packed_ref(const char 
*refname)
 
 /*
  * A loose ref file doesn't exist; check for a packed ref.  The
- * options are forwarded from resolve_safe_unsafe().
+ * options are forwarded from resolve_ref_unsafe().
  */
 static const char *handle_missing_loose_ref(const char *refname,
unsigned char *sha1,
@@ -1387,7 +1387,6 @@ const char *resolve_ref_unsafe(const char *refname, 
unsigned char *sha1, int fla
}
 
git_snpath(path, sizeof(path), %s, refname);
-
/*
 * We might have to loop back here to avoid a race
 * condition: first we lstat() the file, then we try
@@ -2532,6 +2531,9 @@ static int curate_packed_ref_fn(struct ref_entry *entry, 
void *cb_data)
return 0;
 }
 
+/*
+ * Must be called with packed refs already locked (and sorted)
+ */
 int repack_without_refs(const char **refnames, int n, struct strbuf *err)
 {
struct ref_dir *packed;
@@ -2544,19 +2546,12 @@ int repack_without_refs(const char **refnames, int n, 
struct strbuf *err)
if 

Re: [PATCH 5/7] enforce `xfuncname` precedence over `funcname`

2014-07-25 Thread Junio C Hamano
Matthieu Moy matthieu@grenoble-inp.fr writes:

 Tanay Abhra tanay...@gmail.com writes:

 On 7/25/2014 2:52 AM, Ramsay Jones wrote:
 However, I think it you could create a list of pointer to hash-table
 entry, string-list index pairs in the config_set and use that to do
 the iteration. A bit ugly, but it should work.

 Thanks for the advice, that is exactly what I am doing.

 I'd just replace list with array and use
 Documentation/technical/api-allocation-growing.txt.

 But I can't think of a better way.

Presumably this array will reflect the order the source file told us
about the keys and their values; I wonder if the filename, lineno
information we already have can be used (or unified) with it?

Is the when the last variable in a section disappears, make the
section header go away, with sensible handling of comments around
it part of this GSoC project?  If so, I suspect that the feature
would also want to know where things appear in the original file, so
this data structure may play a role there, 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 v2 5/6] config: add `git_die_config()` to the config-set API

2014-07-25 Thread Junio C Hamano
Tanay Abhra tanay...@gmail.com writes:

 On 7/25/2014 7:33 PM, Matthieu Moy wrote:
 Tanay Abhra tanay...@gmail.com writes:
 
 --- a/config.c
 +++ b/config.c
 @@ -1403,11 +1403,12 @@ const struct string_list 
 *git_configset_get_value_multi(struct config_set *cs, c
  
  int git_configset_get_string_const(struct config_set *cs, const char *key, 
 const char **dest)
  {
 -   const char *value;
 -   if (!git_configset_get_value(cs, key, value))
 -   return git_config_string(dest, key, value);
 -   else
 -   return 1;
 +   int ret;
 +   char *value;
 +   ret = git_configset_get_string(cs, key, value);
 +   if (ret = 0)
 +   *dest = (const char*)value;
 +   return ret;
  }
 
 Isn't this a fixup meant for another series?


 Though v12 is in pu, Junio commented that git_configset_get_string_const() 
 git_configset_get_string() can be done more concisely, I was trying to do
 that but I failed.

My comment on that version was not about conciseness.  You had one
that called git_config_string() to let the callee do the nonbool
error handling and xstrdup() of the non-error return value, and the
other one that did exactly what a call to git_config_string() would
have done.  That is being redundant, not just failing to be concise.

I was actually hoping that we would see just

int git_configset_get_string(struct config_set *cs, const char *key, char 
**dest)
{
return git_configset_get_string_const(cs, key, (const char **)dest);
}

with the implementation of _const() variant be the one from v12.

--
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 1/3] config --global --edit: create a template file if needed

2014-07-25 Thread Junio C Hamano
Matthieu Moy matthieu@imag.fr writes:

 When the user has no ~/.gitconfig file, git config --global --edit used
 to launch an editor on an nonexistant file name.

 Instead, create a file with a default content before launching the
 editor. The template contains only commented-out entries, to save a few
 keystrokes for the user. If the values are guessed properly, the user
 will only have to uncomment the entries.

 Advanced users teaching newbies can create a minimalistic configuration
 faster for newbies. Beginners reading a tutorial advising to run git
 config --global --edit as a first step will be slightly more guided for
 their first contact with Git.

 Signed-off-by: Matthieu Moy matthieu@imag.fr
 ---

Probably a good idea; I do not think of any possible interactions we
have to worry about with the configuration file init-db creates with
possible templating.

Do we use user-wide as a phrase to refer to these?  It sounds
somewhat funny to call anything specific to $frotz $frotz-wide, at
least to me.

Surely, /etc/gitconfig is called site-wide.  But .git/config is
per-project (or project-specific), and I would always have thought
that ~/.gitconfig was per-user.

  builtin/config.c | 30 +++---
  cache.h  |  1 +
  ident.c  |  2 +-
  3 files changed, 29 insertions(+), 4 deletions(-)

 diff --git a/builtin/config.c b/builtin/config.c
 index fcd8474..3821697 100644
 --- a/builtin/config.c
 +++ b/builtin/config.c
 @@ -445,6 +445,20 @@ static int get_urlmatch(const char *var, const char *url)
   return 0;
  }
  
 +static char *default_user_config()

static char *default_user_config(void)

 +{
 + struct strbuf buf = STRBUF_INIT;
 + strbuf_addf(buf,
 + _(# This is Git's user-wide configuration file.\n
 +   [core]\n
 +   # Please, adapt and uncomment the following lines:\n

tangent: is it a French tradition to always have comma after please?
--
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/7] enforce `xfuncname` precedence over `funcname`

2014-07-25 Thread Matthieu Moy
Junio C Hamano gits...@pobox.com writes:

 Matthieu Moy matthieu@grenoble-inp.fr writes:

 Tanay Abhra tanay...@gmail.com writes:

 On 7/25/2014 2:52 AM, Ramsay Jones wrote:
 However, I think it you could create a list of pointer to hash-table
 entry, string-list index pairs in the config_set and use that to do
 the iteration. A bit ugly, but it should work.

 Thanks for the advice, that is exactly what I am doing.

 I'd just replace list with array and use
 Documentation/technical/api-allocation-growing.txt.

 But I can't think of a better way.

 Presumably this array will reflect the order the source file told us
 about the keys and their values; I wonder if the filename, lineno
 information we already have can be used (or unified) with it?

I've thought about this too, and I think it would be really hard.

First, there are several files in the picture (eg. /etc/gitconfig,
~/.gitconfig and .git/config), and even included files hence it's not
even a lexical order (file, line).

Then, even if we had a way to order elements with (file, line),
iterating over the hashtable in this order wouldn't be easy (the naive
way, get the smallest, get the second smallest, ... would be O(n^2)).

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


Re: [RFC PATCH 1/3] config --global --edit: create a template file if needed

2014-07-25 Thread Eric Sunshine
On Fri, Jul 25, 2014 at 12:01 PM, Matthieu Moy
matthieu@grenoble-inp.fr wrote:
 Eric Sunshine sunsh...@sunshineco.com writes:

 +static char *default_user_config()
 +{
 +   struct strbuf buf = STRBUF_INIT;
 +   strbuf_addf(buf,
 +   _(# This is Git's user-wide configuration file.\n
 + [core]\n
 + # Please, adapt and uncomment the following lines:\n
 + #user = %s\n
 + #email = %s\n),

 [core], user =, email = should not be translated. Would it make
 sense to keep these outside of _()?

 I would say no, as the code and the string to translate would be much
 less readable without core, user and email inline.

 Were you suggesting stg like

 _(# This is Git's user-wide configuration file.\n
   [%s]\n
   # Please, adapt and uncomment the following lines:\n
   #%s = %s\n
   #%s = %s\n),
   core, name, ..., email, ...

 ?

That or some equivalent variation. I'm not a translator, but the above
seems to convey sufficient context for a translator to understand what
needs to be said, while preventing accidental translations of those
strings which should not be translated.

 +   if (fd) {
 +   char *content = default_user_config();
 +   write_str_in_full(fd, content);

 close(fd);

 Indeed.

 +   free(content);
 +   }
 +   else if (errno != EEXIST)
 +   die_errno(_(Cannot create configuration 
 file %s), config_file);

 Other error messages in this file (including those just above this
 block) begin with a lowercase letter.

 Applied.

 Thanks,

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


Re: [RFC PATCH 1/3] config --global --edit: create a template file if needed

2014-07-25 Thread Matthieu Moy
Junio C Hamano gits...@pobox.com writes:

 Probably a good idea; I do not think of any possible interactions we
 have to worry about with the configuration file init-db creates with
 possible templating.

The feature should trigger only for --global, so it shouldn't interfer
with .git/config and templates.

 Do we use user-wide as a phrase to refer to these?  It sounds
 somewhat funny to call anything specific to $frotz $frotz-wide, at
 least to me.

 Surely, /etc/gitconfig is called site-wide.  But .git/config is
 per-project (or project-specific), and I would always have thought
 that ~/.gitconfig was per-user.

I'm not a native speaker, but to me, user-wide insists on the fact
that it applies to everything for this user, and per-user insists on
the fact that it does not apply to other users.

Perhaps just Git's user configuration file would be enough.

  builtin/config.c | 30 +++---
  cache.h  |  1 +
  ident.c  |  2 +-
  3 files changed, 29 insertions(+), 4 deletions(-)

 diff --git a/builtin/config.c b/builtin/config.c
 index fcd8474..3821697 100644
 --- a/builtin/config.c
 +++ b/builtin/config.c
 @@ -445,6 +445,20 @@ static int get_urlmatch(const char *var, const char 
 *url)
  return 0;
  }
  
 +static char *default_user_config()

 static char *default_user_config(void)

Right. Doing too much C++.

 +{
 +struct strbuf buf = STRBUF_INIT;
 +strbuf_addf(buf,
 +_(# This is Git's user-wide configuration file.\n
 +  [core]\n
 +  # Please, adapt and uncomment the following lines:\n

 tangent: is it a French tradition to always have comma after please?

Perhaps. In French, the comma would be required after S'il vous plait
(litterally, if you like). I'll remove it.

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


[PATCH 4/5] refs.c: make repack_without_refs static

2014-07-25 Thread Ronnie Sahlberg
Signed-off-by: Ronnie Sahlberg sahlb...@google.com
---
 refs.c | 2 +-
 refs.h | 3 ---
 2 files changed, 1 insertion(+), 4 deletions(-)

diff --git a/refs.c b/refs.c
index efa4f0d..5696d18 100644
--- a/refs.c
+++ b/refs.c
@@ -2534,7 +2534,7 @@ static int curate_packed_ref_fn(struct ref_entry *entry, 
void *cb_data)
 /*
  * Must be called with packed refs already locked (and sorted)
  */
-int repack_without_refs(const char **refnames, int n, struct strbuf *err)
+static int repack_without_refs(const char **refnames, int n, struct strbuf 
*err)
 {
struct ref_dir *packed;
struct string_list refs_to_delete = STRING_LIST_INIT_DUP;
diff --git a/refs.h b/refs.h
index eb918a0..7183e8e 100644
--- a/refs.h
+++ b/refs.h
@@ -155,9 +155,6 @@ extern void rollback_packed_refs(void);
  */
 int pack_refs(unsigned int flags);
 
-extern int repack_without_refs(const char **refnames, int n,
-  struct strbuf *err);
-
 extern int ref_exists(const char *);
 
 /*
-- 
2.0.1.518.g4f5a8ad

--
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/5] refs.c: move reflog updates into its own function

2014-07-25 Thread Ronnie Sahlberg
write_ref_sha1 tries to update the reflog while updating the ref.
Move these reflog changes out into its own function so that we can do the
same thing if we write a sha1 ref differently, for example by writing a ref
to the packed refs file instead.

Signed-off-by: Ronnie Sahlberg sahlb...@google.com
---
 refs.c | 62 --
 1 file changed, 36 insertions(+), 26 deletions(-)

diff --git a/refs.c b/refs.c
index 619725a..1048017 100644
--- a/refs.c
+++ b/refs.c
@@ -2869,6 +2869,39 @@ static int is_branch(const char *refname)
return !strcmp(refname, HEAD) || starts_with(refname, refs/heads/);
 }
 
+static int write_sha1_update_reflog(struct ref_lock *lock,
+   const unsigned char *sha1, const char *logmsg)
+{
+   if (log_ref_write(lock-ref_name, lock-old_sha1, sha1, logmsg)  0 ||
+   (strcmp(lock-ref_name, lock-orig_ref_name) 
+log_ref_write(lock-orig_ref_name, lock-old_sha1, sha1, logmsg)  
0)) {
+   return -1;
+   }
+   if (strcmp(lock-orig_ref_name, HEAD) != 0) {
+   /*
+* Special hack: If a branch is updated directly and HEAD
+* points to it (may happen on the remote side of a push
+* for example) then logically the HEAD reflog should be
+* updated too.
+* A generic solution implies reverse symref information,
+* but finding all symrefs pointing to the given branch
+* would be rather costly for this rare event (the direct
+* update of a branch) to be worth it.  So let's cheat and
+* check with HEAD only which should cover 99% of all usage
+* scenarios (even 100% of the default ones).
+*/
+   unsigned char head_sha1[20];
+   int head_flag;
+   const char *head_ref;
+   head_ref = resolve_ref_unsafe(HEAD, head_sha1,
+ RESOLVE_REF_READING, head_flag);
+   if (head_ref  (head_flag  REF_ISSYMREF) 
+   !strcmp(head_ref, lock-ref_name))
+   log_ref_write(HEAD, lock-old_sha1, sha1, logmsg);
+   }
+   return 0;
+}
+
 /*
  * Writes sha1 into the ref specified by the lock. Makes sure that errno
  * is sane on error.
@@ -2912,34 +2945,10 @@ static int write_ref_sha1(struct ref_lock *lock,
return -1;
}
clear_loose_ref_cache(ref_cache);
-   if (log_ref_write(lock-ref_name, lock-old_sha1, sha1, logmsg)  0 ||
-   (strcmp(lock-ref_name, lock-orig_ref_name) 
-log_ref_write(lock-orig_ref_name, lock-old_sha1, sha1, logmsg)  
0)) {
+   if (write_sha1_update_reflog(lock, sha1, logmsg)) {
unlock_ref(lock);
return -1;
}
-   if (strcmp(lock-orig_ref_name, HEAD) != 0) {
-   /*
-* Special hack: If a branch is updated directly and HEAD
-* points to it (may happen on the remote side of a push
-* for example) then logically the HEAD reflog should be
-* updated too.
-* A generic solution implies reverse symref information,
-* but finding all symrefs pointing to the given branch
-* would be rather costly for this rare event (the direct
-* update of a branch) to be worth it.  So let's cheat and
-* check with HEAD only which should cover 99% of all usage
-* scenarios (even 100% of the default ones).
-*/
-   unsigned char head_sha1[20];
-   int head_flag;
-   const char *head_ref;
-   head_ref = resolve_ref_unsafe(HEAD, head_sha1,
- RESOLVE_REF_READING, head_flag);
-   if (head_ref  (head_flag  REF_ISSYMREF) 
-   !strcmp(head_ref, lock-ref_name))
-   log_ref_write(HEAD, lock-old_sha1, sha1, logmsg);
-   }
if (commit_ref(lock)) {
error(Couldn't set %s, lock-ref_name);
unlock_ref(lock);
@@ -3649,7 +3658,8 @@ int transaction_commit(struct ref_transaction 
*transaction,
continue;
if (get_packed_ref(update-refname))
continue;
-   if (!resolve_ref_unsafe(update-refname, sha1, 1, NULL))
+   if (!resolve_ref_unsafe(update-refname, sha1,
+   RESOLVE_REF_READING, NULL))
continue;
 
add_packed_ref(update-refname, sha1);
-- 
2.0.1.518.g4f5a8ad

--
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/5] refs.c: write updates to packed refs when a transaction has more than one ref

2014-07-25 Thread Ronnie Sahlberg
When we are updating more than one single ref, i.e. not a commit, then
write the updated refs directly to the packed refs file instead of writing
them as loose refs.

Change clone to use a transaction instead of using the packed refs API.
This changes the behavior of clone slightly. Previously clone would always
clone all refs into a packed refs file. With this change clone will only
clone into packed refs iff there are two or more refs being cloned.
If the repository we are cloning from only contains exactly one single ref
then clone will now store this as a loose ref. The benefit here is that
we no longer need to export a bunch of API functions to clone to access
packed refs directly. Clone can now just use a normal transaction and all
the packed refs goodness will happen automatically.

Update the t5516 test to cope with the fact that clone now only uses
packed refs if there are more than one ref being cloned.

We still use loose refs for single ref transactions, such as are used
by 'git commit' and friends. The reason for this is that if you have very
many refs then having to re-write the whole packed refs file for every
common operation like commit would have a performance impact.
That said, with these changes it should now be fairly straightforward to
add support to optionally start using packed refs for ALL updates
which could solve existing issues with name clashes in case insensitive
filesystems.

This change also means that multi-ref updates will now appear as a single
atomic change to any external observers instead of a sequence of discreete
changes.

Signed-off-by: Ronnie Sahlberg sahlb...@google.com
---
 builtin/clone.c   | 16 +++---
 refs.c| 83 +--
 t/t5516-fetch-push.sh |  2 +-
 3 files changed, 74 insertions(+), 27 deletions(-)

diff --git a/builtin/clone.c b/builtin/clone.c
index f7307e6..7737e12 100644
--- a/builtin/clone.c
+++ b/builtin/clone.c
@@ -497,17 +497,25 @@ static struct ref *wanted_peer_refs(const struct ref 
*refs,
 static void write_remote_refs(const struct ref *local_refs)
 {
const struct ref *r;
+   struct ref_transaction *transaction;
+   struct strbuf err = STRBUF_INIT;
 
-   lock_packed_refs(LOCK_DIE_ON_ERROR);
+   transaction = transaction_begin(err);
+   if (!transaction)
+   die(%s, err.buf);
 
for (r = local_refs; r; r = r-next) {
if (!r-peer_ref)
continue;
-   add_packed_ref(r-peer_ref-name, r-old_sha1);
+   if (transaction_update_sha1(transaction, r-peer_ref-name,
+   r-old_sha1, NULL, 0, 0, NULL,
+   err))
+   die(%s, err.buf);
}
 
-   if (commit_packed_refs())
-   die_errno(unable to overwrite old ref-pack file);
+   if (transaction_commit(transaction, err))
+   die(%s, err.buf);
+   transaction_free(transaction);
 }
 
 static void write_followtags(const struct ref *refs, const char *msg)
diff --git a/refs.c b/refs.c
index 1048017..efa4f0d 100644
--- a/refs.c
+++ b/refs.c
@@ -2539,33 +2539,18 @@ int repack_without_refs(const char **refnames, int n, 
struct strbuf *err)
struct ref_dir *packed;
struct string_list refs_to_delete = STRING_LIST_INIT_DUP;
struct string_list_item *ref_to_delete;
-   int i, ret, removed = 0;
+   int i, ret;
 
/* Look for a packed ref */
for (i = 0; i  n; i++)
if (get_packed_ref(refnames[i]))
break;
 
-   /* Avoid processing if we have nothing to do */
-   if (i == n) {
-   rollback_packed_refs();
-   return 0; /* no refname exists in packed refs */
-   }
-
packed = get_packed_refs(ref_cache);
 
/* Remove refnames from the cache */
for (i = 0; i  n; i++)
-   if (remove_entry(packed, refnames[i]) != -1)
-   removed = 1;
-   if (!removed) {
-   /*
-* All packed entries disappeared while we were
-* acquiring the lock.
-*/
-   rollback_packed_refs();
-   return 0;
-   }
+   remove_entry(packed, refnames[i]);
 
/* Remove any other accumulated cruft */
do_for_each_entry_in_dir(packed, 0, curate_packed_ref_fn, 
refs_to_delete);
@@ -3614,6 +3599,7 @@ int transaction_commit(struct ref_transaction 
*transaction,
   struct strbuf *err)
 {
int ret = 0, delnum = 0, i, df_conflict = 0, need_repack = 0;
+   int num_updates = 0;
const char **delnames;
int n = transaction-nr;
struct packed_ref_cache *packed_ref_cache;
@@ -3647,19 +3633,38 @@ int transaction_commit(struct ref_transaction 
*transaction,
goto cleanup;
}
 
-   /* any loose refs are to be 

[PATCH 0/5] use packed refs for ref-transactions

2014-07-25 Thread Ronnie Sahlberg
This is a small patch series that continues ontop of the 
ref-transactions-rename series I posted earlier today.

This series expands the use of the packed refs file to make multi-ref
updates much more atomic. Additionally it allows us to continue pushing
external caller to use transactions instead of accessing (packed) refs
directly which allows us to remove a whole bunch of refs functions
from the public api.

After this series there is no real need any more to expose that packed
refs even exist to external callers.


This series is built ontop of the previous series that was posted earlier
today as :
  [PATCH 0/5] ref-transactions-rename


Ronnie Sahlberg (5):
  refs.c: move reflog updates into its own function
  refs.c: write updates to packed refs when a transaction has more than
one ref
  remote.c: use a transaction for deleting refs
  refs.c: make repack_without_refs static
  refs.c: make the *_packed_refs functions static

 builtin/clone.c   |  16 --
 builtin/remote.c  |  70 +--
 refs.c| 153 +-
 refs.h|  33 ---
 t/t5516-fetch-push.sh |   2 +-
 5 files changed, 153 insertions(+), 121 deletions(-)

-- 
2.0.1.518.g4f5a8ad

--
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/5] remote.c: use a transaction for deleting refs

2014-07-25 Thread Ronnie Sahlberg
Transactions now use packed refs when deleting multiple refs so there is no
need to do it manually from remote.c any more.

Signed-off-by: Ronnie Sahlberg sahlb...@google.com
---
 builtin/remote.c | 70 +++-
 1 file changed, 39 insertions(+), 31 deletions(-)

diff --git a/builtin/remote.c b/builtin/remote.c
index 9a9cc92..3e6ef08 100644
--- a/builtin/remote.c
+++ b/builtin/remote.c
@@ -750,25 +750,27 @@ static int mv(int argc, const char **argv)
 
 static int remove_branches(struct string_list *branches)
 {
-   const char **branch_names;
int i, result = 0;
+   struct ref_transaction *transaction;
+   struct strbuf err = STRBUF_INIT;
+
+   transaction = transaction_begin(err);
+   if (!transaction)
+   die(%s, err.buf);
 
-   branch_names = xmalloc(branches-nr * sizeof(*branch_names));
for (i = 0; i  branches-nr; i++)
-   branch_names[i] = branches-items[i].string;
-   if (lock_packed_refs(0))
-   result |= unable_to_lock_error(git_path(packed-refs), errno);
-   result |= repack_without_refs(branch_names, branches-nr, NULL);
-   free(branch_names);
-
-   for (i = 0; i  branches-nr; i++) {
-   struct string_list_item *item = branches-items + i;
-   const char *refname = item-string;
-
-   if (delete_ref(refname, NULL, 0))
-   result |= error(_(Could not remove branch %s), 
refname);
-   }
+   if (transaction_delete_sha1(transaction,
+   branches-items[i].string, NULL,
+   0, 0, remote-branches, err)) {
+   result |= error(%s, err.buf);
+   goto cleanup;
+   }
+   if (transaction_commit(transaction, err))
+   result |= error(%s, err.buf);
 
+ cleanup:
+   strbuf_release(err);
+   transaction_free(transaction);
return result;
 }
 
@@ -1317,10 +1319,11 @@ static int prune_remote(const char *remote, int dry_run)
int result = 0, i;
struct ref_states states;
struct string_list delete_refs_list = STRING_LIST_INIT_NODUP;
-   const char **delete_refs;
const char *dangling_msg = dry_run
? _( %s will become dangling!)
: _( %s has become dangling!);
+   struct ref_transaction *transaction = NULL;
+   struct strbuf err = STRBUF_INIT;
 
memset(states, 0, sizeof(states));
get_remote_ref_states(remote, states, GET_REF_STATES);
@@ -1331,28 +1334,26 @@ static int prune_remote(const char *remote, int dry_run)
   states.remote-url_nr
   ? states.remote-url[0]
   : _((no URL)));
-
-   delete_refs = xmalloc(states.stale.nr * sizeof(*delete_refs));
-   for (i = 0; i  states.stale.nr; i++)
-   delete_refs[i] = states.stale.items[i].util;
-   if (!dry_run) {
-   if (lock_packed_refs(0))
-   result |= unable_to_lock_error(
-   git_path(packed-refs), errno);
-   else
-   result |= repack_without_refs(delete_refs,
-   states.stale.nr, NULL);
-   }
-   free(delete_refs);
}
 
+   if (!dry_run) {
+   transaction = transaction_begin(err);
+   if (!transaction)
+   die(%s, err.buf);
+   }
for (i = 0; i  states.stale.nr; i++) {
const char *refname = states.stale.items[i].util;
 
string_list_insert(delete_refs_list, refname);
 
-   if (!dry_run)
-   result |= delete_ref(refname, NULL, 0);
+   if (!dry_run) {
+   if (transaction_delete_sha1(transaction,
+   refname, NULL,
+   0, 0, remote-branches, err)) {
+   result |= error(%s, err.buf);
+   goto cleanup;
+   }
+   }
 
if (dry_run)
printf_ln(_( * [would prune] %s),
@@ -1362,6 +1363,13 @@ static int prune_remote(const char *remote, int dry_run)
   abbrev_ref(refname, refs/remotes/));
}
 
+   if (!dry_run)
+   if (transaction_commit(transaction, err))
+   result |= error(%s, err.buf);
+
+ cleanup:
+   strbuf_release(err);
+   transaction_free(transaction);
warn_dangling_symrefs(stdout, dangling_msg, delete_refs_list);
string_list_clear(delete_refs_list, 0);
 
-- 
2.0.1.518.g4f5a8ad

--
To unsubscribe from this list: send the line unsubscribe git in
the 

[PATCH 5/5] refs.c: make the *_packed_refs functions static

2014-07-25 Thread Ronnie Sahlberg
We no longer need to expose the lock/add/commit/rollback functions
for packed refs anymore so make them static and remove them from the
public api.

Signed-off-by: Ronnie Sahlberg sahlb...@google.com
---
 refs.c |  8 
 refs.h | 30 --
 2 files changed, 4 insertions(+), 34 deletions(-)

diff --git a/refs.c b/refs.c
index 5696d18..d2ee8a2 100644
--- a/refs.c
+++ b/refs.c
@@ -1135,7 +1135,7 @@ static struct ref_dir *get_packed_refs(struct ref_cache 
*refs)
return get_packed_ref_dir(get_packed_ref_cache(refs));
 }
 
-void add_packed_ref(const char *refname, const unsigned char *sha1)
+static void add_packed_ref(const char *refname, const unsigned char *sha1)
 {
struct packed_ref_cache *packed_ref_cache =
get_packed_ref_cache(ref_cache);
@@ -2268,7 +2268,7 @@ static int write_packed_entry_fn(struct ref_entry *entry, 
void *cb_data)
 }
 
 /* This should return a meaningful errno on failure */
-int lock_packed_refs(int flags)
+static int lock_packed_refs(int flags)
 {
struct packed_ref_cache *packed_ref_cache;
 
@@ -2291,7 +2291,7 @@ int lock_packed_refs(int flags)
  * Commit the packed refs changes.
  * On error we must make sure that errno contains a meaningful value.
  */
-int commit_packed_refs(void)
+static int commit_packed_refs(void)
 {
struct packed_ref_cache *packed_ref_cache =
get_packed_ref_cache(ref_cache);
@@ -2316,7 +2316,7 @@ int commit_packed_refs(void)
return error;
 }
 
-void rollback_packed_refs(void)
+static void rollback_packed_refs(void)
 {
struct packed_ref_cache *packed_ref_cache =
get_packed_ref_cache(ref_cache);
diff --git a/refs.h b/refs.h
index 7183e8e..ec52e13 100644
--- a/refs.h
+++ b/refs.h
@@ -112,36 +112,6 @@ extern void warn_dangling_symref(FILE *fp, const char 
*msg_fmt, const char *refn
 extern void warn_dangling_symrefs(FILE *fp, const char *msg_fmt, const struct 
string_list* refnames);
 
 /*
- * Lock the packed-refs file for writing.  Flags is passed to
- * hold_lock_file_for_update().  Return 0 on success.
- * Errno is set to something meaningful on error.
- */
-extern int lock_packed_refs(int flags);
-
-/*
- * Add a reference to the in-memory packed reference cache.  This may
- * only be called while the packed-refs file is locked (see
- * lock_packed_refs()).  To actually write the packed-refs file, call
- * commit_packed_refs().
- */
-extern void add_packed_ref(const char *refname, const unsigned char *sha1);
-
-/*
- * Write the current version of the packed refs cache from memory to
- * disk.  The packed-refs file must already be locked for writing (see
- * lock_packed_refs()).  Return zero on success.
- * Sets errno to something meaningful on error.
- */
-extern int commit_packed_refs(void);
-
-/*
- * Rollback the lockfile for the packed-refs file, and discard the
- * in-memory packed reference cache.  (The packed-refs file will be
- * read anew if it is needed again after this function is called.)
- */
-extern void rollback_packed_refs(void);
-
-/*
  * Flags for controlling behaviour of pack_refs()
  * PACK_REFS_PRUNE: Prune loose refs after packing
  * PACK_REFS_ALL:   Pack _all_ refs, not just tags and already packed refs
-- 
2.0.1.518.g4f5a8ad

--
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 1/3] config --global --edit: create a template file if needed

2014-07-25 Thread Junio C Hamano
Matthieu Moy matthieu@grenoble-inp.fr writes:

 Eric Sunshine sunsh...@sunshineco.com writes:

 +static char *default_user_config()
 +{
 +   struct strbuf buf = STRBUF_INIT;
 +   strbuf_addf(buf,
 +   _(# This is Git's user-wide configuration file.\n
 + [core]\n
 + # Please, adapt and uncomment the following lines:\n
 + #user = %s\n
 + #email = %s\n),

 [core], user =, email = should not be translated. Would it make
 sense to keep these outside of _()?

 I would say no, as the code and the string to translate would be much
 less readable without core, user and email inline.

 Were you suggesting stg like

 _(# This is Git's user-wide configuration file.\n
   [%s]\n
   # Please, adapt and uncomment the following lines:\n
   #%s = %s\n
   #%s = %s\n),
   core, name, ..., email, ...

 ?

;-) That is a clever way to say what my first reaction to Eric's
comment was, which was to have this as multiple strbuf_addf().

Technically speaking, the '#' at the beginning of lines must not be
translated, either, and if that goes without saying, i.e. if the
translators know well enough not to change them, then I can be
persuaded that we can expect that translators know well enough not
to touch the three substrings Eric pointed out.

So, the original message may be fine as-is.

 +   if (fd) {
 +   char *content = default_user_config();
 +   write_str_in_full(fd, content);

 close(fd);

 Indeed.

 +   free(content);
 +   }
 +   else if (errno != EEXIST)
 +   die_errno(_(Cannot create configuration 
 file %s), config_file);

 Other error messages in this file (including those just above this
 block) begin with a lowercase letter.

 Applied.

 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


[PATCH v2 2/3] home_config_path: allow NULL xdg parameter

2014-07-25 Thread Matthieu Moy
This allows a caller to request the global config file without requesting
the XDG one.

Signed-off-by: Matthieu Moy matthieu@imag.fr
---
 path.c | 10 ++
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/path.c b/path.c
index 3afcdb4..f68df0c 100644
--- a/path.c
+++ b/path.c
@@ -148,10 +148,12 @@ void home_config_paths(char **global, char **xdg, char 
*file)
*global = mkpathdup(%s/.gitconfig, home);
}
 
-   if (!xdg_home)
-   *xdg = NULL;
-   else
-   *xdg = mkpathdup(%s/git/%s, xdg_home, file);
+   if (xdg) {
+   if (!xdg_home)
+   *xdg = NULL;
+   else
+   *xdg = mkpathdup(%s/git/%s, xdg_home, file);
+   }
 
free(to_free);
 }
-- 
2.0.2.737.gfb43bde

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


[PATCH v2 1/3] config --global --edit: create a template file if needed

2014-07-25 Thread Matthieu Moy
When the user has no ~/.gitconfig file, git config --global --edit used
to launch an editor on an nonexistant file name.

Instead, create a file with a default content before launching the
editor. The template contains only commented-out entries, to save a few
keystrokes for the user. If the values are guessed properly, the user
will only have to uncomment the entries.

Advanced users teaching newbies can create a minimalistic configuration
faster for newbies. Beginners reading a tutorial advising to run git
config --global --edit as a first step will be slightly more guided for
their first contact with Git.

Signed-off-by: Matthieu Moy matthieu@imag.fr
---
Hopefully, all remarks applied. I went for Git's user configuration, but
I can change it to whatever native speakers think is better.

 builtin/config.c | 31 ---
 cache.h  |  1 +
 ident.c  |  2 +-
 3 files changed, 30 insertions(+), 4 deletions(-)

diff --git a/builtin/config.c b/builtin/config.c
index fcd8474..1363478 100644
--- a/builtin/config.c
+++ b/builtin/config.c
@@ -445,6 +445,20 @@ static int get_urlmatch(const char *var, const char *url)
return 0;
 }
 
+static char *default_user_config(void)
+{
+   struct strbuf buf = STRBUF_INIT;
+   strbuf_addf(buf,
+   _(# This is Git's user configuration file.\n
+ [core]\n
+ # Please adapt and uncomment the following lines:\n
+ #user = %s\n
+ #email = %s\n),
+   ident_default_name(),
+   ident_default_email());
+   return strbuf_detach(buf, NULL);
+}
+
 int cmd_config(int argc, const char **argv, const char *prefix)
 {
int nongit = !startup_info-have_repository;
@@ -551,6 +565,8 @@ int cmd_config(int argc, const char **argv, const char 
*prefix)
}
}
else if (actions == ACTION_EDIT) {
+   const char *config_file = given_config_source.file ?
+   given_config_source.file : git_path(config);
check_argc(argc, 0, 0);
if (!given_config_source.file  nongit)
die(not in a git directory);
@@ -559,9 +575,18 @@ int cmd_config(int argc, const char **argv, const char 
*prefix)
if (given_config_source.blob)
die(editing blobs is not supported);
git_config(git_default_config, NULL);
-   launch_editor(given_config_source.file ?
- given_config_source.file : git_path(config),
- NULL, NULL);
+   if (use_global_config) {
+   int fd = open(config_file, O_CREAT | O_EXCL | O_WRONLY, 
0666);
+   if (fd) {
+   char *content = default_user_config();
+   write_str_in_full(fd, content);
+   free(content);
+   close(fd);
+   }
+   else if (errno != EEXIST)
+   die_errno(_(cannot create configuration file 
%s), config_file);
+   }
+   launch_editor(config_file, NULL, NULL);
}
else if (actions == ACTION_SET) {
int ret;
diff --git a/cache.h b/cache.h
index fcb511d..b06cbb2 100644
--- a/cache.h
+++ b/cache.h
@@ -1061,6 +1061,7 @@ extern const char *git_author_info(int);
 extern const char *git_committer_info(int);
 extern const char *fmt_ident(const char *name, const char *email, const char 
*date_str, int);
 extern const char *fmt_name(const char *name, const char *email);
+extern const char *ident_default_name(void);
 extern const char *ident_default_email(void);
 extern const char *git_editor(void);
 extern const char *git_pager(int stdout_is_tty);
diff --git a/ident.c b/ident.c
index 1d9b6e7..77bc882 100644
--- a/ident.c
+++ b/ident.c
@@ -102,7 +102,7 @@ static void copy_email(const struct passwd *pw, struct 
strbuf *email)
add_domainname(email);
 }
 
-static const char *ident_default_name(void)
+const char *ident_default_name(void)
 {
if (!git_default_name.len) {
copy_gecos(xgetpwuid_self(), git_default_name);
-- 
2.0.2.737.gfb43bde

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


[PATCH v2 3/3] commit: advertise config --global --edit on guessed identity

2014-07-25 Thread Matthieu Moy
When the user has no user-wide configuration file, it's faster to use the
newly introduced config file template than to run two commands to set
user.name and user.email. Advise this to the user.

The old advice is kept if the user already has a configuration file since
the template feature would not trigger in this case.

Signed-off-by: Matthieu Moy matthieu@imag.fr
---
 builtin/commit.c | 34 --
 1 file changed, 32 insertions(+), 2 deletions(-)

diff --git a/builtin/commit.c b/builtin/commit.c
index 5ed6036..7502b0e 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -42,7 +42,20 @@ static const char * const builtin_status_usage[] = {
NULL
 };
 
-static const char implicit_ident_advice[] =
+static const char implicit_ident_advice_noconfig[] =
+N_(Your name and email address were configured automatically based\n
+on your username and hostname. Please check that they are accurate.\n
+You can suppress this message by setting them explicitly. Run the\n
+following command and follow the instructions in your editor to edit\n
+your configuration file:\n
+\n
+git config --global --edit\n
+\n
+After doing this, you may fix the identity used for this commit with:\n
+\n
+git commit --amend --reset-author\n);
+
+static const char implicit_ident_advice_config[] =
 N_(Your name and email address were configured automatically based\n
 on your username and hostname. Please check that they are accurate.\n
 You can suppress this message by setting them explicitly:\n
@@ -1402,6 +1415,23 @@ int cmd_status(int argc, const char **argv, const char 
*prefix)
return 0;
 }
 
+static const char *implicit_ident_advice() {
+   char *user_config = NULL;
+   char *xdg_config = NULL;
+   int config_exists;
+
+   home_config_paths(user_config, xdg_config, config);
+   config_exists = file_exists(user_config) || file_exists(xdg_config);
+   free(user_config);
+   free(xdg_config);
+
+   if (config_exists)
+   return _(implicit_ident_advice_config);
+   else
+   return _(implicit_ident_advice_noconfig);
+
+}
+
 static void print_summary(const char *prefix, const unsigned char *sha1,
  int initial_commit)
 {
@@ -1440,7 +1470,7 @@ static void print_summary(const char *prefix, const 
unsigned char *sha1,
strbuf_addbuf_percentquote(format, committer_ident);
if (advice_implicit_identity) {
strbuf_addch(format, '\n');
-   strbuf_addstr(format, _(implicit_ident_advice));
+   strbuf_addstr(format, implicit_ident_advice());
}
}
strbuf_release(author_ident);
-- 
2.0.2.737.gfb43bde

--
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 2/3] home_config_path: allow NULL xdg parameter

2014-07-25 Thread Junio C Hamano
Matthieu Moy matthieu@imag.fr writes:

 This allows a caller to requst the global config file without requesting
 the XDG one.

 Signed-off-by: Matthieu Moy matthieu@imag.fr
 ---
 This is actually not needed, but I wrote this for a previous version,
 and it seems sensible anyway.

I was about to say Let's not do this until some caller needs it,
implicitly assuming that we do not let global=NULL to signal that
the caller is interested only in XDG, but I checked and we do check
the NULL-ness of global, so it is consistent to do so for xdg.  The
change makes very good sense.

I wouldn't have had to spend the time to dig, if the log message
justified it that way, instead of having actually not needed
comment there ;-)

home_config_paths(): let the caller ignore xdg path

The caller can signal that it is not interested in learning
the location of $HOME/.gitconfig by passing global=NULL, but
there is no way to decline the ptah to the configuration
file based on $XDG_CONFIG_HOME.

Allow the caller to pass xdg=NULL to signal that it is not
interested in the XDG location.

or something, perhaps?


  path.c | 10 ++
  1 file changed, 6 insertions(+), 4 deletions(-)

 diff --git a/path.c b/path.c
 index 3afcdb4..f68df0c 100644
 --- a/path.c
 +++ b/path.c
 @@ -148,10 +148,12 @@ void home_config_paths(char **global, char **xdg, char 
 *file)
   *global = mkpathdup(%s/.gitconfig, home);
   }
  
 - if (!xdg_home)
 - *xdg = NULL;
 - else
 - *xdg = mkpathdup(%s/git/%s, xdg_home, file);
 + if (xdg) {
 + if (!xdg_home)
 + *xdg = NULL;
 + else
 + *xdg = mkpathdup(%s/git/%s, xdg_home, file);
 + }
  
   free(to_free);
  }
--
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 2/3] home_config_path: allow NULL xdg parameter

2014-07-25 Thread Matthieu Moy
Junio C Hamano gits...@pobox.com writes:

 Matthieu Moy matthieu@imag.fr writes:

 This allows a caller to requst the global config file without requesting
 the XDG one.

 Signed-off-by: Matthieu Moy matthieu@imag.fr
 ---
 This is actually not needed, but I wrote this for a previous version,
 and it seems sensible anyway.

 I was about to say Let's not do this until some caller needs it,
 implicitly assuming that we do not let global=NULL to signal that
 the caller is interested only in XDG, but I checked and we do check
 the NULL-ness of global, so it is consistent to do so for xdg.  The
 change makes very good sense.

 I wouldn't have had to spend the time to dig, if the log message
 justified it that way, instead of having actually not needed
 comment there ;-)

   home_config_paths(): let the caller ignore xdg path

   The caller can signal that it is not interested in learning
   the location of $HOME/.gitconfig by passing global=NULL, but
   there is no way to decline the ptah to the configuration
   file based on $XDG_CONFIG_HOME.

 Allow the caller to pass xdg=NULL to signal that it is not
 interested in the XDG location.

Good point. Applied locally, I'll resend later.

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


Re: [PATCH 5/7] enforce `xfuncname` precedence over `funcname`

2014-07-25 Thread Junio C Hamano
Matthieu Moy matthieu@grenoble-inp.fr writes:

 I'd just replace list with array and use
 Documentation/technical/api-allocation-growing.txt.

 But I can't think of a better way.

 Presumably this array will reflect the order the source file told us
 about the keys and their values; I wonder if the filename, lineno
 information we already have can be used (or unified) with it?

 I've thought about this too, and I think it would be really hard.

Yeah, I do not offhand think of a good solution, either, without
going pointer-crazy and have bidirectional link everywhere X-.
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2 1/3] config --global --edit: create a template file if needed

2014-07-25 Thread Junio C Hamano
Matthieu Moy matthieu@imag.fr writes:

 When the user has no ~/.gitconfig file, git config --global --edit used
 to launch an editor on an nonexistant file name.

 Instead, create a file with a default content before launching the
 editor. The template contains only commented-out entries, to save a few
 keystrokes for the user. If the values are guessed properly, the user
 will only have to uncomment the entries.

 Advanced users teaching newbies can create a minimalistic configuration
 faster for newbies. Beginners reading a tutorial advising to run git
 config --global --edit as a first step will be slightly more guided for
 their first contact with Git.

 Signed-off-by: Matthieu Moy matthieu@imag.fr
 ---
 Hopefully, all remarks applied. I went for Git's user configuration, but
 I can change it to whatever native speakers think is better.

I am not native but I have a slight worry that a template that lists
only core.{user,email} and marked as Git's user configuration will
easily mislead the reader that the file is only about these two
(i.e. I am telling the stupid Git who I am), and is not meant to
hold any other configuration that are private to the user.  I still
have funny feeling about user-wide, but Git's user configuration
somehow smells worse for that reason.

What the patch attempts to do is a good idea and the code looks done
right.  Let's queue it and hope people can polish the wording.

Thanks.

  builtin/config.c | 31 ---
  cache.h  |  1 +
  ident.c  |  2 +-
  3 files changed, 30 insertions(+), 4 deletions(-)

 diff --git a/builtin/config.c b/builtin/config.c
 index fcd8474..1363478 100644
 --- a/builtin/config.c
 +++ b/builtin/config.c
 @@ -445,6 +445,20 @@ static int get_urlmatch(const char *var, const char *url)
   return 0;
  }
  
 +static char *default_user_config(void)
 +{
 + struct strbuf buf = STRBUF_INIT;
 + strbuf_addf(buf,
 + _(# This is Git's user configuration file.\n
 +   [core]\n
 +   # Please adapt and uncomment the following lines:\n
 +   #user = %s\n
 +   #email = %s\n),
 + ident_default_name(),
 + ident_default_email());
 + return strbuf_detach(buf, NULL);
 +}
 +
  int cmd_config(int argc, const char **argv, const char *prefix)
  {
   int nongit = !startup_info-have_repository;
 @@ -551,6 +565,8 @@ int cmd_config(int argc, const char **argv, const char 
 *prefix)
   }
   }
   else if (actions == ACTION_EDIT) {
 + const char *config_file = given_config_source.file ?
 + given_config_source.file : git_path(config);
   check_argc(argc, 0, 0);
   if (!given_config_source.file  nongit)
   die(not in a git directory);
 @@ -559,9 +575,18 @@ int cmd_config(int argc, const char **argv, const char 
 *prefix)
   if (given_config_source.blob)
   die(editing blobs is not supported);
   git_config(git_default_config, NULL);
 - launch_editor(given_config_source.file ?
 -   given_config_source.file : git_path(config),
 -   NULL, NULL);
 + if (use_global_config) {
 + int fd = open(config_file, O_CREAT | O_EXCL | O_WRONLY, 
 0666);
 + if (fd) {
 + char *content = default_user_config();
 + write_str_in_full(fd, content);
 + free(content);
 + close(fd);
 + }
 + else if (errno != EEXIST)
 + die_errno(_(cannot create configuration file 
 %s), config_file);
 + }
 + launch_editor(config_file, NULL, NULL);
   }
   else if (actions == ACTION_SET) {
   int ret;
 diff --git a/cache.h b/cache.h
 index fcb511d..b06cbb2 100644
 --- a/cache.h
 +++ b/cache.h
 @@ -1061,6 +1061,7 @@ extern const char *git_author_info(int);
  extern const char *git_committer_info(int);
  extern const char *fmt_ident(const char *name, const char *email, const char 
 *date_str, int);
  extern const char *fmt_name(const char *name, const char *email);
 +extern const char *ident_default_name(void);
  extern const char *ident_default_email(void);
  extern const char *git_editor(void);
  extern const char *git_pager(int stdout_is_tty);
 diff --git a/ident.c b/ident.c
 index 1d9b6e7..77bc882 100644
 --- a/ident.c
 +++ b/ident.c
 @@ -102,7 +102,7 @@ static void copy_email(const struct passwd *pw, struct 
 strbuf *email)
   add_domainname(email);
  }
  
 -static const char *ident_default_name(void)
 +const char *ident_default_name(void)
  {
   if (!git_default_name.len) {
   copy_gecos(xgetpwuid_self(), git_default_name);
--
To unsubscribe from this 

Re: [PATCH v2 2/3] home_config_path: allow NULL xdg parameter

2014-07-25 Thread Junio C Hamano
Matthieu Moy matthieu@imag.fr writes:

 This allows a caller to request the global config file without requesting
 the XDG one.

 Signed-off-by: Matthieu Moy matthieu@imag.fr
 ---

Will rephrase

A caller can ask only for XDG location by passing global=NULL.
Allow it to ask only for the $HOME/.gitconfig by passing
xdg=NULL.

as you seem to have forgotten ;-)

  path.c | 10 ++
  1 file changed, 6 insertions(+), 4 deletions(-)

 diff --git a/path.c b/path.c
 index 3afcdb4..f68df0c 100644
 --- a/path.c
 +++ b/path.c
 @@ -148,10 +148,12 @@ void home_config_paths(char **global, char **xdg, char 
 *file)
   *global = mkpathdup(%s/.gitconfig, home);
   }
  
 - if (!xdg_home)
 - *xdg = NULL;
 - else
 - *xdg = mkpathdup(%s/git/%s, xdg_home, file);
 + if (xdg) {
 + if (!xdg_home)
 + *xdg = NULL;
 + else
 + *xdg = mkpathdup(%s/git/%s, xdg_home, file);
 + }
  
   free(to_free);
  }
--
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 1/3] config --global --edit: create a template file if needed

2014-07-25 Thread Matthieu Moy
When the user has no ~/.gitconfig file, git config --global --edit used
to launch an editor on an nonexistant file name.

Instead, create a file with a default content before launching the
editor. The template contains only commented-out entries, to save a few
keystrokes for the user. If the values are guessed properly, the user
will only have to uncomment the entries.

Advanced users teaching newbies can create a minimalistic configuration
faster for newbies. Beginners reading a tutorial advising to run git
config --global --edit as a first step will be slightly more guided for
their first contact with Git.

Signed-off-by: Matthieu Moy matthieu@imag.fr
---
 I am not native but I have a slight worry that a template that lists
 only core.{user,email} and marked as Git's user configuration will
 easily mislead the reader that the file is only about these two

Good point, here's the one with per-user, and PATCH 2 with your
improved commit message.

 builtin/config.c | 31 ---
 cache.h  |  1 +
 ident.c  |  2 +-
 3 files changed, 30 insertions(+), 4 deletions(-)

diff --git a/builtin/config.c b/builtin/config.c
index fcd8474..aba7135 100644
--- a/builtin/config.c
+++ b/builtin/config.c
@@ -445,6 +445,20 @@ static int get_urlmatch(const char *var, const char *url)
return 0;
 }
 
+static char *default_user_config(void)
+{
+   struct strbuf buf = STRBUF_INIT;
+   strbuf_addf(buf,
+   _(# This is Git's per-user configuration file.\n
+ [core]\n
+ # Please adapt and uncomment the following lines:\n
+ #user = %s\n
+ #email = %s\n),
+   ident_default_name(),
+   ident_default_email());
+   return strbuf_detach(buf, NULL);
+}
+
 int cmd_config(int argc, const char **argv, const char *prefix)
 {
int nongit = !startup_info-have_repository;
@@ -551,6 +565,8 @@ int cmd_config(int argc, const char **argv, const char 
*prefix)
}
}
else if (actions == ACTION_EDIT) {
+   const char *config_file = given_config_source.file ?
+   given_config_source.file : git_path(config);
check_argc(argc, 0, 0);
if (!given_config_source.file  nongit)
die(not in a git directory);
@@ -559,9 +575,18 @@ int cmd_config(int argc, const char **argv, const char 
*prefix)
if (given_config_source.blob)
die(editing blobs is not supported);
git_config(git_default_config, NULL);
-   launch_editor(given_config_source.file ?
- given_config_source.file : git_path(config),
- NULL, NULL);
+   if (use_global_config) {
+   int fd = open(config_file, O_CREAT | O_EXCL | O_WRONLY, 
0666);
+   if (fd) {
+   char *content = default_user_config();
+   write_str_in_full(fd, content);
+   free(content);
+   close(fd);
+   }
+   else if (errno != EEXIST)
+   die_errno(_(cannot create configuration file 
%s), config_file);
+   }
+   launch_editor(config_file, NULL, NULL);
}
else if (actions == ACTION_SET) {
int ret;
diff --git a/cache.h b/cache.h
index fcb511d..b06cbb2 100644
--- a/cache.h
+++ b/cache.h
@@ -1061,6 +1061,7 @@ extern const char *git_author_info(int);
 extern const char *git_committer_info(int);
 extern const char *fmt_ident(const char *name, const char *email, const char 
*date_str, int);
 extern const char *fmt_name(const char *name, const char *email);
+extern const char *ident_default_name(void);
 extern const char *ident_default_email(void);
 extern const char *git_editor(void);
 extern const char *git_pager(int stdout_is_tty);
diff --git a/ident.c b/ident.c
index 1d9b6e7..77bc882 100644
--- a/ident.c
+++ b/ident.c
@@ -102,7 +102,7 @@ static void copy_email(const struct passwd *pw, struct 
strbuf *email)
add_domainname(email);
 }
 
-static const char *ident_default_name(void)
+const char *ident_default_name(void)
 {
if (!git_default_name.len) {
copy_gecos(xgetpwuid_self(), git_default_name);
-- 
2.0.2.737.gfb43bde

--
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 2/3] home_config_paths(): let the caller ignore xdg path

2014-07-25 Thread Matthieu Moy
The caller can signal that it is not interested in learning
the location of $HOME/.gitconfig by passing global=NULL, but
there is no way to decline the path to the configuration
file based on $XDG_CONFIG_HOME.

Allow the caller to pass xdg=NULL to signal that it is not
interested in the XDG location.

Commit-message-by: Junio C Hamano gits...@pobox.com
Signed-off-by: Matthieu Moy matthieu@imag.fr
---
 path.c | 10 ++
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/path.c b/path.c
index 3afcdb4..f68df0c 100644
--- a/path.c
+++ b/path.c
@@ -148,10 +148,12 @@ void home_config_paths(char **global, char **xdg, char 
*file)
*global = mkpathdup(%s/.gitconfig, home);
}
 
-   if (!xdg_home)
-   *xdg = NULL;
-   else
-   *xdg = mkpathdup(%s/git/%s, xdg_home, file);
+   if (xdg) {
+   if (!xdg_home)
+   *xdg = NULL;
+   else
+   *xdg = mkpathdup(%s/git/%s, xdg_home, file);
+   }
 
free(to_free);
 }
-- 
2.0.2.737.gfb43bde

--
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 3/3] commit: advertise config --global --edit on guessed identity

2014-07-25 Thread Matthieu Moy
When the user has no user-wide configuration file, it's faster to use the
newly introduced config file template than to run two commands to set
user.name and user.email. Advise this to the user.

The old advice is kept if the user already has a configuration file since
the template feature would not trigger in this case.

Signed-off-by: Matthieu Moy matthieu@imag.fr
---
 builtin/commit.c | 34 --
 1 file changed, 32 insertions(+), 2 deletions(-)

diff --git a/builtin/commit.c b/builtin/commit.c
index 5ed6036..7502b0e 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -42,7 +42,20 @@ static const char * const builtin_status_usage[] = {
NULL
 };
 
-static const char implicit_ident_advice[] =
+static const char implicit_ident_advice_noconfig[] =
+N_(Your name and email address were configured automatically based\n
+on your username and hostname. Please check that they are accurate.\n
+You can suppress this message by setting them explicitly. Run the\n
+following command and follow the instructions in your editor to edit\n
+your configuration file:\n
+\n
+git config --global --edit\n
+\n
+After doing this, you may fix the identity used for this commit with:\n
+\n
+git commit --amend --reset-author\n);
+
+static const char implicit_ident_advice_config[] =
 N_(Your name and email address were configured automatically based\n
 on your username and hostname. Please check that they are accurate.\n
 You can suppress this message by setting them explicitly:\n
@@ -1402,6 +1415,23 @@ int cmd_status(int argc, const char **argv, const char 
*prefix)
return 0;
 }
 
+static const char *implicit_ident_advice() {
+   char *user_config = NULL;
+   char *xdg_config = NULL;
+   int config_exists;
+
+   home_config_paths(user_config, xdg_config, config);
+   config_exists = file_exists(user_config) || file_exists(xdg_config);
+   free(user_config);
+   free(xdg_config);
+
+   if (config_exists)
+   return _(implicit_ident_advice_config);
+   else
+   return _(implicit_ident_advice_noconfig);
+
+}
+
 static void print_summary(const char *prefix, const unsigned char *sha1,
  int initial_commit)
 {
@@ -1440,7 +1470,7 @@ static void print_summary(const char *prefix, const 
unsigned char *sha1,
strbuf_addbuf_percentquote(format, committer_ident);
if (advice_implicit_identity) {
strbuf_addch(format, '\n');
-   strbuf_addstr(format, _(implicit_ident_advice));
+   strbuf_addstr(format, implicit_ident_advice());
}
}
strbuf_release(author_ident);
-- 
2.0.2.737.gfb43bde

--
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 1/3] config --global --edit: create a template file if needed

2014-07-25 Thread Junio C Hamano
Thanks; will queue the patches from this iteration.
--
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/5] refs.c: allow passing raw git_committer_info as email to _update_reflog

2014-07-25 Thread Jonathan Nieder
Ronnie Sahlberg wrote:

 Add a new flag REFLOG_EMAIL_IS_COMMITTER to _update_reflog to tell it
 that what we pass in as email is already the fully baked committer string
 we can use as-is.

With and without the new flag, the 'email' argument has two different
meanings:

 * with the new flag, it should be an ident string, like
   'Jonathan Nieder jrnie...@gmail.com 1406251347 -0700'

 * without it, it should be the name-part of an ident string,
   like 'Jonathan Nieder jrnie...@gmail.com

In neither case is it an email address.  This seems unnecessarily
confusing.

Is the caller responsible for checking the argument for validity?
Do callers do so?  Is this performance-critical or could the
transaction_update_reflog function do a sanity-check?

[...]
  /*
   * Append a reflog entry for refname. If the REFLOG_TRUNCATE flag is set
   * this update will first truncate the reflog before writing the entry.
   * If msg is NULL no update will be written to the log.
   */
  int transaction_update_reflog(struct ref_transaction *transaction,
const char *refname,
const unsigned char *new_sha1,
const unsigned char *old_sha1,
const char *email,
unsigned long timestamp, int tz,
const char *msg, int flags,
struct strbuf *err);

This is a lot of parameters, some optional, not all documented.  Would
it make sense to pack some into a struct?

Thanks and hope that helps,
Jonathan
--
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 3/3] commit: advertise config --global --edit on guessed identity

2014-07-25 Thread Junio C Hamano
Matthieu Moy matthieu@imag.fr writes:

 +static const char *implicit_ident_advice() {

Style:

static const char *implicit_ident_advice(void)
{

No need to resend.

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 2/5] refs.c: return error instead of dying when locking fails during transaction

2014-07-25 Thread Jonathan Nieder
Ronnie Sahlberg wrote:

 --- a/refs.c
 +++ b/refs.c
 @@ -2214,7 +2214,7 @@ static struct ref_lock *lock_ref_sha1_basic(const char 
 *refname,
*/
   goto retry;
   else
 - unable_to_lock_index_die(ref_file, errno);
 + goto error_return;

Should probably save last_errno so error_return can pass that
information back.

Can the caller recover from this error?  Does it have enough information
to produce the same helpful message as unable_to_lock_index_die?

If this could be done without regressing behavior (e.g., by passing
back error information as a message instead of through errno) then I
think it would make sense.

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


Re: [PATCH 3/5] refs.c: use packed refs when deleting refs during a transaction

2014-07-25 Thread Jonathan Nieder
Ronnie Sahlberg wrote:

 Make the deletion of refs during a transaction more atomic.
 Start by first copying all loose refs we will be deleting to the packed
 refs file and then commit the packed refs file. Then re-lock the packed refs
 file to stop anyone else from modifying these refs and keep it locked until
 we are finished.
[...]
 By deleting all the loose refs at the start of the transaction we make make
 it possible to both delete one ref and then re-create a different ref in
 the same transaction even if the two refs would normally conflict.

 Example: rename m-m/m

Makes a lot of sense.

This can potentially slow down a single-ref deletion in a repository with
a huge amount of refs (e.g., a Gerrit server with lots of
refs/changes/* refs), right?  But the cost is not more than a factor
of 2 worse than if the ref had been packed (since you have to
repack_without_refs anyway) so I think this is acceptable.

[...]
 The exception is for refs that can not be resolved. Those refs are never
 added to the packed refs and will just be un-rollback-ably deleted during
 commit.

This also seems reasonable --- there's no need to be able to roll back
into an invalid state. :)

[...]
 --- a/builtin/remote.c
 +++ b/builtin/remote.c
 @@ -756,6 +756,8 @@ static int remove_branches(struct string_list *branches)
   branch_names = xmalloc(branches-nr * sizeof(*branch_names));
   for (i = 0; i  branches-nr; i++)
   branch_names[i] = branches-items[i].string;
 + if (lock_packed_refs(0))
 + result |= unable_to_lock_error(git_path(packed-refs), errno);
   result |= repack_without_refs(branch_names, branches-nr, NULL);

What should happen if lock_packed_refs fails?  Since
repack_without_refs is now documented to require a locked packed-refs
file, shouldn't the repack_without_refs call be guarded, like it is
below?

[...]
 @@ -1333,9 +1335,14 @@ static int prune_remote(const char *remote, int 
 dry_run)
   delete_refs = xmalloc(states.stale.nr * sizeof(*delete_refs));
   for (i = 0; i  states.stale.nr; i++)
   delete_refs[i] = states.stale.items[i].util;
 - if (!dry_run)
 - result |= repack_without_refs(delete_refs,
 -   states.stale.nr, NULL);
 + if (!dry_run) {
 + if (lock_packed_refs(0))
 + result |= unable_to_lock_error(
 + git_path(packed-refs), errno);
 + else
 + result |= repack_without_refs(delete_refs,
 + states.stale.nr, NULL);
[...]
 --- a/refs.c
 +++ b/refs.c
 @@ -1330,7 +1330,7 @@ static struct ref_entry *get_packed_ref(const char 
 *refname)
  
  /*
   * A loose ref file doesn't exist; check for a packed ref.  The
 - * options are forwarded from resolve_safe_unsafe().
 + * options are forwarded from resolve_ref_unsafe().

Unrelated changes snuck in?  (A good change, but it presumably belongs
as a separate patch.)

[...]
 @@ -1387,7 +1387,6 @@ const char *resolve_ref_unsafe(const char *refname, 
 unsigned char *sha1, int fla
   }
  
   git_snpath(path, sizeof(path), %s, refname);
 -
   /*

Why?

[...]
 @@ -2532,6 +2531,9 @@ static int curate_packed_ref_fn(struct ref_entry 
 *entry, void *cb_data)
   return 0;
  }
  
 +/*
 + * Must be called with packed refs already locked (and sorted)
 + */
  int repack_without_refs(const char **refnames, int n, struct strbuf *err)

Aren't packed refs always sorted?  If it needs mentioning, that seems
more like an implementation comment.

The 'packed refs must be locked' kind of documentation belongs in
refs.h since this is part of the API.  Usually when there are API
changes like this we like to change the function name or signature to
make it easy to catch callers that were introduced without noticing
the change --- would that be easy to do here?

E.g. introducing a new repack_without_refs_locked (name is just a
placeholder, I'm bad at names) and keeping repack_without_refs with
the current semantics as a wrapper around that.

[...]
 @@ -2544,19 +2546,12 @@ int repack_without_refs(const char **refnames, int n, 
 struct strbuf *err)
   if (get_packed_ref(refnames[i]))
   break;
  
 - /* Avoid locking if we have nothing to do */
 + /* Avoid processing if we have nothing to do */

This implies a small speed regression but I don't think anyone would
mind.

[...]
 @@ -3692,12 +3689,65 @@ int transaction_commit(struct ref_transaction 
 *transaction,
   goto cleanup;
   }
  
 - /* Acquire all ref locks while verifying old values */
 + /* Lock packed refs during commit */
 + if (lock_packed_refs(0)) {

I stopped reviewing here but assume the rest is okay. :)

Thanks,
Jonathan
--
To unsubscribe from this list: send the line 

Re: [PATCH 4/5] refs.c: update rename_ref to use a transaction

2014-07-25 Thread Jonathan Nieder
Ronnie Sahlberg wrote:

 Change refs.c to use a single transaction to copy/rename both the refs and
 its reflog.

Yay!

 Since we are no longer using rename() to move the reflog file
 we no longer need to disallow rename_ref for refs with a symlink for its
 reflog so we can remove that test from the testsuite.

It's generally better to update the testsuite with the new expected
behavior instead. :)
--
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


Amending merge commits?

2014-07-25 Thread Besen, David

Hi folks,

I think one of my coworkers has stumbled on a git bug -- if you amend a merge 
commit, and then pull, your amends are lost.

Is this expected behavior?

I've reproduced the problem in a script (attached).  I ran it against a couple 
of versions of git (1.7.1, 1.7.9, 1.8.4, 2.0.0) and in each case it seemed to 
lose the amend.

- Dave



amend-merge.sh
Description: amend-merge.sh


Re: What's cooking in git.git (Jul 2014, #04; Tue, 22)

2014-07-25 Thread Junio C Hamano
Junio C Hamano gits...@pobox.com writes:

 Philip Oakley philipoak...@iee.org writes:

 which still makes me feel hesitant to promote this
 document without updating its contents, though.


 I hadn't viewed it as a 'promotion', rather it was simply ensuring
 access to the guide via the help system, instead of leaving it
 somewhat hidden.

 Stale or incorrect pieces of advice that are hidden will not harm
 (non-)readers.  Making them more available would mean giving them
 more chances to do harm ;-).

Let's disect it.  I do not have time/concentration to finish all in
one message, so I'll do the first two.

| Everyday Git With 20 Commands Or So
| ===
| 
| Individual Developer (Standalone) commands are essential for
| anybody who makes a commit, even for somebody who works alone.
| 
| If you work with other people, you will need commands listed in
| the Individual Developer (Participant) section as well.
| 
| People who play the Integrator role need to learn some more
| commands in addition to the above.
| 
| Repository Administration commands are for system
| administrators who are responsible for the care and feeding
| of Git repositories.

Let's assume the categorization above is sensible for now.

| Individual Developer (Standalone)[[Individual Developer (Standalone)]]
| --
| 
| A standalone individual developer does not exchange patches with
| other people, and works alone in a single repository, using the
| following commands.
| ...

Everything in the enumeration looks OK except for this one,

|   * linkgit:git-show-branch[1] to see where you are.

which is probably no longer the case, for two reasons.  In the
original design of Git UI, you see many things that encourage you to
view and think about the whole collection of your branches as a whole.
git show-branch whose default is to show all of your branches is
just one of them (other examples include git push whose default
used to be matching, expecting that you will work on completing
all the branches before you push the result out for all of them).

Over time, Git UI mutated into put a lot more focus and stress on
the current branch, disregarding what are on the branches you are
not corrently on.  git log @{u}.. to see how much more you have
done on top of others' work would be more in line with such an
attitude.

I'd suggest dropping this command from this enumeration.

| Examples
| 
| 
| Use a tarball as a starting point for a new repository.::
| ...

Perfectly fine.

| Create a topic branch and develop.::
| +
| 
| $ git checkout -b alsa-audio 1
| $ edit/compile/test
| $ git checkout -- curses/ux_audio_oss.c 2
| $ git add curses/ux_audio_alsa.c 3
| $ edit/compile/test
| $ git diff HEAD 4
| $ git commit -a -s 5

Perefectly fine up to this point.

| $ edit/compile/test
| $ git reset --soft HEAD^ 6
| $ edit/compile/test
| $ git diff ORIG_HEAD 7
| $ git commit -a -c ORIG_HEAD 8

This shows how a typical sequence I try to further tweak what I
committed looked like.  With the modern Git, you would do

$ edit/compile/test
$ git diff HEAD^ 7
$ git commit -a --amend

without the soft reset, which was invented solely because there
wasn't commit --amend available.

The example is perfectly fine after this step, but 6 and 8 need
to be dropped and others renumbered.

| Individual Developer (Participant)[[Individual Developer (Participant)]]
| 
| ...
|   * linkgit:git-format-patch[1] to prepare e-mail submission, if
| you adopt Linux kernel-style public forum workflow.

Probably git-send-email needs to be appended to the end of the
enumeration.

| Examples
| 
| 
| Clone the upstream and work on it.  Feed changes to upstream.::
| +
| 
| $ git clone git://git.kernel.org/pub/scm/.../torvalds/linux-2.6 my2.6
| $ cd my2.6
| $ edit/compile/test; git commit -a -s 1
| $ git format-patch origin 2
| $ git pull 3
| $ git log -p ORIG_HEAD.. arch/i386 include/asm-i386 4
| $ git pull git://git.kernel.org/pub/.../jgarzik/libata-dev.git ALL 5
| $ git reset --hard ORIG_HEAD 6
| $ git gc 7
| $ git fetch --tags 8
| 
| +
| 1 repeat as needed.
| 2 extract patches from your branch for e-mail submission.
| 3 `git pull` fetches from `origin` by default and merges into the
| current branch.
| 4 immediately after pulling, look at the changes done upstream
| since last time we checked, only in the
| area we are interested in.
| 5 fetch from a specific branch from a specific repository and merge.
| 6 revert the pull.
| 7 garbage collect leftover objects from reverted pull.
| 8 from time to time, obtain official tags from the `origin`
| and store them under `.git/refs/tags/`.

This example works directly on 'master', which is not ideal.  If I
were writing this today, I would have made it work on 'mine' branch,
produced a patch series out of that branch 

Re: Amending merge commits?

2014-07-25 Thread David Besen
Besen, David david.besen at hp.com writes:

 
 
 Hi folks,
 
 I think one of my coworkers has stumbled on a git bug -- if you amend a 
merge commit, and then pull, your amends
 are lost.
 
 Is this expected behavior?
 
 I've reproduced the problem in a script (attached).  I ran it against a 
couple of versions of git (1.7.1,
 1.7.9, 1.8.4, 2.0.0) and in each case it seemed to lose the amend.
 
 - Dave
 
 
 Attachment (amend-merge.sh): application/octet-stream, 1061 bytes


Whoops, accidentally encoded the script, here it is inline:

#!/bin/bash

set -ex

if [ -z $GIT ]; then GIT=git; fi
GIT_MERGE_AUTOEDIT=no

# Clean up from the last run
rm -rf repo.git repo repo2 || :

# Set up a bare remote repo
$GIT init --bare repo.git

# Check out the remote repo
$GIT clone repo.git repo

# Add a commit
cd repo
echo file  file.txt
$GIT add file.txt
$GIT commit -m Add file.txt
$GIT push origin master

# Make a branch
$GIT checkout -b mybranch

# Add a commit on the branch
echo mybranch  file.txt
$GIT add .
$GIT commit -m Add 'mybranch' line

# Go back to master
$GIT checkout master

# Merge in mybranch to create a merge commit
$GIT merge --no-ff mybranch

# Push that back
$GIT push

# Amend the merge commit
echo amended  file.txt
$GIT add .
$GIT commit -C HEAD --amend

cd ..

# Make a second checkout
$GIT clone repo.git repo2
cd repo2

# Add some unrelated changes to be pulled
echo repo2  file2.txt
$GIT add .
$GIT commit -m Add file2
$GIT push

cd ..
cd repo

# Pull
$GIT pull --rebase

# Now, we expect the text amended to be in file.txt
grep amended file.txt



--
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: Amending merge commits?

2014-07-25 Thread Jonathan Nieder
Besen, David wrote:

 I think one of my coworkers has stumbled on a git bug -- if you
 amend a merge commit, and then pull, your amends are lost.

This is how pull --rebase works.  It turns your single-parent commits
into a sequence of patches on top of upstream and completely ignores
your merge commits.

There is a --rebase=preserve option that makes a halfhearted attempt
to preserve your merges --- perhaps that would help?  The
git-rebase(1) documentation has more details.

In an ideal world, I think pull --rebase would do the following:

 1. Do the same thing it does today
 2. Behind the scenes, *also* try a 'pull --merge' but don't save
the result.
 3. Compare the results.  If they differ, show a diff and explain
to the user what happened.

I may be the only one that wants that, though.

Hope that helps,
Jonathan
--
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: Amending merge commits?

2014-07-25 Thread Besen, David
Ah thanks, I'll RTFM better in the future.

- Dave

-Original Message-
From: Jonathan Nieder [mailto:jrnie...@gmail.com] 
Sent: Friday, July 25, 2014 4:19 PM
To: Besen, David
Cc: git@vger.kernel.org
Subject: Re: Amending merge commits?

Besen, David wrote:

 I think one of my coworkers has stumbled on a git bug -- if you
 amend a merge commit, and then pull, your amends are lost.

This is how pull --rebase works.  It turns your single-parent commits
into a sequence of patches on top of upstream and completely ignores
your merge commits.

There is a --rebase=preserve option that makes a halfhearted attempt
to preserve your merges --- perhaps that would help?  The
git-rebase(1) documentation has more details.

In an ideal world, I think pull --rebase would do the following:

 1. Do the same thing it does today
 2. Behind the scenes, *also* try a 'pull --merge' but don't save
the result.
 3. Compare the results.  If they differ, show a diff and explain
to the user what happened.

I may be the only one that wants that, though.

Hope that helps,
Jonathan
--
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: Amending merge commits?

2014-07-25 Thread Jonathan Nieder
David Besen wrote:
 Jonathan Nieder wrote:

 This is how pull --rebase works.  It turns your single-parent commits
 into a sequence of patches on top of upstream and completely ignores
 your merge commits.

 There is a --rebase=preserve option that makes a halfhearted attempt
 to preserve your merges --- perhaps that would help?  The
 git-rebase(1) documentation has more details.

 Ah thanks, I'll RTFM better in the future.

No, not a problem.  It's very useful to see examples of where git's
behavior was counterintuitive and the documentation was more obscure
than it could have been.

I should also emphasize the halfhearted above.  There's a lot of
room for improvement in rebase --preserve-merges's handling of evil
and otherwise amended merges.

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


Re: [PATCH 3/4] refs.c: move ref parsing code out of resolve_ref()

2014-07-25 Thread Duy Nguyen
On Fri, Jul 25, 2014 at 11:12 PM, Ronnie Sahlberg sahlb...@google.com wrote:
 diff --git a/refs.c b/refs.c
 index bec2bb1..2769f20 100644
 --- a/refs.c
 +++ b/refs.c
 @@ -1533,6 +1533,105 @@ static int handle_missing_loose_ref(const char 
 *refname,
 }
  }

 +int parse_ref(const char *path, struct strbuf *ref,
 + unsigned char *sha1, int *flag)

 Can you make this function static?
 It is not used by anything outside of this series and thus making it
 static avoids growing the public refs api.

It's to be used by builtin/checkout.c in nd/multiple-work-trees. I
could mark it static now and unmark it later, but I'd need to add the
static prototype back in refs.c because in the next patch
resolve_gitlink_ref() uses this function and resolve_gitlink_ref() is
before parse_ref().
-- 
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