Re: [PATCH v2 00/12] Improve "refs" module encapsulation

2015-06-14 Thread Stefan Beller
On Sat, Jun 13, 2015 at 7:42 AM, Michael Haggerty  wrote:
> This is v2 of this patch series. I think I have addressed all of the
> feedback from v1 [1]. Thanks to Stefan, Peff and Junio for their
> feedback.

This version looks good to me.

>
> Changes since v1:
>
> * Change docstring for delete_ref() and a comment within the function
>   definition.
>
> * Squash together two commits dealing with the error message in
>   delete_refs().
>
> These patches are also available from my GitHub account [2] as branch
> "init-delete-refs-api".
>
> Michael
>
> [1] http://thread.gmane.org/gmane.comp.version-control.git/271017
> [2] https://github.com/mhagger/git
>
> Michael Haggerty (12):
>   delete_ref(): move declaration to refs.h
>   remove_branches(): remove temporary
>   delete_ref(): handle special case more explicitly
>   delete_refs(): new function for the refs API
>   delete_refs(): improve error message
>   prune_remote(): use delete_refs()
>   repack_without_refs(): make function private
>   initial_ref_transaction_commit(): function for initial ref creation
>   refs: remove some functions from the module's public interface
>   initial_ref_transaction_commit(): check for duplicate refs
>   initial_ref_transaction_commit(): check for ref D/F conflicts
>   refs: move the remaining ref module declarations to refs.h
>
>  archive.c   |   1 +
>  builtin/blame.c |   1 +
>  builtin/clone.c |  19 -
>  builtin/fast-export.c   |   1 +
>  builtin/fmt-merge-msg.c |   1 +
>  builtin/init-db.c   |   1 +
>  builtin/log.c   |   1 +
>  builtin/remote.c|  33 +---
>  cache.h |  68 
>  refs.c  | 171 ---
>  refs.h  | 211 
> +++-
>  remote-testsvn.c|   1 +
>  12 files changed, 321 insertions(+), 188 deletions(-)
>
> --
> 2.1.4
>
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v7 2/5] setup: sanity check file size in read_gitfile_gently

2015-06-14 Thread Eric Sunshine
On Sun, Jun 14, 2015 at 1:21 PM, erik elfström  wrote:
> On Sun, Jun 14, 2015 at 5:42 AM, Eric Sunshine  
> wrote:
>>
>> This variable name doesn't convey much about its purpose, and
>> introduces a bit of maintenance burden if the limit is some day
>> changed. Perhaps "sane_size_limit" or something even more descriptive
>> (and/or terse) would be better.
>
> Would you be happy with this change?
>
> -   static const int one_MB = 1 << 20;
> +   static const int max_file_size = 1 << 20;  /* 1MB */

Yep, that's a much nicer variable name. Thanks.

I also note that 'const int' shows up pretty frequently in the git
source code, but 'static const int' is used only very rarely.
--
To unsubscribe from this list: send the line "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] Documentation/i18n.txt: clarify character encoding support

2015-06-14 Thread Junio C Hamano
Karsten Blees  writes:

> diff --git a/Documentation/i18n.txt b/Documentation/i18n.txt
> index e9a1d5d..e5f6233 100644
> --- a/Documentation/i18n.txt
> +++ b/Documentation/i18n.txt
> @@ -1,18 +1,28 @@
> -At the core level, Git is character encoding agnostic.
> -
> - - The pathnames recorded in the index and in the tree objects
> -   are treated as uninterpreted sequences of non-NUL bytes.
> -   What readdir(2) returns are what are recorded and compared
> -   with the data Git keeps track of, which in turn are expected
> -   to be what lstat(2) and creat(2) accepts.  There is no such
> -   thing as pathname encoding translation.
> +Git is to some extent character encoding agnostic.

I do not think the removal of the text makes much sense here unless
you add the equivalent to the new text below.

>   - The contents of the blob objects are uninterpreted sequences
> of bytes.  There is no encoding translation at the core
> level.
>  
> - - The commit log messages are uninterpreted sequences of non-NUL
> -   bytes.
> + - Pathnames are encoded in UTF-8 normalization form C. This

That is true only on some systems like OSX (with HFS+) and Windows,
no?  BSDs in general and Linux do not do any such mangling IIRC.  I
am OK with mangling described as a notable oddball to warn users,
though; i.e. not as a norm as your new text suggests but as an
exception.

> +   platforms. If file system APIs don't use UTF-8 (which may be
> +   file system specific), it is recommended to stick to pure
> +   ASCII file names.

Hmph, who endorsed such a recommendation?  It is recommended to
stick to whatever naming scheme that would not cause troubles to
project participants.  If your participants all want to (and can)
use ISO-8859-1, we do not discourage them from doing so.
--
To unsubscribe from this list: send the line "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] Makefile / racy-git.txt: clarify USE_NSEC prerequisites

2015-06-14 Thread Junio C Hamano
Karsten Blees  writes:

>  members are also compared, but this is not enabled by default
> -because in-core timestamps can have finer granularity than
> +because on Linux, in-core timestamps can have finer granularity than
>  on-disk timestamps, resulting in meaningless changes when an
>  inode is evicted from the inode cache.  See commit 8ce13b0
>  of git://git.kernel.org/pub/scm/linux/kernel/git/tglx/history.git
>  ([PATCH] Sync in core time granularity with filesystems,
> -2005-01-04).

Hmm, the above makes one wonder if on systems other than Linux it
may be better enabled by default.  Perhaps

members are also compared.  On Linux, this is not enabled by
default because ...

would make the logic and text flow better?

>  # Define USE_NSEC below if you want git to care about sub-second file mtimes
> -# and ctimes. Note that you need recent glibc (at least 2.2.4) for this, and
> -# it will BREAK YOUR LOCAL DIFFS! show-diff and anything using it will likely
> -# randomly break unless your underlying filesystem supports those sub-second
> -# times (my ext3 doesn't).
> +# and ctimes. Note that you need recent glibc (at least 2.2.4) for this. On
> +# Linux, kernel 2.6.11 or newer is required for reliable sub-second file 
> times
> +# on file systems with exactly 1 ns or 1 s resolution. If you intend to use 
> Git
> +# on other file systems (e.g. CEPH, CIFS, NTFS, UDF), don't enable USE_NSEC. 
> See
> +# Documentation/technical/racy-git.txt for details.

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


Re: [PATCH 0/3] Raw gpg output support for verify-commit and verify-tag

2015-06-14 Thread brian m. carlson
On Sun, Jun 14, 2015 at 02:23:47PM -0700, Junio C Hamano wrote:
> What this series wants to achieve makes a lot of sense to me.  One
> comment I have after skimming the patfches is that I want the new
> "raw" bit added not as a yet another parameter after "verbose", but
> by turning the existing "verbose" into an "unsigned flag" flag word
> (with "#define GPG_VERIFY_VERBOSE 01") and then defining use of a
> new bit in the same flag word "#define GPG_VERIFY_RAW 01" or
> something.  That way, over time other people add differnt things to
> the interface, we would not have to end up with 47 different
> parameters each of which signals a single bit.

I'll wait for other responses (if any) and then reroll.
-- 
brian m. carlson / brian with sandals: Houston, Texas, US
+1 832 623 2791 | http://www.crustytoothpaste.net/~bmc | My opinion only
OpenPGP: RSA v4 4096b: 88AC E9B2 9196 305B A994 7552 F1BA 225C 0223 B187


signature.asc
Description: Digital signature


Re: [PATCH/WIP v2 07/19] am: extract patch, message and authorship with git-mailinfo

2015-06-14 Thread Junio C Hamano
Paul Tan  writes:

> For the purpose of applying the patch and committing the results,
> implement extracting the patch data, commit message and authorship from
> an e-mail message using git-mailinfo.
>
> git-mailinfo is run as a separate process, but ideally in the future,
> we should be be able to access its functionality directly without
> spawning a new process.
>
> Helped-by: Junio C Hamano 
> Helped-by: Jeff King 
> Signed-off-by: Paul Tan 
> ---
>
> Notes:
> v2
> 
> * use die_errno()
> 
> * use '%*d' as the format specifier for msgnum()
>
>  builtin/am.c | 228 
> +++
>  1 file changed, 228 insertions(+)
>
> diff --git a/builtin/am.c b/builtin/am.c
> index 7379b97..a1db474 100644
> --- a/builtin/am.c
> +++ b/builtin/am.c
> @@ -9,6 +9,23 @@
>  #include "parse-options.h"
>  #include "dir.h"
>  #include "run-command.h"
> +#include "quote.h"
> +
> +/**
> + * Returns 1 if the file is empty or does not exist, 0 otherwise.
> + */
> +static int is_empty_file(const char *filename)
> +{
> + struct stat st;
> +
> + if (stat(filename, &st) < 0) {
> + if (errno == ENOENT)
> + return 1;
> + die_errno(_("could not stat %s"), filename);
> + }
> +
> + return !st.st_size;
> +}
>  
>  enum patch_format {
>   PATCH_FORMAT_UNKNOWN = 0,
> @@ -23,6 +40,12 @@ struct am_state {
>   int cur;
>   int last;
>  
> + /* commit message and metadata */
> + struct strbuf author_name;
> + struct strbuf author_email;
> + struct strbuf author_date;
> + struct strbuf msg;
> +
>   /* number of digits in patch filename */
>   int prec;
>  };
> @@ -35,6 +58,10 @@ static void am_state_init(struct am_state *state)
>   memset(state, 0, sizeof(*state));
>  
>   strbuf_init(&state->dir, 0);
> + strbuf_init(&state->author_name, 0);
> + strbuf_init(&state->author_email, 0);
> + strbuf_init(&state->author_date, 0);
> + strbuf_init(&state->msg, 0);
>   state->prec = 4;
>  }
>  
> @@ -44,6 +71,10 @@ static void am_state_init(struct am_state *state)
>  static void am_state_release(struct am_state *state)
>  {
>   strbuf_release(&state->dir);
> + strbuf_release(&state->author_name);
> + strbuf_release(&state->author_email);
> + strbuf_release(&state->author_date);
> + strbuf_release(&state->msg);
>  }
>  
>  /**
> @@ -93,6 +124,95 @@ static int read_state_file(struct strbuf *sb, const char 
> *file, size_t hint, int
>  }
>  
>  /**
> + * Parses the "author script" `filename`, and sets state->author_name,
> + * state->author_email and state->author_date accordingly. We are strict with
> + * our parsing, as the author script is supposed to be eval'd, and loosely
> + * parsing it may not give the results the user expects.
> + *
> + * The author script is of the format:
> + *
> + *   GIT_AUTHOR_NAME='$author_name'

It seems that you have SP * SP TAB GIT_AUTHOR_... here; lose SP
before the TAB?

> + if (!skip_prefix(sb.buf, "GIT_AUTHOR_NAME=", (const char**) &value))

Style:

if (!skip_prefix(sb.buf, "GIT_AUTHOR_NAME=", (const char **)&value))
--
To unsubscribe from this list: send the line "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/WIP v2 03/19] am: implement skeletal builtin am

2015-06-14 Thread Junio C Hamano
Paul Tan  writes:

> +int cmd_am(int argc, const char **argv, const char *prefix)
> +{
> + if (!getenv("_GIT_USE_BUILTIN_AM")) {
> + const char *path = mkpath("%s/git-am", git_exec_path());
> +
> + if (sane_execvp(path, (char**) argv) < 0)

Style: 

if (sane_execvp(path, (char**)argv) < 0)

> + die_errno("could not exec %s", path);
> + }
> +
> + return 0;
> +}
> diff --git a/git.c b/git.c
> index 44374b1..42328ed 100644
> --- a/git.c
> +++ b/git.c
> @@ -370,6 +370,7 @@ static int run_builtin(struct cmd_struct *p, int argc, 
> const char **argv)
>  
>  static struct cmd_struct commands[] = {
>   { "add", cmd_add, RUN_SETUP | NEED_WORK_TREE },
> + { "am", cmd_am, RUN_SETUP | NEED_WORK_TREE },

Would this, especially having RUN_SETUP, keep the same behaviour
when the command is run from a subdirectory of a working tree?
e.g.

save messages to ./inbox
$ cd sub/dir
$ git am ../../inbox



>   { "annotate", cmd_annotate, RUN_SETUP },
>   { "apply", cmd_apply, RUN_SETUP_GENTLY },
>   { "archive", cmd_archive },
--
To unsubscribe from this list: send the line "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] pathspec: adjust prefixlen after striping trailing slash

2015-06-14 Thread Junio C Hamano
Duy Nguyen  writes:

> I think we should stop the ok-to-replace feature when submodules are
> involved, we consider submdules much more valuable than symlinks.

Hmm, I am not sure "valuable" is a good criterion to decide what
should happen, though.

The push to use ".git" that is a file pointing at a repository that
is safely stored away is a move to make valuable submodule more
easily removable from the working tree without losing information,
so that we can remove it from the working tree when the user
instructs us to, just like we can remove a symlink safely without
losing information.  The only thing we need to be careful is that
that the path that corresponds to the index entry is not "dirty".
That is, for a symlink, if you make it point at something different
without doing "git add" it, you would lose that working-tree-only
change when we "kill" that symbolic link in order to replace it with
a regular directory.  For a submodule, if you have uncommitted
changes in the submodule working tree, you would lose that the same
way when we "kill" that submodule in order to replace that directory
as part of the superproject's working tree.

There may need some more safety implemented (i.e. how we detect the
"dirty"-ness and when we stop the operation based on that), but I
would imagine there is nothing fundamentally special about submodule
that does not apply to a symlink or a normal blob.
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [GIT PULL] l10n updates for 2.4 maint branch

2015-06-14 Thread Junio C Hamano
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 0/3] Raw gpg output support for verify-commit and verify-tag

2015-06-14 Thread Junio C Hamano
"brian m. carlson"  writes:

> Currently, verify-commit and verify-tag produce human-readable output.
> This is great for humans, and awful for machines.  It also lacks a lot
> of the information that GnuPG's --status-fd output provides.
>
> For example, if you wanted to know
> * the hash algorithm;
> * whether the signature was made with a subkey; or
> * the OpenPGP signature version
> none of that information is available in the human-readable output.

What this series wants to achieve makes a lot of sense to me.  One
comment I have after skimming the patfches is that I want the new
"raw" bit added not as a yet another parameter after "verbose", but
by turning the existing "verbose" into an "unsigned flag" flag word
(with "#define GPG_VERIFY_VERBOSE 01") and then defining use of a
new bit in the same flag word "#define GPG_VERIFY_RAW 01" or
something.  That way, over time other people add differnt things to
the interface, we would not have to end up with 47 different
parameters each of which signals a single bit.

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 7/7] bisect: allows any terms set by user

2015-06-14 Thread Antoine Delaite
This message's goal is to explained where am I on the bisect 
functions. 

-git bisect replay now work with any terms. 
-I took account of most of the last reviews (coding style, 
double sed ...)
-'git bisect terms' without arguments now display the current 
terms 
-bisect_terms : if a bisection has already started, a more 
verbose message is displayed 
-I solved a merge conflict in bisect.c due to the update of 
master branch. 

To submit a v3 I would need answer about how we rebase the commit 
history and what do we do to simplify the life of the user with the 
terms (see my last mails). 
I was thinking of: 
-a config variable that would say :"as long as I don't reset keep 
the terms of the previous bisection" 
or we could decided that this is the default behaviour of bisect. 

-two config variables to choose default terms 

I may have less time in the next days but I would like to submit a v3. 
--
To unsubscribe from this list: send the line "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 7/7] bisect: allows any terms set by user

2015-06-14 Thread Antoine Delaite
Matthieu Moy  writes:

>> +if test -s "$GIT_DIR/TERMS_DEFINED"
>> +then
>> +terms_defined=1
>> +get_terms
>> +rm -rf "$GIT_DIR/TERMS_DEFINED"
>
>I don't understand why you need to delete this file. I did not review
>thoroughly so there may be a reason, but you can help the reader with a
>comment here.

I will just complete Louis' answer. We delete it with backward
compatibility with old/new in mind (even if old/new is not merged yet).
For instance, after a old/new mode, if you do a 'bisect start rev1 rev2'
the mode would be bad/good ie the default mode. So if you defined your
terms, we decided it would only be for the following bisection. The next 
'bisect start rev1 rev2' would be in bad/good mode.
But this have to be discuted, do the user have to type 'git bisect terms'
each bisection if he wants to use special terms ?
--
To unsubscribe from this list: send the line "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 7/7] bisect: allows any terms set by user

2015-06-14 Thread Antoine Delaite
Louis Stuber  writes: 

>Matthieu Moy  writes: 
> 
>> Modifying in PATCH 7 some code that you introduced in PATCH 3 is 
>> suspicious. Is there any reason you did not name the variable 
>> "terms_defined" in the first place? (i.e. squash this hunk and the other 
>> instance of start_bad_good into PATCH 3) 
>> 
>> (Whether this is a rethorical question is up to you ;-) ) 
> 
>In the previouses versions where we only want to introduce old/new, 
>the terms can only be defined in bisect_start if the user typed 
>start  . The name "start_bad_good" is not very explicit 
>indeed, but isn't it more appropriate in this case than terms_defined ? 

I agree with Louis, but maybe a consistant commit history is more 
important. But if only the first patches (which implement old/new ) 
would come to be accepted the name of the variable would sounds strange. 

>> I don't understand why you need to delete this file. I did not review 
>> thoroughly so there may be a reason, but you can help the reader with a 
>> comment here. 
> 
>I think it's a mistake. I'd say we should put this test just before the 
>"bisect_clean_state || exit" line, but that would deserve more attention 
>indeed. The idea is to delete the file at the right moment because we 
>don't want it to exist again when the user starts an other bisection, 
>but also have an intelligent behaviour if the start command fails. 

Yes if the start commands fails, like if you gave wrong sha1, it would be 
nice not to have to type again 'git bisect terms ...' . There is no use to 
put it before clean_state because clean_state because clean_state will 
actually delete the file. So we can just let clean_state do this. 
--
To unsubscribe from this list: send the line "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/3] verify-commit: add option to print raw gpg status information

2015-06-14 Thread brian m. carlson
verify-commit by default displays human-readable output on standard
error.  However, it can also be useful to get access to the raw gpg
status information, which is machine-readable, allowing automated
implementation of signing policy.  Add a --raw option to make
verify-commit produce the gpg status information on standard error
instead of the human-readable format.

Signed-off-by: brian m. carlson 
---
 Documentation/git-verify-commit.txt |  4 
 builtin/verify-commit.c | 13 +++--
 t/t7510-signed-commit.sh| 32 
 3 files changed, 43 insertions(+), 6 deletions(-)

diff --git a/Documentation/git-verify-commit.txt 
b/Documentation/git-verify-commit.txt
index 9413e28..ecf4da1 100644
--- a/Documentation/git-verify-commit.txt
+++ b/Documentation/git-verify-commit.txt
@@ -16,6 +16,10 @@ Validates the gpg signature created by 'git commit -S'.
 
 OPTIONS
 ---
+--raw::
+   Print the raw gpg status output to standard error instead of the normal
+   human-readable output.
+
 -v::
 --verbose::
Print the contents of the commit object before validating it.
diff --git a/builtin/verify-commit.c b/builtin/verify-commit.c
index ec0c4e3..04646fc 100644
--- a/builtin/verify-commit.c
+++ b/builtin/verify-commit.c
@@ -18,7 +18,7 @@ static const char * const verify_commit_usage[] = {
NULL
 };
 
-static int run_gpg_verify(const unsigned char *sha1, const char *buf, unsigned 
long size, int verbose)
+static int run_gpg_verify(const unsigned char *sha1, const char *buf, unsigned 
long size, int verbose, int raw)
 {
struct signature_check signature_check;
 
@@ -30,13 +30,13 @@ static int run_gpg_verify(const unsigned char *sha1, const 
char *buf, unsigned l
fputs(signature_check.payload, stdout);
 
if (signature_check.gpg_output)
-   fputs(signature_check.gpg_output, stderr);
+   fputs(raw ? signature_check.gpg_status : 
signature_check.gpg_output, stderr);
 
signature_check_clear(&signature_check);
return signature_check.result != 'G';
 }
 
-static int verify_commit(const char *name, int verbose)
+static int verify_commit(const char *name, int verbose, int raw)
 {
enum object_type type;
unsigned char sha1[20];
@@ -54,7 +54,7 @@ static int verify_commit(const char *name, int verbose)
return error("%s: cannot verify a non-commit object of type 
%s.",
name, typename(type));
 
-   ret = run_gpg_verify(sha1, buf, size, verbose);
+   ret = run_gpg_verify(sha1, buf, size, verbose, raw);
 
free(buf);
return ret;
@@ -70,9 +70,10 @@ static int git_verify_commit_config(const char *var, const 
char *value, void *cb
 
 int cmd_verify_commit(int argc, const char **argv, const char *prefix)
 {
-   int i = 1, verbose = 0, had_error = 0;
+   int i = 1, verbose = 0, had_error = 0, raw = 0;
const struct option verify_commit_options[] = {
OPT__VERBOSE(&verbose, N_("print commit contents")),
+   OPT_BOOL(0, "raw", &raw, N_("print raw gpg status output")),
OPT_END()
};
 
@@ -87,7 +88,7 @@ int cmd_verify_commit(int argc, const char **argv, const char 
*prefix)
 * was received in the process of writing the gpg input: */
signal(SIGPIPE, SIG_IGN);
while (i < argc)
-   if (verify_commit(argv[i++], verbose))
+   if (verify_commit(argv[i++], verbose, raw))
had_error = 1;
return had_error;
 }
diff --git a/t/t7510-signed-commit.sh b/t/t7510-signed-commit.sh
index 13331e5..ef316f2 100755
--- a/t/t7510-signed-commit.sh
+++ b/t/t7510-signed-commit.sh
@@ -81,6 +81,38 @@ test_expect_success GPG 'verify and show signatures' '
)
 '
 
+test_expect_success GPG 'verify signatures with --raw' '
+   (
+   for commit in initial second merge fourth-signed fifth-signed 
sixth-signed seventh-signed
+   do
+   git verify-commit --raw $commit 2>actual &&
+   grep "GOODSIG" actual &&
+   ! grep "BADSIG" actual &&
+   echo $commit OK || exit 1
+   done
+   ) &&
+   (
+   for commit in merge^2 fourth-unsigned sixth-unsigned 
seventh-unsigned
+   do
+   test_must_fail git verify-commit --raw $commit 2>actual 
&&
+   ! grep "GOODSIG" actual &&
+   ! grep "BADSIG" actual &&
+   echo $commit OK || exit 1
+   done
+   ) &&
+   (
+   for commit in eighth-signed-alt
+   do
+   # Undefined trust causes verify-commit to exit 
abnormally.
+   test_must_fail git verify-commit --raw $commit 2>actual 
&&
+   grep "GOODSIG" actual &&
+  

[PATCH 0/3] Raw gpg output support for verify-commit and verify-tag

2015-06-14 Thread brian m. carlson
Currently, verify-commit and verify-tag produce human-readable output.
This is great for humans, and awful for machines.  It also lacks a lot
of the information that GnuPG's --status-fd output provides.

For example, if you wanted to know
* the hash algorithm;
* whether the signature was made with a subkey; or
* the OpenPGP signature version
none of that information is available in the human-readable output.

We've had people in the past come to the list who require signed commits
in their corporate environment.  It's not unreasonable to expect that
they might want to programmatically verify signatures, including aspects
of the signatures we don't currently expose.  It's also much nicer to
parse the machine-readable output we already collect than hoping GnuPG
doesn't change its output.

This series introduces a --raw option for verify-commit and verify-tag.
If it's used, they provide the gpg --status-fd output on standard error
instead of the human-readable output.  The series also adds tests for
verify-tag, since there were none; these are based off the ones for
verify-commit.

In writing this series, I noticed an incompatibility between
verify-commit and verify-tag.  If a valid signature is made with an
untrusted key, verify-commit will exit 1, but verify-tag will exit 0.
I'm unclear on what we can do about this now, short of adding another
option.  This is because the two commands share little common code.

brian m. carlson (3):
  verify-commit: add option to print raw gpg status information
  verify-tag: add tests
  verify-tag: add option to print raw gpg status information

 Documentation/git-verify-commit.txt |   4 ++
 Documentation/git-verify-tag.txt|   4 ++
 builtin/verify-commit.c |  13 ++--
 builtin/verify-tag.c|  21 +--
 t/t7030-verify-tag.sh   | 116 
 t/t7510-signed-commit.sh|  32 ++
 6 files changed, 178 insertions(+), 12 deletions(-)
 create mode 100755 t/t7030-verify-tag.sh

-- 
2.4.0

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


[PATCH 3/3] verify-tag: add option to print raw gpg status information

2015-06-14 Thread brian m. carlson
verify-tag by default displays human-readable output on standard error.
However, it can also be useful to get access to the raw gpg status
information, which is machine-readable, allowing automated
implementation of signing policy.  Add a --raw option to make verify-tag
produce the gpg status information on standard error instead of the
human-readable format.

Signed-off-by: brian m. carlson 
---
 Documentation/git-verify-tag.txt |  4 
 builtin/verify-tag.c | 21 +++--
 t/t7030-verify-tag.sh| 31 +++
 3 files changed, 50 insertions(+), 6 deletions(-)

diff --git a/Documentation/git-verify-tag.txt b/Documentation/git-verify-tag.txt
index f88ba96..d590edc 100644
--- a/Documentation/git-verify-tag.txt
+++ b/Documentation/git-verify-tag.txt
@@ -16,6 +16,10 @@ Validates the gpg signature created by 'git tag'.
 
 OPTIONS
 ---
+--raw::
+   Print the raw gpg status output to standard error instead of the normal
+   human-readable output.
+
 -v::
 --verbose::
Print the contents of the tag object before validating it.
diff --git a/builtin/verify-tag.c b/builtin/verify-tag.c
index 53c68fc..745c013 100644
--- a/builtin/verify-tag.c
+++ b/builtin/verify-tag.c
@@ -18,9 +18,12 @@ static const char * const verify_tag_usage[] = {
NULL
 };
 
-static int run_gpg_verify(const char *buf, unsigned long size, int verbose)
+static int run_gpg_verify(const char *buf, unsigned long size, int verbose, 
int raw)
 {
+   struct strbuf status = STRBUF_INIT, human_readable = STRBUF_INIT;
+   const struct strbuf *output = raw ? &status : &human_readable;
int len;
+   int ret;
 
len = parse_signature(buf, size);
if (verbose)
@@ -29,10 +32,15 @@ static int run_gpg_verify(const char *buf, unsigned long 
size, int verbose)
if (size == len)
return error("no signature found");
 
-   return verify_signed_buffer(buf, len, buf + len, size - len, NULL, 
NULL);
+   ret = verify_signed_buffer(buf, len, buf + len, size - len, 
&human_readable,
+   &status);
+
+   fputs(output->buf, stderr);
+
+   return ret;
 }
 
-static int verify_tag(const char *name, int verbose)
+static int verify_tag(const char *name, int verbose, int raw)
 {
enum object_type type;
unsigned char sha1[20];
@@ -52,7 +60,7 @@ static int verify_tag(const char *name, int verbose)
if (!buf)
return error("%s: unable to read file.", name);
 
-   ret = run_gpg_verify(buf, size, verbose);
+   ret = run_gpg_verify(buf, size, verbose, raw);
 
free(buf);
return ret;
@@ -68,9 +76,10 @@ static int git_verify_tag_config(const char *var, const char 
*value, void *cb)
 
 int cmd_verify_tag(int argc, const char **argv, const char *prefix)
 {
-   int i = 1, verbose = 0, had_error = 0;
+   int i = 1, verbose = 0, had_error = 0, raw = 0;
const struct option verify_tag_options[] = {
OPT__VERBOSE(&verbose, N_("print tag contents")),
+   OPT_BOOL(0, "raw", &raw, N_("print raw gpg status output")),
OPT_END()
};
 
@@ -85,7 +94,7 @@ int cmd_verify_tag(int argc, const char **argv, const char 
*prefix)
 * was received in the process of writing the gpg input: */
signal(SIGPIPE, SIG_IGN);
while (i < argc)
-   if (verify_tag(argv[i++], verbose))
+   if (verify_tag(argv[i++], verbose, raw))
had_error = 1;
return had_error;
 }
diff --git a/t/t7030-verify-tag.sh b/t/t7030-verify-tag.sh
index 9ca0d29..0ac15e6 100755
--- a/t/t7030-verify-tag.sh
+++ b/t/t7030-verify-tag.sh
@@ -82,4 +82,35 @@ test_expect_success GPG 'verify and show signatures' '
)
 '
 
+test_expect_success GPG 'verify signatures with --raw' '
+   (
+   for tag in initial second merge fourth-signed sixth-signed 
seventh-signed
+   do
+   git verify-tag --raw $tag 2>actual &&
+   grep "GOODSIG" actual &&
+   ! grep "BADSIG" actual &&
+   echo $tag OK || exit 1
+   done
+   ) &&
+   (
+   for tag in fourth-unsigned fifth-unsigned sixth-unsigned
+   do
+   test_must_fail git verify-tag --raw $tag 2>actual &&
+   ! grep "GOODSIG" actual &&
+   ! grep "BADSIG" actual &&
+   echo $tag OK || exit 1
+   done
+   ) &&
+   (
+   for tag in eighth-signed-alt
+   do
+   git verify-tag --raw $tag 2>actual &&
+   grep "GOODSIG" actual &&
+   ! grep "BADSIG" actual &&
+   grep "TRUST_UNDEFINED" actual &&
+   echo $tag OK || exit 1
+   done
+   )
+'
+
 test_done
-- 
2.4

[PATCH 2/3] verify-tag: add tests

2015-06-14 Thread brian m. carlson
verify-tag was lacking tests.  Add some, mirroring those used for
verify-commit.

Signed-off-by: brian m. carlson 
---
 t/t7030-verify-tag.sh | 85 +++
 1 file changed, 85 insertions(+)
 create mode 100755 t/t7030-verify-tag.sh

diff --git a/t/t7030-verify-tag.sh b/t/t7030-verify-tag.sh
new file mode 100755
index 000..9ca0d29
--- /dev/null
+++ b/t/t7030-verify-tag.sh
@@ -0,0 +1,85 @@
+#!/bin/sh
+
+test_description='signed tag tests'
+. ./test-lib.sh
+. "$TEST_DIRECTORY/lib-gpg.sh"
+
+test_expect_success GPG 'create signed tags' '
+   echo 1 >file && git add file &&
+   test_tick && git commit -m initial &&
+   git tag -s -m initial initial &&
+   git branch side &&
+   echo a &&
+
+   echo 2 >file && test_tick && git commit -a -m second &&
+   git tag -s -m second second &&
+   echo b &&
+
+   git checkout side &&
+   echo 3 >elif && git add elif &&
+   test_tick && git commit -m "third on side" &&
+   echo c &&
+
+   git checkout master &&
+   test_tick && git merge -S side &&
+   git tag -s -m merge merge &&
+   echo d &&
+
+   echo 4 >file && test_tick && git commit -a -S -m "fourth unsigned" &&
+   git tag -a -m fourth-unsigned fourth-unsigned &&
+   echo e &&
+
+   test_tick && git commit --amend -S -m "fourth signed" &&
+   git tag -s -m fourth fourth-signed &&
+   echo f &&
+
+   echo 5 >file && test_tick && git commit -a -m "fifth" &&
+   git tag fifth-unsigned &&
+   echo g &&
+
+   git config commit.gpgsign true &&
+   echo 6 >file && test_tick && git commit -a -m "sixth" &&
+   git tag -a -m sixth sixth-unsigned &&
+   echo h &&
+
+   test_tick && git rebase -f HEAD^^ && git tag -s -m 6th sixth-signed 
HEAD^ &&
+   git tag -m seventh -s seventh-signed &&
+   echo i &&
+
+   echo 8 >file && test_tick && git commit -a -m eighth &&
+   git tag -uB7227189 -m eighth eighth-signed-alt &&
+   echo j
+'
+
+test_expect_success GPG 'verify and show signatures' '
+   (
+   for tag in initial second merge fourth-signed sixth-signed 
seventh-signed
+   do
+   git verify-tag $tag 2>actual &&
+   grep "Good signature from" actual &&
+   ! grep "BAD signature from" actual &&
+   echo $tag OK || exit 1
+   done
+   ) &&
+   (
+   for tag in fourth-unsigned fifth-unsigned sixth-unsigned
+   do
+   test_must_fail git verify-tag $tag 2>actual &&
+   ! grep "Good signature from" actual &&
+   ! grep "BAD signature from" actual &&
+   echo $tag OK || exit 1
+   done
+   ) &&
+   (
+   for tag in eighth-signed-alt
+   do
+   git verify-tag $tag 2>actual &&
+   grep "Good signature from" actual &&
+   ! grep "BAD signature from" actual &&
+   grep "not certified" actual &&
+   echo $tag OK || exit 1
+   done
+   )
+'
+
+test_done
-- 
2.4.0

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


[ANNOUNCE] git-multimail 1.1.0-rc1

2015-06-14 Thread Matthieu Moy
Hi,

I'm happy to announce the first release candidate of git-multimail 1.1.

git-multimail is a tool to send notification emails for pushes to a git
repository. It can be downloaded from
https://github.com/git-multimail/git-multimail (the release itself can
be seen here: https://github.com/git-multimail/git-multimail/releases ).

The main new features are:

* When a single commit is pushed, omit the reference changed email.
  Set multimailhook.combineWhenSingleCommit to false to disable this
  new feature.

* In gitolite environments, the pusher's email address can be used as
  the From address by creating a specially formatted comment block in
  gitolite.conf (see multimailhook.from in README).

* Support for SMTP authentication and SSL/TLS encryption was added,
  see smtpUser, smtpPass, smtpEncryption in README.

* A new option scanCommitForCc was added to allow git-multimail to
  search the commit message for 'Cc: ...' lines, and add the
  corresponding emails in Cc.

* If $USER is not set, use the variable $USERNAME. This is needed on
  Windows platform to recognize the pusher.

* The emailPrefix variable can now be set to an empty string to remove
  the prefix.

* A short tutorial was added in doc/gitolite.rst to set up
  git-multimail with gitolite.

* The post-receive file was renamed to post-receive.example. It has
  always been an example (the standard way to call git-multimail is to
  call git_multimail.py), but it was unclear to many users.

* A new refchangeShowGraph option was added to make it possible to
  include both a graph and a log in the summary emails.  The options
  to control the graph formatting can be set via the new graphOpts
  option.

Internally, I've improved the testing system (plug travis-ci.org on the
GitHub repository, check PEP8 conformance in the code and RST on the
README). Hopefully, I didn't break too many things ;-).

Next on the roadmap:

* There's a long standing pull request (#52) to allow filtering out some
  refs. We still need to figure out what the best way to do this is.

* Once this is done, there are other pull requests on top of this to
  support Atlassian Stash and Gerrit.

* At some point, we'll need to start supporting Python 3.x, but I'd
  rather focus on features for now.

Please, test, report bugs, send patches ... and have fun!

-- 
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 v7 2/5] setup: sanity check file size in read_gitfile_gently

2015-06-14 Thread erik elfström
On Sun, Jun 14, 2015 at 5:42 AM, Eric Sunshine  wrote:
>
> This variable name doesn't convey much about its purpose, and
> introduces a bit of maintenance burden if the limit is some day
> changed. Perhaps "sane_size_limit" or something even more descriptive
> (and/or terse) would be better.
>

Would you be happy with this change?

-   static const int one_MB = 1 << 20;
+   static const int max_file_size = 1 << 20;  /* 1MB */
--
To unsubscribe from this list: send the line "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: reverse history tree, for faster & background clones

2015-06-14 Thread Andres G. Aragoneses

On 12/06/15 14:33, Dennis Kaarsemaker wrote:

On vr, 2015-06-12 at 13:39 +0200, Andres G. Aragoneses wrote:

On 12/06/15 13:33, Dennis Kaarsemaker wrote:

On vr, 2015-06-12 at 13:26 +0200, Andres G. Aragoneses wrote:


AFAIU git stores the contents of a repo as a sequence of patches in the
.git metadata folder.


It does not, it stores full snapshots of files.


In bare repos too?


Yes. A bare repo is nothing more than the .git dir of a non-bare repo
with the core.bare variable set to True :)


1. `git clone --depth 1` would be way faster, and without the need of
on-demand compressing of packfiles in the server side, correct me if I'm
wrong?


You're wrong due to the misunderstanding of how git works :)


Thanks for pointing this out, do you mind giving me a link of some docs
where I can correct my knowledge about this?


http://git-scm.com/book/en/v2/Git-Internals-Git-Objects should help.


Wow, now I wonder if I should also propose a change to make git 
optionally not store the full snapshots, so save disk space. Thanks for 
pointing this out to me.




2. `git clone` would be able to allow a "fast operation, complete in the
background" mode that would allow you to download the first snapshot of
the repo very quickly, so that the user would be able to start working
on his working directory very quickly, while a "background job" keeps
retreiving the history data in the background.


This could actually be a good thing, and can be emulated now with git
clone --depth=1 and subsequent fetches in the background to deepen the
history. I can see some value in clone doing this by itself, first doing
a depth=1 fetch, then launching itself into the background, giving you a
worktree to play with earlier.


You're right, didn't think about the feature that converts a --depth=1
repo to a normal one. Then a patch that would create a --progressive
flag (for instance, didn't think of a better name yet) for the `clone`
command would actually be trivial to create, I assume, because it would
just use `depth=1` and then retrieve the rest of the history in the
background, right?


A naive implementation that does just clone --depth=1 and then fetch
--unshallow would probably not be too hard, no. But whether that would
be the 'right' way of implementing it, I wouldn't know.


Ok, anyone else that can give an insight here?

I imagine that I would not get real feedback until I send a [PATCH]...

I guess I would use a user-facing message like this one:

Finished cloning the last snapshot of the repository.
Auto downloading the rest of the history in background.

(Since there's already a similar "background" feature already wrt 
auto-packing the repository: `Auto packing the repository in background 
for optimum performance. See "git help gc" for manual housekeeping.`.)


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


[GIT PULL] l10n updates for 2.4 maint branch

2015-06-14 Thread Jiang Xin
The following changes since commit 9eabf5b536662000f79978c4d1b6e4eff5c8d785:

  Git 2.4.2 (2015-05-26 13:49:59 -0700)

are available in the git repository at:

  git://github.com/git-l10n/git-po tags/l10n-2.4-maint-de-updates

for you to fetch changes up to a9845c5f504498644abcb5f6fd6adc2ffd076f2b:

  l10n: de.po: translation fix for fall-back to 3way merge (2015-06-12
20:40:04 +0200)


l10n-2.4-maint-de-updates


Michael J Gruber (3):
  l10n: de.po: grammar fix
  l10n: de.po: punctuation fixes
  l10n: de.po: translation fix for fall-back to 3way merge

Phillip Sz (1):
  l10n: de.po: change error message from "sagen" to "Meinten Sie"

 po/de.po | 10 +-
 1 file changed, 5 insertions(+), 5 deletions(-)

--
Jiang Xin
--
To unsubscribe from this list: send the line "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] pathspec: adjust prefixlen after striping trailing slash

2015-06-14 Thread Duy Nguyen
On Thu, Apr 23, 2015 at 10:47 AM, Junio C Hamano  wrote:
> On Wed, Apr 22, 2015 at 3:32 PM, Jens Lehmann  wrote:
>> ...
>>> But it is unclear if we should still do (2) when "subrepo/.git" is
>>> no longer there.  That has to be done manually and it may be an
>>> indication that is clear enough that the end user wants the
>>> directory to be a normal directory without any submodule involved,
>>> in which case it may match the expectation of the user better to
>>> just nuke the corresponding 16 entry in the index and replace it
>>> with files in there.  I dunno.
>>
>> The user having removed subrepo/.git is just one reason for that.
>> Another is a user adding a file in an unpopulated work tree of a
>> not initialized submodule. I doubt that simply nuking the 16
>> entry would be the right thing to do in this case, I expect this
>> to be a pilot error we should barf about ;-)
>
> OK, that sounds sensible.

There are more to this "submodule vs the world". When .git is gone, if
you expect to warn instead of deleting 16. You may want the same
for the opposite direction: when b/c is in the index and you add
b/.git, you may want "git add b" to complain too (right not it ignores
b/.git and updates b/c).

We may need more surgery around this area. It seems to be the "Path %s
is in submodule" check (in pathspec.c) is at the wrong place. We have
d/f check in add_index_entry_with_check. That should catch it, at the
core, not from call sites like add or update-index. But that check is
not active...

The first version of "path is in submodule" is in 2ce53f9 (git add: do
not add files from a submodule - 2009-01-02). Back then dir.c does not
intervene. If you have "b" as 16 in the index and tries to add
b/c, the ok_to_replace feature kicks in and kills 'b'. This is why d/f
check is turned off. This ok_to_replace is to deal with symlinks, see
192268c (Add git-update-cache --replace option. - 2005-05-07).

I think we should stop the ok-to-replace feature when submodules are
involved, we consider submdules much more valuable than symlinks. If
we do this, I think we can delete those "Path is in submodule" trick
becaue the index core can handle it well.
-- 
Duy
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2 7/7] bisect: allows any terms set by user

2015-06-14 Thread Louis-Alexandre Stuber
Matthieu Moy  writes:

> Modifying in PATCH 7 some code that you introduced in PATCH 3 is
> suspicious. Is there any reason you did not name the variable
> "terms_defined" in the first place? (i.e. squash this hunk and the other
> instance of start_bad_good into PATCH 3)
>
> (Whether this is a rethorical question is up to you ;-) )

In the previouses versions where we only want to introduce old/new,
the terms can only be defined in bisect_start if the user typed
start  . The name "start_bad_good" is not very explicit
indeed, but isn't it more appropriate in this case than terms_defined ?

> I don't understand why you need to delete this file. I did not review
> thoroughly so there may be a reason, but you can help the reader with a
> comment here.

I think it's a mistake. I'd say we should put this test just before the
"bisect_clean_state || exit" line, but that would deserve more attention
indeed. The idea is to delete the file at the right moment because we 
don't want it to exist again when the user starts an other bisection,
but also have an intelligent behaviour if the start command fails.



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


Re: [PATCH v2 4/7] bisect: add the terms old/new

2015-06-14 Thread Louis-Alexandre Stuber
I agree this makes no sense hardcoding old/new once bisect terms is
considerred. It would have been a lot better if we had started
implementing bisect terms immediatly (but we thought old/new would
already be an appreciable step for most of users).
--
To unsubscribe from this list: send the line "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: Failed assertion in pathspec.c

2015-06-14 Thread Duy Nguyen
On Sun, Jun 14, 2015 at 5:21 PM, Sami Boukortt  wrote:
>> On Sun, Jun 14, 2015 at 12:18 AM, Sami Boukortt
>>  wrote:
>> > git: pathspec.c:317: prefix_pathspec: Assertion
>> > `item->nowildcard_len <= item->len && item->prefix <= item->len'
>> > failed.
>>
>> Known issue, but no one stepped up to fix it yet
>>
>> http://thread.gmane.org/gmane.comp.version-control.git/267095
>
> Oh, I see. Sorry for the duplicate report.

No, it's actually good. It reminded me about this bug again. Maybe
I'll do something about it :)
-- 
Duy
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: Failed assertion in pathspec.c

2015-06-14 Thread Sami Boukortt
> On Sun, Jun 14, 2015 at 12:18 AM, Sami Boukortt
>  wrote:
> > git: pathspec.c:317: prefix_pathspec: Assertion
> > `item->nowildcard_len <= item->len && item->prefix <= item->len'
> > failed.
> 
> Known issue, but no one stepped up to fix it yet
> 
> http://thread.gmane.org/gmane.comp.version-control.git/267095

Oh, I see. Sorry for the duplicate report.
--
To unsubscribe from this list: send the line "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 12/19] pull: fast-forward working tree if head is updated

2015-06-14 Thread Paul Tan
Since b10ac50 (Fix pulling into the same branch., 2005-08-25), git-pull,
upon detecting that git-fetch updated the current head, will
fast-forward the working tree to the updated head commit.

Re-implement this behavior.

Signed-off-by: Paul Tan 
---
 builtin/pull.c | 30 ++
 1 file changed, 30 insertions(+)

diff --git a/builtin/pull.c b/builtin/pull.c
index cb5898a..0e48a14 100644
--- a/builtin/pull.c
+++ b/builtin/pull.c
@@ -412,6 +412,7 @@ int cmd_pull(int argc, const char **argv, const char 
*prefix)
 {
const char *repo, **refspecs;
struct sha1_array merge_heads = SHA1_ARRAY_INIT;
+   unsigned char orig_head[GIT_SHA1_RAWSZ], curr_head[GIT_SHA1_RAWSZ];
 
if (!getenv("_GIT_USE_BUILTIN_PULL")) {
const char *path = mkpath("%s/git-pull", git_exec_path());
@@ -435,12 +436,41 @@ int cmd_pull(int argc, const char **argv, const char 
*prefix)
if (file_exists(git_path("MERGE_HEAD")))
die_conclude_merge();
 
+   if (get_sha1("HEAD", orig_head))
+   hashclr(orig_head);
+
if (run_fetch(repo, refspecs))
return 1;
 
if (opt_dry_run)
return 0;
 
+   if (get_sha1("HEAD", curr_head))
+   hashclr(curr_head);
+
+   if (!is_null_sha1(orig_head) && !is_null_sha1(curr_head) &&
+   hashcmp(orig_head, curr_head)) {
+   /*
+* The fetch involved updating the current branch.
+*
+* The working tree and the index file are still based on
+* orig_head commit, but we are merging into curr_head.
+* Update the working tree to match curr_head.
+*/
+
+   warning(_("fetch updated the current branch head.\n"
+   "fast-forwarding your working tree from\n"
+   "commit %s."), sha1_to_hex(orig_head));
+
+   if (checkout_fast_forward(orig_head, curr_head, 0))
+   die(_("Cannot fast-forward your working tree.\n"
+   "After making sure that you saved anything 
precious from\n"
+   "$ git diff %s\n"
+   "output, run\n"
+   "$ git reset --hard\n"
+   "to recover."), sha1_to_hex(orig_head));
+   }
+
get_merge_heads(&merge_heads);
 
if (!merge_heads.nr)
-- 
2.1.4

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


[PATCH v3 13/19] pull: implement pulling into an unborn branch

2015-06-14 Thread Paul Tan
b4dc085 (pull: merge into unborn by fast-forwarding from empty
tree, 2013-06-20) established git-pull's current behavior of pulling
into an unborn branch by fast-forwarding the work tree from an empty
tree to the merge head, then setting HEAD to the merge head.

Re-implement this behavior by introducing pull_into_void() which will be
called instead of run_merge() if HEAD is invalid.

Helped-by: Stephen Robin 
Signed-off-by: Paul Tan 
---

Notes:
v3

* style fixes

 builtin/pull.c | 29 -
 1 file changed, 28 insertions(+), 1 deletion(-)

diff --git a/builtin/pull.c b/builtin/pull.c
index 0e48a14..a2dd0ba 100644
--- a/builtin/pull.c
+++ b/builtin/pull.c
@@ -13,6 +13,7 @@
 #include "sha1-array.h"
 #include "remote.h"
 #include "dir.h"
+#include "refs.h"
 
 static const char * const pull_usage[] = {
N_("git pull [options] [ [...]]"),
@@ -368,6 +369,27 @@ static int run_fetch(const char *repo, const char 
**refspecs)
 }
 
 /**
+ * "Pulls into void" by branching off merge_head.
+ */
+static int pull_into_void(const unsigned char *merge_head,
+   const unsigned char *curr_head)
+{
+   /*
+* Two-way merge: we treat the index as based on an empty tree,
+* and try to fast-forward to HEAD. This ensures we will not lose
+* index/worktree changes that the user already made on the unborn
+* branch.
+*/
+   if (checkout_fast_forward(EMPTY_TREE_SHA1_BIN, merge_head, 0))
+   return 1;
+
+   if (update_ref("initial pull", "HEAD", merge_head, curr_head, 0, 
UPDATE_REFS_DIE_ON_ERR))
+   return 1;
+
+   return 0;
+}
+
+/**
  * Runs git-merge, returning its exit status.
  */
 static int run_merge(void)
@@ -476,5 +498,10 @@ int cmd_pull(int argc, const char **argv, const char 
*prefix)
if (!merge_heads.nr)
die_no_merge_candidates(repo, refspecs);
 
-   return run_merge();
+   if (is_null_sha1(orig_head)) {
+   if (merge_heads.nr > 1)
+   die(_("Cannot merge multiple branches into empty 
head."));
+   return pull_into_void(*merge_heads.sha1, curr_head);
+   } else
+   return run_merge();
 }
-- 
2.1.4

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


[PATCH v3 17/19] pull --rebase: exit early when the working directory is dirty

2015-06-14 Thread Paul Tan
Re-implement the behavior introduced by f9189cf (pull --rebase: exit
early when the working directory is dirty, 2008-05-21).

Signed-off-by: Paul Tan 
---
 builtin/pull.c | 77 +-
 1 file changed, 76 insertions(+), 1 deletion(-)

diff --git a/builtin/pull.c b/builtin/pull.c
index e4098d0..a379c1f 100644
--- a/builtin/pull.c
+++ b/builtin/pull.c
@@ -14,6 +14,8 @@
 #include "remote.h"
 #include "dir.h"
 #include "refs.h"
+#include "revision.h"
+#include "lockfile.h"
 
 enum rebase_type {
REBASE_INVALID = -1,
@@ -295,6 +297,73 @@ static enum rebase_type config_get_rebase(void)
 }
 
 /**
+ * Returns 1 if there are unstaged changes, 0 otherwise.
+ */
+static int has_unstaged_changes(const char *prefix)
+{
+   struct rev_info rev_info;
+   int result;
+
+   init_revisions(&rev_info, prefix);
+   DIFF_OPT_SET(&rev_info.diffopt, IGNORE_SUBMODULES);
+   DIFF_OPT_SET(&rev_info.diffopt, QUICK);
+   diff_setup_done(&rev_info.diffopt);
+   result = run_diff_files(&rev_info, 0);
+   return diff_result_code(&rev_info.diffopt, result);
+}
+
+/**
+ * Returns 1 if there are uncommitted changes, 0 otherwise.
+ */
+static int has_uncommitted_changes(const char *prefix)
+{
+   struct rev_info rev_info;
+   int result;
+
+   if (is_cache_unborn())
+   return 0;
+
+   init_revisions(&rev_info, prefix);
+   DIFF_OPT_SET(&rev_info.diffopt, IGNORE_SUBMODULES);
+   DIFF_OPT_SET(&rev_info.diffopt, QUICK);
+   add_head_to_pending(&rev_info);
+   diff_setup_done(&rev_info.diffopt);
+   result = run_diff_index(&rev_info, 1);
+   return diff_result_code(&rev_info.diffopt, result);
+}
+
+/**
+ * If the work tree has unstaged or uncommitted changes, dies with the
+ * appropriate message.
+ */
+static void die_on_unclean_work_tree(const char *prefix)
+{
+   struct lock_file *lock_file = xcalloc(1, sizeof(*lock_file));
+   int do_die = 0;
+
+   hold_locked_index(lock_file, 0);
+   refresh_cache(REFRESH_QUIET);
+   update_index_if_able(&the_index, lock_file);
+   rollback_lock_file(lock_file);
+
+   if (has_unstaged_changes(prefix)) {
+   error(_("Cannot pull with rebase: You have unstaged changes."));
+   do_die = 1;
+   }
+
+   if (has_uncommitted_changes(prefix)) {
+   if (do_die)
+   error(_("Additionally, your index contains uncommitted 
changes."));
+   else
+   error(_("Cannot pull with rebase: Your index contains 
uncommitted changes."));
+   do_die = 1;
+   }
+
+   if (do_die)
+   exit(1);
+}
+
+/**
  * Appends merge candidates from FETCH_HEAD that are not marked not-for-merge
  * into merge_heads.
  */
@@ -750,9 +819,15 @@ int cmd_pull(int argc, const char **argv, const char 
*prefix)
if (get_sha1("HEAD", orig_head))
hashclr(orig_head);
 
-   if (opt_rebase)
+   if (opt_rebase) {
+   if (is_null_sha1(orig_head) && !is_cache_unborn())
+   die(_("Updating an unborn branch with changes added to 
the index."));
+
+   die_on_unclean_work_tree(prefix);
+
if (get_rebase_fork_point(rebase_fork_point, repo, *refspecs))
hashclr(rebase_fork_point);
+   }
 
if (run_fetch(repo, refspecs))
return 1;
-- 
2.1.4

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


[PATCH v3 19/19] pull: remove redirection to git-pull.sh

2015-06-14 Thread Paul Tan
At the beginning of the rewrite of git-pull.sh to C, we introduced a
redirection to git-pull.sh if the environment variable
_GIT_USE_BUILTIN_PULL was not defined in order to not break test scripts
that relied on a functional git-pull.

Now that all of git-pull's functionality has been re-implemented in
builtin/pull.c, remove this redirection, and retire the old git-pull.sh
into contrib/examples/.

Signed-off-by: Paul Tan 
---
 Makefile| 1 -
 builtin/pull.c  | 7 ---
 git-pull.sh => contrib/examples/git-pull.sh | 0
 3 files changed, 8 deletions(-)
 rename git-pull.sh => contrib/examples/git-pull.sh (100%)

diff --git a/Makefile b/Makefile
index 2057a9d..67cef1c 100644
--- a/Makefile
+++ b/Makefile
@@ -474,7 +474,6 @@ SCRIPT_SH += git-merge-octopus.sh
 SCRIPT_SH += git-merge-one-file.sh
 SCRIPT_SH += git-merge-resolve.sh
 SCRIPT_SH += git-mergetool.sh
-SCRIPT_SH += git-pull.sh
 SCRIPT_SH += git-quiltimport.sh
 SCRIPT_SH += git-rebase.sh
 SCRIPT_SH += git-remote-testgit.sh
diff --git a/builtin/pull.c b/builtin/pull.c
index b78c67c..d690aee 100644
--- a/builtin/pull.c
+++ b/builtin/pull.c
@@ -797,13 +797,6 @@ int cmd_pull(int argc, const char **argv, const char 
*prefix)
unsigned char orig_head[GIT_SHA1_RAWSZ], curr_head[GIT_SHA1_RAWSZ];
unsigned char rebase_fork_point[GIT_SHA1_RAWSZ];
 
-   if (!getenv("_GIT_USE_BUILTIN_PULL")) {
-   const char *path = mkpath("%s/git-pull", git_exec_path());
-
-   if (sane_execvp(path, (char **)argv) < 0)
-   die_errno("could not exec %s", path);
-   }
-
if (!getenv("GIT_REFLOG_ACTION"))
set_reflog_message(argc, argv);
 
diff --git a/git-pull.sh b/contrib/examples/git-pull.sh
similarity index 100%
rename from git-pull.sh
rename to contrib/examples/git-pull.sh
-- 
2.1.4

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


[PATCH v3 15/19] pull: teach git pull about --rebase

2015-06-14 Thread Paul Tan
Since cd67e4d (Teach 'git pull' about --rebase, 2007-11-28), if the
--rebase option is set, git-rebase is run instead of git-merge.

Re-implement this by introducing run_rebase(), which is called instead
of run_merge() if opt_rebase is a true value.

Since c85c792 (pull --rebase: be cleverer with rebased upstream
branches, 2008-01-26), git-pull handles the case where the upstream
branch was rebased since it was last fetched. The fork point (old remote
ref) of the branch from the upstream branch is calculated before fetch,
and then rebased from onto the new remote head (merge_head) after fetch.

Re-implement this by introducing get_merge_branch_2() and
get_merge_branch_1() to find the upstream branch for the
specified/current branch, and get_rebase_fork_point() which will find
the fork point between the upstream branch and current branch.

However, the above change created a problem where git-rebase cannot
detect commits that are already upstream, and thus may result in
unnecessary conflicts. cf65426 (pull --rebase: Avoid spurious conflicts
and reapplying unnecessary patches, 2010-08-12) fixes this by ignoring
the above old remote ref if it is contained within the merge base of the
merge head and the current branch.

This is re-implemented in run_rebase() where fork_point is not used if
it is the merge base returned by get_octopus_merge_base().

Helped-by: Stefan Beller 
Helped-by: Johannes Schindelin 
Signed-off-by: Paul Tan 
---

Notes:
v3

* use branch_get_upstream()

* style fixes

* adjust to removal of branch->remote in 9e3751d (remote.c: drop
  "remote" pointer from "struct branch", 2015-05-21)

* I realised that if parse_config_rebase() handled the die()-ing and
  error()-ing, it would make the next patch more pleasant.

 builtin/pull.c | 247 -
 1 file changed, 245 insertions(+), 2 deletions(-)

diff --git a/builtin/pull.c b/builtin/pull.c
index a2c900e..8915947 100644
--- a/builtin/pull.c
+++ b/builtin/pull.c
@@ -15,6 +15,53 @@
 #include "dir.h"
 #include "refs.h"
 
+enum rebase_type {
+   REBASE_INVALID = -1,
+   REBASE_FALSE = 0,
+   REBASE_TRUE,
+   REBASE_PRESERVE
+};
+
+/**
+ * Parses the value of --rebase. If value is a false value, returns
+ * REBASE_FALSE. If value is a true value, returns REBASE_TRUE. If value is
+ * "preserve", returns REBASE_PRESERVE. If value is a invalid value, dies with
+ * a fatal error if fatal is true, otherwise returns REBASE_INVALID.
+ */
+static enum rebase_type parse_config_rebase(const char *key, const char *value,
+   int fatal)
+{
+   int v = git_config_maybe_bool("pull.rebase", value);
+
+   if (!v)
+   return REBASE_FALSE;
+   else if (v > 0)
+   return REBASE_TRUE;
+   else if (!strcmp(value, "preserve"))
+   return REBASE_PRESERVE;
+
+   if (fatal)
+   die(_("Invalid value for %s: %s"), key, value);
+   else
+   error(_("Invalid value for %s: %s"), key, value);
+
+   return REBASE_INVALID;
+}
+
+/**
+ * Callback for --rebase, which parses arg with parse_config_rebase().
+ */
+static int parse_opt_rebase(const struct option *opt, const char *arg, int 
unset)
+{
+   enum rebase_type *value = opt->value;
+
+   if (arg)
+   *value = parse_config_rebase("--rebase", arg, 0);
+   else
+   *value = unset ? REBASE_FALSE : REBASE_TRUE;
+   return *value == REBASE_INVALID ? -1 : 0;
+}
+
 static const char * const pull_usage[] = {
N_("git pull [options] [ [...]]"),
NULL
@@ -24,7 +71,8 @@ static const char * const pull_usage[] = {
 static int opt_verbosity;
 static char *opt_progress;
 
-/* Options passed to git-merge */
+/* Options passed to git-merge or git-rebase */
+static enum rebase_type opt_rebase;
 static char *opt_diffstat;
 static char *opt_log;
 static char *opt_squash;
@@ -58,8 +106,12 @@ static struct option pull_options[] = {
N_("force progress reporting"),
PARSE_OPT_NOARG),
 
-   /* Options passed to git-merge */
+   /* Options passed to git-merge or git-rebase */
OPT_GROUP(N_("Options related to merging")),
+   { OPTION_CALLBACK, 'r', "rebase", &opt_rebase,
+ N_("false|true|preserve"),
+ N_("incorporate changes by rebasing rather than merging"),
+ PARSE_OPT_OPTARG, parse_opt_rebase },
OPT_PASSTHRU('n', NULL, &opt_diffstat, NULL,
N_("do not show a diffstat at the end of the merge"),
PARSE_OPT_NOARG | PARSE_OPT_NONEG),
@@ -449,11 +501,194 @@ static int run_merge(void)
return ret;
 }
 
+/**
+ * Returns remote's upstream branch for the current branch. If remote is NULL,
+ * the current branch's configured default remote is used. Returns NULL if
+ * `remote` does not name a valid remote, HEAD does not point to a branch,
+ * remote is not the branch's configured remote

[PATCH v3 07/19] pull: pass git-merge's options to git-merge

2015-06-14 Thread Paul Tan
Specify git-merge's options in the option list, and pass any specified
options to git-merge.

These options are:

* -n, --stat, --summary: since d8abe14 (merge, pull: introduce
  '--(no-)stat' option, 2008-04-06)

* --log: since efb779f (merge, pull: add '--(no-)log' command line
  option, 2008-04-06)

* --squash: since 7d0c688 (git-merge --squash, 2006-06-23)

* --commit: since 5072a32 (Teach git-pull about --[no-]ff, --no-squash
  and --commit, 2007-10-29)

* --edit: since 8580830 ("git pull" doesn't know "--edit", 2012-02-11)

* --ff, --ff-only: since 5072a32 (Teach git-pull about --[no-]ff,
  --no-squash and --commit, 2007-10-29)

* --verify-signatures: since efed002 (merge/pull: verify GPG signatures
  of commits being merged, 2013-03-31)

* -s, --strategy: since 60fb5b2 (Use git-merge in git-pull (second
  try)., 2005-09-25)

* -X, --strategy-option: since ee2c795 (Teach git-pull to pass
  -X to git-merge, 2009-11-25)

* -S, --gpg-sign: since ea230d8 (pull: add the --gpg-sign option.,
  2014-02-10)

Signed-off-by: Paul Tan 
---
 builtin/pull.c | 75 ++
 1 file changed, 75 insertions(+)

diff --git a/builtin/pull.c b/builtin/pull.c
index 5d9f2b5..0442da9 100644
--- a/builtin/pull.c
+++ b/builtin/pull.c
@@ -20,6 +20,18 @@ static const char * const pull_usage[] = {
 static int opt_verbosity;
 static char *opt_progress;
 
+/* Options passed to git-merge */
+static char *opt_diffstat;
+static char *opt_log;
+static char *opt_squash;
+static char *opt_commit;
+static char *opt_edit;
+static char *opt_ff;
+static char *opt_verify_signatures;
+static struct argv_array opt_strategies = ARGV_ARRAY_INIT;
+static struct argv_array opt_strategy_opts = ARGV_ARRAY_INIT;
+static char *opt_gpg_sign;
+
 static struct option pull_options[] = {
/* Shared options */
OPT__VERBOSITY(&opt_verbosity),
@@ -27,6 +39,49 @@ static struct option pull_options[] = {
N_("force progress reporting"),
PARSE_OPT_NOARG),
 
+   /* Options passed to git-merge */
+   OPT_GROUP(N_("Options related to merging")),
+   OPT_PASSTHRU('n', NULL, &opt_diffstat, NULL,
+   N_("do not show a diffstat at the end of the merge"),
+   PARSE_OPT_NOARG | PARSE_OPT_NONEG),
+   OPT_PASSTHRU(0, "stat", &opt_diffstat, NULL,
+   N_("show a diffstat at the end of the merge"),
+   PARSE_OPT_NOARG),
+   OPT_PASSTHRU(0, "summary", &opt_diffstat, NULL,
+   N_("(synonym to --stat)"),
+   PARSE_OPT_NOARG | PARSE_OPT_HIDDEN),
+   OPT_PASSTHRU(0, "log", &opt_log, N_("n"),
+   N_("add (at most ) entries from shortlog to merge commit 
message"),
+   PARSE_OPT_OPTARG),
+   OPT_PASSTHRU(0, "squash", &opt_squash, NULL,
+   N_("create a single commit instead of doing a merge"),
+   PARSE_OPT_NOARG),
+   OPT_PASSTHRU(0, "commit", &opt_commit, NULL,
+   N_("perform a commit if the merge succeeds (default)"),
+   PARSE_OPT_NOARG),
+   OPT_PASSTHRU(0, "edit", &opt_edit, NULL,
+   N_("edit message before committing"),
+   PARSE_OPT_NOARG),
+   OPT_PASSTHRU(0, "ff", &opt_ff, NULL,
+   N_("allow fast-forward"),
+   PARSE_OPT_NOARG),
+   OPT_PASSTHRU(0, "ff-only", &opt_ff, NULL,
+   N_("abort if fast-forward is not possible"),
+   PARSE_OPT_NOARG | PARSE_OPT_NONEG),
+   OPT_PASSTHRU(0, "verify-signatures", &opt_verify_signatures, NULL,
+   N_("verify that the named commit has a valid GPG signature"),
+   PARSE_OPT_NOARG),
+   OPT_PASSTHRU_ARGV('s', "strategy", &opt_strategies, N_("strategy"),
+   N_("merge strategy to use"),
+   0),
+   OPT_PASSTHRU_ARGV('X', "strategy-option", &opt_strategy_opts,
+   N_("option=value"),
+   N_("option for selected merge strategy"),
+   0),
+   OPT_PASSTHRU('S', "gpg-sign", &opt_gpg_sign, N_("key-id"),
+   N_("GPG sign commit"),
+   PARSE_OPT_OPTARG),
+
OPT_END()
 };
 
@@ -101,6 +156,26 @@ static int run_merge(void)
if (opt_progress)
argv_array_push(&args, opt_progress);
 
+   /* Options passed to git-merge */
+   if (opt_diffstat)
+   argv_array_push(&args, opt_diffstat);
+   if (opt_log)
+   argv_array_push(&args, opt_log);
+   if (opt_squash)
+   argv_array_push(&args, opt_squash);
+   if (opt_commit)
+   argv_array_push(&args, opt_commit);
+   if (opt_edit)
+   argv_array_push(&args, opt_edit);
+   if (opt_ff)
+   argv_array_push(&args, opt_ff);
+   if (opt_verify_signatures)
+   argv_array_push(&args, opt_verify_signatures);
+   argv_array_pushv(&args, opt_strategies.argv);
+   argv_array_pushv(&args, opt_strategy_o

[PATCH v3 16/19] pull: configure --rebase via branch..rebase or pull.rebase

2015-06-14 Thread Paul Tan
Since cd67e4d (Teach 'git pull' about --rebase, 2007-11-28),
fetch+rebase could be set by default by defining the config variable
branch..rebase. This setting can be overriden on the command line
by --rebase and --no-rebase.

Since 6b37dff (pull: introduce a pull.rebase option to enable --rebase,
2011-11-06), git-pull --rebase can also be configured via the
pull.rebase configuration option.

Re-implement support for these two configuration settings by introducing
config_get_rebase() which is called before parse_options() to set the
default value of opt_rebase.

Helped-by: Stefan Beller 
Signed-off-by: Paul Tan 
---

Notes:
v3

* Now that parse_config_rebase() takes care of the die()-ing and
  error()-ing, we only need one function again. Yay!

* The free()s is ugly though. Ideally, I would like to have a xstrfmt()
  function that returns a static buffer.

* We now don't lookup the pull.rebase config if the --rebase option is
  provided on the command-line.

 builtin/pull.c | 34 +-
 1 file changed, 33 insertions(+), 1 deletion(-)

diff --git a/builtin/pull.c b/builtin/pull.c
index 8915947..e4098d0 100644
--- a/builtin/pull.c
+++ b/builtin/pull.c
@@ -72,7 +72,7 @@ static int opt_verbosity;
 static char *opt_progress;
 
 /* Options passed to git-merge or git-rebase */
-static enum rebase_type opt_rebase;
+static enum rebase_type opt_rebase = -1;
 static char *opt_diffstat;
 static char *opt_log;
 static char *opt_squash;
@@ -266,6 +266,35 @@ static const char *config_get_ff(void)
 }
 
 /**
+ * Returns the default configured value for --rebase. It first looks for the
+ * value of "branch.$curr_branch.rebase", where $curr_branch is the current
+ * branch, and if HEAD is detached or the configuration key does not exist,
+ * looks for the value of "pull.rebase". If both configuration keys do not
+ * exist, returns REBASE_FALSE.
+ */
+static enum rebase_type config_get_rebase(void)
+{
+   struct branch *curr_branch = branch_get("HEAD");
+   const char *value;
+
+   if (curr_branch) {
+   char *key = xstrfmt("branch.%s.rebase", curr_branch->name);
+
+   if (!git_config_get_value(key, &value)) {
+   free(key);
+   return parse_config_rebase(key, value, 1);
+   }
+
+   free(key);
+   }
+
+   if (!git_config_get_value("pull.rebase", &value))
+   return parse_config_rebase("pull.rebase", value, 1);
+
+   return REBASE_FALSE;
+}
+
+/**
  * Appends merge candidates from FETCH_HEAD that are not marked not-for-merge
  * into merge_heads.
  */
@@ -707,6 +736,9 @@ int cmd_pull(int argc, const char **argv, const char 
*prefix)
if (!opt_ff)
opt_ff = xstrdup_or_null(config_get_ff());
 
+   if (opt_rebase < 0)
+   opt_rebase = config_get_rebase();
+
git_config(git_default_config, NULL);
 
if (read_cache_unmerged())
-- 
2.1.4

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


[PATCH v3 14/19] pull: set reflog message

2015-06-14 Thread Paul Tan
f947413 (Use GIT_REFLOG_ACTION environment variable instead.,
2006-12-28) established git-pull's method for setting the reflog
message, which is to set the environment variable GIT_REFLOG_ACTION to
the evaluation of "pull${1+ $*}" if it has not already been set.

Re-implement this behavior.

Helped-by: Junio C Hamano 
Signed-off-by: Paul Tan 
---
 builtin/pull.c | 22 ++
 1 file changed, 22 insertions(+)

diff --git a/builtin/pull.c b/builtin/pull.c
index a2dd0ba..a2c900e 100644
--- a/builtin/pull.c
+++ b/builtin/pull.c
@@ -169,6 +169,25 @@ static void argv_push_force(struct argv_array *arr)
 }
 
 /**
+ * Sets the GIT_REFLOG_ACTION environment variable to the concatenation of argv
+ */
+static void set_reflog_message(int argc, const char **argv)
+{
+   int i;
+   struct strbuf msg = STRBUF_INIT;
+
+   for (i = 0; i < argc; i++) {
+   if (i)
+   strbuf_addch(&msg, ' ');
+   strbuf_addstr(&msg, argv[i]);
+   }
+
+   setenv("GIT_REFLOG_ACTION", msg.buf, 0);
+
+   strbuf_release(&msg);
+}
+
+/**
  * If pull.ff is unset, returns NULL. If pull.ff is "true", returns "--ff". If
  * pull.ff is "false", returns "--no-ff". If pull.ff is "only", returns
  * "--ff-only". Otherwise, if pull.ff is set to an invalid value, die with an
@@ -443,6 +462,9 @@ int cmd_pull(int argc, const char **argv, const char 
*prefix)
die_errno("could not exec %s", path);
}
 
+   if (!getenv("GIT_REFLOG_ACTION"))
+   set_reflog_message(argc, argv);
+
argc = parse_options(argc, argv, prefix, pull_options, pull_usage, 0);
 
parse_repo_refspecs(argc, argv, &repo, &refspecs);
-- 
2.1.4

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


[PATCH v3 18/19] pull --rebase: error on no merge candidate cases

2015-06-14 Thread Paul Tan
Tweak the error messages printed by die_no_merge_candidates() to take
into account that we may be "rebasing against" rather than "merging
with".

Signed-off-by: Paul Tan 
---
 builtin/pull.c | 15 ---
 1 file changed, 12 insertions(+), 3 deletions(-)

diff --git a/builtin/pull.c b/builtin/pull.c
index a379c1f..b78c67c 100644
--- a/builtin/pull.c
+++ b/builtin/pull.c
@@ -430,7 +430,10 @@ static void NORETURN die_no_merge_candidates(const char 
*repo, const char **refs
const char *remote = curr_branch ? curr_branch->remote_name : NULL;
 
if (*refspecs) {
-   fprintf_ln(stderr, _("There are no candidates for merging among 
the refs that you just fetched."));
+   if (opt_rebase)
+   fprintf_ln(stderr, _("There is no candidate for 
rebasing against among the refs that you just fetched."));
+   else
+   fprintf_ln(stderr, _("There are no candidates for 
merging among the refs that you just fetched."));
fprintf_ln(stderr, _("Generally this means that you provided a 
wildcard refspec which had no\n"
"matches on the remote end."));
} else if (repo && curr_branch && (!remote || strcmp(repo, remote))) {
@@ -440,7 +443,10 @@ static void NORETURN die_no_merge_candidates(const char 
*repo, const char **refs
repo);
} else if (!curr_branch) {
fprintf_ln(stderr, _("You are not currently on a branch."));
-   fprintf_ln(stderr, _("Please specify which branch you want to 
merge with."));
+   if (opt_rebase)
+   fprintf_ln(stderr, _("Please specify which branch you 
want to rebase against."));
+   else
+   fprintf_ln(stderr, _("Please specify which branch you 
want to merge with."));
fprintf_ln(stderr, _("See git-pull(1) for details."));
fprintf(stderr, "\n");
fprintf_ln(stderr, "git pull  ");
@@ -452,7 +458,10 @@ static void NORETURN die_no_merge_candidates(const char 
*repo, const char **refs
remote_name = "";
 
fprintf_ln(stderr, _("There is no tracking information for the 
current branch."));
-   fprintf_ln(stderr, _("Please specify which branch you want to 
merge with."));
+   if (opt_rebase)
+   fprintf_ln(stderr, _("Please specify which branch you 
want to rebase against."));
+   else
+   fprintf_ln(stderr, _("Please specify which branch you 
want to merge with."));
fprintf_ln(stderr, _("See git-pull(1) for details."));
fprintf(stderr, "\n");
fprintf_ln(stderr, "git pull  ");
-- 
2.1.4

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


[PATCH v3 08/19] pull: pass git-fetch's options to git-fetch

2015-06-14 Thread Paul Tan
Since eb2a8d9 (pull: handle git-fetch's options as well, 2015-06-02),
git-pull knows about and handles git-fetch's options, passing them to
git-fetch. Re-implement this behavior.

Since 29609e6 (pull: do nothing on --dry-run, 2010-05-25) git-pull
supported the --dry-run option, exiting after git-fetch if --dry-run is
set. Re-implement this behavior.

Signed-off-by: Paul Tan 
---
 builtin/pull.c | 95 ++
 1 file changed, 95 insertions(+)

diff --git a/builtin/pull.c b/builtin/pull.c
index 0442da9..731e2a6 100644
--- a/builtin/pull.c
+++ b/builtin/pull.c
@@ -32,6 +32,21 @@ static struct argv_array opt_strategies = ARGV_ARRAY_INIT;
 static struct argv_array opt_strategy_opts = ARGV_ARRAY_INIT;
 static char *opt_gpg_sign;
 
+/* Options passed to git-fetch */
+static char *opt_all;
+static char *opt_append;
+static char *opt_upload_pack;
+static int opt_force;
+static char *opt_tags;
+static char *opt_prune;
+static char *opt_recurse_submodules;
+static int opt_dry_run;
+static char *opt_keep;
+static char *opt_depth;
+static char *opt_unshallow;
+static char *opt_update_shallow;
+static char *opt_refmap;
+
 static struct option pull_options[] = {
/* Shared options */
OPT__VERBOSITY(&opt_verbosity),
@@ -82,6 +97,46 @@ static struct option pull_options[] = {
N_("GPG sign commit"),
PARSE_OPT_OPTARG),
 
+   /* Options passed to git-fetch */
+   OPT_GROUP(N_("Options related to fetching")),
+   OPT_PASSTHRU(0, "all", &opt_all, 0,
+   N_("fetch from all remotes"),
+   PARSE_OPT_NOARG),
+   OPT_PASSTHRU('a', "append", &opt_append, 0,
+   N_("append to .git/FETCH_HEAD instead of overwriting"),
+   PARSE_OPT_NOARG),
+   OPT_PASSTHRU(0, "upload-pack", &opt_upload_pack, N_("path"),
+   N_("path to upload pack on remote end"),
+   0),
+   OPT__FORCE(&opt_force, N_("force overwrite of local branch")),
+   OPT_PASSTHRU('t', "tags", &opt_tags, 0,
+   N_("fetch all tags and associated objects"),
+   PARSE_OPT_NOARG),
+   OPT_PASSTHRU('p', "prune", &opt_prune, 0,
+   N_("prune remote-tracking branches no longer on remote"),
+   PARSE_OPT_NOARG),
+   OPT_PASSTHRU(0, "recurse-submodules", &opt_recurse_submodules,
+   N_("on-demand"),
+   N_("control recursive fetching of submodules"),
+   PARSE_OPT_OPTARG),
+   OPT_BOOL(0, "dry-run", &opt_dry_run,
+   N_("dry run")),
+   OPT_PASSTHRU('k', "keep", &opt_keep, 0,
+   N_("keep downloaded pack"),
+   PARSE_OPT_NOARG),
+   OPT_PASSTHRU(0, "depth", &opt_depth, N_("depth"),
+   N_("deepen history of shallow clone"),
+   0),
+   OPT_PASSTHRU(0, "unshallow", &opt_unshallow, 0,
+   N_("convert to a complete repository"),
+   PARSE_OPT_NONEG | PARSE_OPT_NOARG),
+   OPT_PASSTHRU(0, "update-shallow", &opt_update_shallow, 0,
+   N_("accept refs that update .git/shallow"),
+   PARSE_OPT_NOARG),
+   OPT_PASSTHRU(0, "refmap", &opt_refmap, N_("refmap"),
+   N_("specify fetch refmap"),
+   PARSE_OPT_NONEG),
+
OPT_END()
 };
 
@@ -100,6 +155,16 @@ static void argv_push_verbosity(struct argv_array *arr)
 }
 
 /**
+ * Pushes "-f" switches into arr to match the opt_force level.
+ */
+static void argv_push_force(struct argv_array *arr)
+{
+   int force = opt_force;
+   while (force-- > 0)
+   argv_array_push(arr, "-f");
+}
+
+/**
  * Parses argv into [ [...]], returning their values in `repo`
  * as a string and `refspecs` as a null-terminated array of strings. If `repo`
  * is not provided in argv, it is set to NULL.
@@ -131,6 +196,33 @@ static int run_fetch(const char *repo, const char 
**refspecs)
if (opt_progress)
argv_array_push(&args, opt_progress);
 
+   /* Options passed to git-fetch */
+   if (opt_all)
+   argv_array_push(&args, opt_all);
+   if (opt_append)
+   argv_array_push(&args, opt_append);
+   if (opt_upload_pack)
+   argv_array_push(&args, opt_upload_pack);
+   argv_push_force(&args);
+   if (opt_tags)
+   argv_array_push(&args, opt_tags);
+   if (opt_prune)
+   argv_array_push(&args, opt_prune);
+   if (opt_recurse_submodules)
+   argv_array_push(&args, opt_recurse_submodules);
+   if (opt_dry_run)
+   argv_array_push(&args, "--dry-run");
+   if (opt_keep)
+   argv_array_push(&args, opt_keep);
+   if (opt_depth)
+   argv_array_push(&args, opt_depth);
+   if (opt_unshallow)
+   argv_array_push(&args, opt_unshallow);
+   if (opt_update_shallow)
+   argv_array_push(&args, opt_update_shallow);
+   if (opt_refmap

[PATCH v3 10/19] pull: support pull.ff config

2015-06-14 Thread Paul Tan
Since b814da8 (pull: add pull.ff configuration, 2014-01-15), git-pull.sh
would lookup the configuration value of "pull.ff", and set the flag
"--ff" if its value is "true", "--no-ff" if its value is "false" and
"--ff-only" if its value is "only".

Re-implement this behavior.

Signed-off-by: Paul Tan 
---

Notes:
v3

* style fixes

 builtin/pull.c | 29 +
 1 file changed, 29 insertions(+)

diff --git a/builtin/pull.c b/builtin/pull.c
index 83691fc..0ddb964 100644
--- a/builtin/pull.c
+++ b/builtin/pull.c
@@ -167,6 +167,32 @@ static void argv_push_force(struct argv_array *arr)
 }
 
 /**
+ * If pull.ff is unset, returns NULL. If pull.ff is "true", returns "--ff". If
+ * pull.ff is "false", returns "--no-ff". If pull.ff is "only", returns
+ * "--ff-only". Otherwise, if pull.ff is set to an invalid value, die with an
+ * error.
+ */
+static const char *config_get_ff(void)
+{
+   const char *value;
+
+   if (git_config_get_value("pull.ff", &value))
+   return NULL;
+
+   switch (git_config_maybe_bool("pull.ff", value)) {
+   case 0:
+   return "--no-ff";
+   case 1:
+   return "--ff";
+   }
+
+   if (!strcmp(value, "only"))
+   return "--ff-only";
+
+   die(_("Invalid value for pull.ff: %s"), value);
+}
+
+/**
  * Appends merge candidates from FETCH_HEAD that are not marked not-for-merge
  * into merge_heads.
  */
@@ -397,6 +423,9 @@ int cmd_pull(int argc, const char **argv, const char 
*prefix)
 
parse_repo_refspecs(argc, argv, &repo, &refspecs);
 
+   if (!opt_ff)
+   opt_ff = xstrdup_or_null(config_get_ff());
+
if (run_fetch(repo, refspecs))
return 1;
 
-- 
2.1.4

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


[PATCH v3 05/19] pull: implement fetch + merge

2015-06-14 Thread Paul Tan
Implement the fetch + merge functionality of git-pull, by first running
git-fetch with the repo and refspecs provided on the command line, then
running git-merge on FETCH_HEAD to merge the fetched refs into the
current branch.

Helped-by: Junio C Hamano 
Signed-off-by: Paul Tan 
---

Notes:
v3

* Catch bug where there is are refspecs but no repo.

 builtin/pull.c | 62 +-
 1 file changed, 61 insertions(+), 1 deletion(-)

diff --git a/builtin/pull.c b/builtin/pull.c
index cabeed4..9157536 100644
--- a/builtin/pull.c
+++ b/builtin/pull.c
@@ -9,8 +9,10 @@
 #include "builtin.h"
 #include "parse-options.h"
 #include "exec_cmd.h"
+#include "run-command.h"
 
 static const char * const pull_usage[] = {
+   N_("git pull [options] [ [...]]"),
NULL
 };
 
@@ -18,8 +20,61 @@ static struct option pull_options[] = {
OPT_END()
 };
 
+/**
+ * Parses argv into [ [...]], returning their values in `repo`
+ * as a string and `refspecs` as a null-terminated array of strings. If `repo`
+ * is not provided in argv, it is set to NULL.
+ */
+static void parse_repo_refspecs(int argc, const char **argv, const char **repo,
+   const char ***refspecs)
+{
+   if (argc > 0) {
+   *repo = *argv++;
+   argc--;
+   } else
+   *repo = NULL;
+   *refspecs = argv;
+}
+
+/**
+ * Runs git-fetch, returning its exit status. `repo` and `refspecs` are the
+ * repository and refspecs to fetch, or NULL if they are not provided.
+ */
+static int run_fetch(const char *repo, const char **refspecs)
+{
+   struct argv_array args = ARGV_ARRAY_INIT;
+   int ret;
+
+   argv_array_pushl(&args, "fetch", "--update-head-ok", NULL);
+   if (repo) {
+   argv_array_push(&args, repo);
+   argv_array_pushv(&args, refspecs);
+   } else if (*refspecs)
+   die("BUG: refspecs without repo?");
+   ret = run_command_v_opt(args.argv, RUN_GIT_CMD);
+   argv_array_clear(&args);
+   return ret;
+}
+
+/**
+ * Runs git-merge, returning its exit status.
+ */
+static int run_merge(void)
+{
+   int ret;
+   struct argv_array args = ARGV_ARRAY_INIT;
+
+   argv_array_pushl(&args, "merge", NULL);
+   argv_array_push(&args, "FETCH_HEAD");
+   ret = run_command_v_opt(args.argv, RUN_GIT_CMD);
+   argv_array_clear(&args);
+   return ret;
+}
+
 int cmd_pull(int argc, const char **argv, const char *prefix)
 {
+   const char *repo, **refspecs;
+
if (!getenv("_GIT_USE_BUILTIN_PULL")) {
const char *path = mkpath("%s/git-pull", git_exec_path());
 
@@ -29,5 +84,10 @@ int cmd_pull(int argc, const char **argv, const char *prefix)
 
argc = parse_options(argc, argv, prefix, pull_options, pull_usage, 0);
 
-   return 0;
+   parse_repo_refspecs(argc, argv, &repo, &refspecs);
+
+   if (run_fetch(repo, refspecs))
+   return 1;
+
+   return run_merge();
 }
-- 
2.1.4

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


[PATCH v3 03/19] argv-array: implement argv_array_pushv()

2015-06-14 Thread Paul Tan
When we have a null-terminated array, it would be useful to convert it
or append it to an argv_array for further manipulation.

Implement argv_array_pushv() which will push a null-terminated array of
strings on to an argv_array.

Signed-off-by: Paul Tan 
---
 Documentation/technical/api-argv-array.txt | 3 +++
 argv-array.c   | 6 ++
 argv-array.h   | 1 +
 3 files changed, 10 insertions(+)

diff --git a/Documentation/technical/api-argv-array.txt 
b/Documentation/technical/api-argv-array.txt
index 1a79781..8076172 100644
--- a/Documentation/technical/api-argv-array.txt
+++ b/Documentation/technical/api-argv-array.txt
@@ -46,6 +46,9 @@ Functions
Format a string and push it onto the end of the array. This is a
convenience wrapper combining `strbuf_addf` and `argv_array_push`.
 
+`argv_array_pushv`::
+   Push a null-terminated array of strings onto the end of the array.
+
 `argv_array_pop`::
Remove the final element from the array. If there are no
elements in the array, do nothing.
diff --git a/argv-array.c b/argv-array.c
index 256741d..eaed477 100644
--- a/argv-array.c
+++ b/argv-array.c
@@ -49,6 +49,12 @@ void argv_array_pushl(struct argv_array *array, ...)
va_end(ap);
 }
 
+void argv_array_pushv(struct argv_array *array, const char **argv)
+{
+   for (; *argv; argv++)
+   argv_array_push(array, *argv);
+}
+
 void argv_array_pop(struct argv_array *array)
 {
if (!array->argc)
diff --git a/argv-array.h b/argv-array.h
index c65e6e8..a2fa0aa 100644
--- a/argv-array.h
+++ b/argv-array.h
@@ -17,6 +17,7 @@ __attribute__((format (printf,2,3)))
 void argv_array_pushf(struct argv_array *, const char *fmt, ...);
 LAST_ARG_MUST_BE_NULL
 void argv_array_pushl(struct argv_array *, ...);
+void argv_array_pushv(struct argv_array *, const char **);
 void argv_array_pop(struct argv_array *);
 void argv_array_clear(struct argv_array *);
 
-- 
2.1.4

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


[PATCH v3 01/19] parse-options-cb: implement parse_opt_passthru()

2015-06-14 Thread Paul Tan
Certain git commands, such as git-pull, are simply wrappers around other
git commands like git-fetch, git-merge and git-rebase. As such, these
wrapper commands will typically need to "pass through" command-line
options of the commands they wrap.

Implement the parse_opt_passthru() parse-options callback, which will
reconstruct the command-line option into an char* string, such that it
can be passed to another git command.

Helped-by: Johannes Schindelin 
Helped-by: Junio C Hamano 
Helped-by: Stefan Beller 
Signed-off-by: Paul Tan 
---

Notes:
v3

* Reverted back to returning newly-allocated strings. Junio raised the
  concern that it may not be such a good idea to burden the users of the
  API to always use X.buf to access the string. Personally I believe
  that memory management safety is usually more important, but I don't
  have strong feelings about this.

* Extracted out the "option reconstruction" logic into a private
  function so that it can be shared with parse_opt_passthru_argv() in
  the next patch.

* Introduced the OPT_PASSTHRU() macro and documented it in
  Documentation/technical/api-parse-options.txt. This macro relieves the
  user of having to specify OPTION_CALLBACK and parse_opt_passthru() for
  every option.

* The function used to be named parse_opt_pass_strbuf() to save
  horizontal space, but then again parse_opt_passthru() is probably a
  better name.

* Added comment to the docstring that the callback should only be used
  for options where the last one wins.

 Documentation/technical/api-parse-options.txt |  7 
 parse-options-cb.c| 49 +++
 parse-options.h   |  3 ++
 3 files changed, 59 insertions(+)

diff --git a/Documentation/technical/api-parse-options.txt 
b/Documentation/technical/api-parse-options.txt
index 1f2db31..85d10ab 100644
--- a/Documentation/technical/api-parse-options.txt
+++ b/Documentation/technical/api-parse-options.txt
@@ -212,6 +212,13 @@ There are some macros to easily define options:
Use it to hide deprecated options that are still to be recognized
and ignored silently.
 
+`OPT_PASSTHRU(short, long, &char_var, arg_str, description, flags)`::
+   Introduce an option that will be reconstructed into a char* string,
+   which must be initialized to NULL. This is useful when you need to
+   pass the command-line option to another command. Any previous value
+   will be overwritten, so this should only be used for options where
+   the last one specified on the command line wins.
+
 
 The last element of the array must be `OPT_END()`.
 
diff --git a/parse-options-cb.c b/parse-options-cb.c
index be8c413..68bc593 100644
--- a/parse-options-cb.c
+++ b/parse-options-cb.c
@@ -134,3 +134,52 @@ int parse_opt_noop_cb(const struct option *opt, const char 
*arg, int unset)
 {
return 0;
 }
+
+/**
+ * Recreates the command-line option in the strbuf.
+ */
+static int recreate_opt(struct strbuf *sb, const struct option *opt,
+   const char *arg, int unset)
+{
+   strbuf_reset(sb);
+
+   if (opt->long_name) {
+   strbuf_addstr(sb, unset ? "--no-" : "--");
+   strbuf_addstr(sb, opt->long_name);
+   if (arg) {
+   strbuf_addch(sb, '=');
+   strbuf_addstr(sb, arg);
+   }
+   } else if (opt->short_name && !unset) {
+   strbuf_addch(sb, '-');
+   strbuf_addch(sb, opt->short_name);
+   if (arg)
+   strbuf_addstr(sb, arg);
+   } else
+   return -1;
+
+   return 0;
+}
+
+/**
+ * For an option opt, recreates the command-line option in opt->value which
+ * must be an char* initialized to NULL. This is useful when we need to pass
+ * the command-line option to another command. Since any previous value will be
+ * overwritten, this callback should only be used for options where the last
+ * one wins.
+ */
+int parse_opt_passthru(const struct option *opt, const char *arg, int unset)
+{
+   static struct strbuf sb = STRBUF_INIT;
+   char **opt_value = opt->value;
+
+   if (recreate_opt(&sb, opt, arg, unset) < 0)
+   return -1;
+
+   if (*opt_value)
+   free(*opt_value);
+
+   *opt_value = strbuf_detach(&sb, NULL);
+
+   return 0;
+}
diff --git a/parse-options.h b/parse-options.h
index c71e9da..5b0f886 100644
--- a/parse-options.h
+++ b/parse-options.h
@@ -224,6 +224,7 @@ extern int parse_opt_with_commit(const struct option *, 
const char *, int);
 extern int parse_opt_tertiary(const struct option *, const char *, int);
 extern int parse_opt_string_list(const struct option *, const char *, int);
 extern int parse_opt_noop_cb(const struct option *, const char *, int);
+extern int parse_opt_passthru(const struct option *, const char *, int);
 
 #def

[PATCH v3 09/19] pull: error on no merge candidates

2015-06-14 Thread Paul Tan
Commit a8c9bef (pull: improve advice for unconfigured error case,
2009-10-05) fully established the current advices given by git-pull for
the different cases where git-fetch will not have anything marked for
merge:

1. We fetched from a specific remote, and a refspec was given, but it
   ended up not fetching anything. This is usually because the user
   provided a wildcard refspec which had no matches on the remote end.

2. We fetched from a non-default remote, but didn't specify a branch to
   merge. We can't use the configured one because it applies to the
   default remote, and thus the user must specify the branches to merge.

3. We fetched from the branch's or repo's default remote, but:

   a. We are not on a branch, so there will never be a configured branch
  to merge with.

   b. We are on a branch, but there is no configured branch to merge
  with.

4. We fetched from the branch's or repo's default remote, but the
   configured branch to merge didn't get fetched (either it doesn't
   exist, or wasn't part of the configured fetch refspec)

Re-implement the above behavior by implementing get_merge_heads() to
parse the heads in FETCH_HEAD for merging, and implementing
die_no_merge_candidates(), which will be called when FETCH_HEAD has no
heads for merging.

Helped-by: Johannes Schindelin 
Helped-by: Junio C Hamano 
Signed-off-by: Paul Tan 
---

Notes:
v3

* Tightening up of FETCH_HEAD parsing code and style fixes.

 builtin/pull.c | 113 +
 1 file changed, 113 insertions(+)

diff --git a/builtin/pull.c b/builtin/pull.c
index 731e2a6..83691fc 100644
--- a/builtin/pull.c
+++ b/builtin/pull.c
@@ -10,6 +10,8 @@
 #include "parse-options.h"
 #include "exec_cmd.h"
 #include "run-command.h"
+#include "sha1-array.h"
+#include "remote.h"
 
 static const char * const pull_usage[] = {
N_("git pull [options] [ [...]]"),
@@ -165,6 +167,111 @@ static void argv_push_force(struct argv_array *arr)
 }
 
 /**
+ * Appends merge candidates from FETCH_HEAD that are not marked not-for-merge
+ * into merge_heads.
+ */
+static void get_merge_heads(struct sha1_array *merge_heads)
+{
+   const char *filename = git_path("FETCH_HEAD");
+   FILE *fp;
+   struct strbuf sb = STRBUF_INIT;
+   unsigned char sha1[GIT_SHA1_RAWSZ];
+
+   if (!(fp = fopen(filename, "r")))
+   die_errno(_("could not open '%s' for reading"), filename);
+   while (strbuf_getline(&sb, fp, '\n') != EOF) {
+   if (get_sha1_hex(sb.buf, sha1))
+   continue;  /* invalid line: does not start with SHA1 */
+   if (starts_with(sb.buf + GIT_SHA1_HEXSZ, "\tnot-for-merge\t"))
+   continue;  /* ref is not-for-merge */
+   sha1_array_append(merge_heads, sha1);
+   }
+   fclose(fp);
+   strbuf_release(&sb);
+}
+
+/**
+ * Used by die_no_merge_candidates() as a for_each_remote() callback to
+ * retrieve the name of the remote if the repository only has one remote.
+ */
+static int get_only_remote(struct remote *remote, void *cb_data)
+{
+   const char **remote_name = cb_data;
+
+   if (*remote_name)
+   return -1;
+
+   *remote_name = remote->name;
+   return 0;
+}
+
+/**
+ * Dies with the appropriate reason for why there are no merge candidates:
+ *
+ * 1. We fetched from a specific remote, and a refspec was given, but it ended
+ *up not fetching anything. This is usually because the user provided a
+ *wildcard refspec which had no matches on the remote end.
+ *
+ * 2. We fetched from a non-default remote, but didn't specify a branch to
+ *merge. We can't use the configured one because it applies to the default
+ *remote, thus the user must specify the branches to merge.
+ *
+ * 3. We fetched from the branch's or repo's default remote, but:
+ *
+ *a. We are not on a branch, so there will never be a configured branch to
+ *   merge with.
+ *
+ *b. We are on a branch, but there is no configured branch to merge with.
+ *
+ * 4. We fetched from the branch's or repo's default remote, but the configured
+ *branch to merge didn't get fetched. (Either it doesn't exist, or wasn't
+ *part of the configured fetch refspec.)
+ */
+static void NORETURN die_no_merge_candidates(const char *repo, const char 
**refspecs)
+{
+   struct branch *curr_branch = branch_get("HEAD");
+   const char *remote = curr_branch ? curr_branch->remote_name : NULL;
+
+   if (*refspecs) {
+   fprintf_ln(stderr, _("There are no candidates for merging among 
the refs that you just fetched."));
+   fprintf_ln(stderr, _("Generally this means that you provided a 
wildcard refspec which had no\n"
+   "matches on the remote end."));
+   } else if (repo && curr_branch && (!remote || strcmp(repo, remote))) {
+   fprintf_ln(stderr, _("You asked to pull from the remote

[PATCH v3 02/19] parse-options-cb: implement parse_opt_passthru_argv()

2015-06-14 Thread Paul Tan
Certain git commands, such as git-pull, are simply wrappers around other
git commands like git-fetch, git-merge and git-rebase. As such, these
wrapper commands will typically need to "pass through" command-line
options of the commands they wrap.

Implement the parse_opt_passthru_argv() parse-options callback, which
will reconstruct all the provided command-line options into an
argv_array, such that it can be passed to another git command. This is
useful for passing command-line options that can be specified multiple
times.

Helped-by: Stefan Beller 
Signed-off-by: Paul Tan 
---

Notes:
v3

* Renamed function to the more descriptive parse_opt_passthru_argv().

* Introduced and documented OPT_PASSTHRU_ARGV() macro, which saves the
  user from having to specify OPTION_CALLBACK and
  parse_opt_passthru_argv() for each option.

 Documentation/technical/api-parse-options.txt |  6 ++
 parse-options-cb.c| 20 
 parse-options.h   |  3 +++
 3 files changed, 29 insertions(+)

diff --git a/Documentation/technical/api-parse-options.txt 
b/Documentation/technical/api-parse-options.txt
index 85d10ab..0b0ab01 100644
--- a/Documentation/technical/api-parse-options.txt
+++ b/Documentation/technical/api-parse-options.txt
@@ -219,6 +219,12 @@ There are some macros to easily define options:
will be overwritten, so this should only be used for options where
the last one specified on the command line wins.
 
+`OPT_PASSTHRU_ARGV(short, long, &argv_array_var, arg_str, description, 
flags)`::
+   Introduce an option where all instances of it on the command-line will
+   be reconstructed into an argv_array. This is useful when you need to
+   pass the command-line option, which can be specified multiple times,
+   to another command.
+
 
 The last element of the array must be `OPT_END()`.
 
diff --git a/parse-options-cb.c b/parse-options-cb.c
index 68bc593..5ab6ed6 100644
--- a/parse-options-cb.c
+++ b/parse-options-cb.c
@@ -4,6 +4,7 @@
 #include "commit.h"
 #include "color.h"
 #include "string-list.h"
+#include "argv-array.h"
 
 /*- some often used options -*/
 
@@ -183,3 +184,22 @@ int parse_opt_passthru(const struct option *opt, const 
char *arg, int unset)
 
return 0;
 }
+
+/**
+ * For an option opt, recreate the command-line option, appending it to
+ * opt->value which must be a argv_array. This is useful when we need to pass
+ * the command-line option, which can be specified multiple times, to another
+ * command.
+ */
+int parse_opt_passthru_argv(const struct option *opt, const char *arg, int 
unset)
+{
+   static struct strbuf sb = STRBUF_INIT;
+   struct argv_array *opt_value = opt->value;
+
+   if (recreate_opt(&sb, opt, arg, unset) < 0)
+   return -1;
+
+   argv_array_push(opt_value, sb.buf);
+
+   return 0;
+}
diff --git a/parse-options.h b/parse-options.h
index 5b0f886..aba06688 100644
--- a/parse-options.h
+++ b/parse-options.h
@@ -225,6 +225,7 @@ extern int parse_opt_tertiary(const struct option *, const 
char *, int);
 extern int parse_opt_string_list(const struct option *, const char *, int);
 extern int parse_opt_noop_cb(const struct option *, const char *, int);
 extern int parse_opt_passthru(const struct option *, const char *, int);
+extern int parse_opt_passthru_argv(const struct option *, const char *, int);
 
 #define OPT__VERBOSE(var, h)  OPT_COUNTUP('v', "verbose", (var), (h))
 #define OPT__QUIET(var, h)OPT_COUNTUP('q', "quiet",   (var), (h))
@@ -245,5 +246,7 @@ extern int parse_opt_passthru(const struct option *, const 
char *, int);
{ OPTION_CALLBACK, (s), (l), (v), N_("style"), (h), PARSE_OPT_OPTARG, 
parseopt_column_callback }
 #define OPT_PASSTHRU(s, l, v, a, h, f) \
{ OPTION_CALLBACK, (s), (l), (v), (a), (h), (f), parse_opt_passthru }
+#define OPT_PASSTHRU_ARGV(s, l, v, a, h, f) \
+   { OPTION_CALLBACK, (s), (l), (v), (a), (h), (f), 
parse_opt_passthru_argv }
 
 #endif
-- 
2.1.4

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


[PATCH v3 04/19] pull: implement skeletal builtin pull

2015-06-14 Thread Paul Tan
For the purpose of rewriting git-pull.sh into a C builtin, implement a
skeletal builtin/pull.c that redirects to $GIT_EXEC_PATH/git-pull.sh if
the environment variable _GIT_USE_BUILTIN_PULL is not defined. This
allows us to fall back on the functional git-pull.sh when running the
test suite for tests that depend on a working git-pull implementation.

This redirection should be removed when all the features of git-pull.sh
have been re-implemented in builtin/pull.c.

Helped-by: Junio C Hamano 
Signed-off-by: Paul Tan 
---

Notes:
v3

* style fixes

 Makefile   |  1 +
 builtin.h  |  1 +
 builtin/pull.c | 33 +
 git.c  |  1 +
 4 files changed, 36 insertions(+)
 create mode 100644 builtin/pull.c

diff --git a/Makefile b/Makefile
index 54ec511..2057a9d 100644
--- a/Makefile
+++ b/Makefile
@@ -877,6 +877,7 @@ BUILTIN_OBJS += builtin/pack-refs.o
 BUILTIN_OBJS += builtin/patch-id.o
 BUILTIN_OBJS += builtin/prune-packed.o
 BUILTIN_OBJS += builtin/prune.o
+BUILTIN_OBJS += builtin/pull.o
 BUILTIN_OBJS += builtin/push.o
 BUILTIN_OBJS += builtin/read-tree.o
 BUILTIN_OBJS += builtin/receive-pack.o
diff --git a/builtin.h b/builtin.h
index b87df70..ea3c834 100644
--- a/builtin.h
+++ b/builtin.h
@@ -98,6 +98,7 @@ extern int cmd_pack_redundant(int argc, const char **argv, 
const char *prefix);
 extern int cmd_patch_id(int argc, const char **argv, const char *prefix);
 extern int cmd_prune(int argc, const char **argv, const char *prefix);
 extern int cmd_prune_packed(int argc, const char **argv, const char *prefix);
+extern int cmd_pull(int argc, const char **argv, const char *prefix);
 extern int cmd_push(int argc, const char **argv, const char *prefix);
 extern int cmd_read_tree(int argc, const char **argv, const char *prefix);
 extern int cmd_receive_pack(int argc, const char **argv, const char *prefix);
diff --git a/builtin/pull.c b/builtin/pull.c
new file mode 100644
index 000..cabeed4
--- /dev/null
+++ b/builtin/pull.c
@@ -0,0 +1,33 @@
+/*
+ * Builtin "git pull"
+ *
+ * Based on git-pull.sh by Junio C Hamano
+ *
+ * Fetch one or more remote refs and merge it/them into the current HEAD.
+ */
+#include "cache.h"
+#include "builtin.h"
+#include "parse-options.h"
+#include "exec_cmd.h"
+
+static const char * const pull_usage[] = {
+   NULL
+};
+
+static struct option pull_options[] = {
+   OPT_END()
+};
+
+int cmd_pull(int argc, const char **argv, const char *prefix)
+{
+   if (!getenv("_GIT_USE_BUILTIN_PULL")) {
+   const char *path = mkpath("%s/git-pull", git_exec_path());
+
+   if (sane_execvp(path, (char **)argv) < 0)
+   die_errno("could not exec %s", path);
+   }
+
+   argc = parse_options(argc, argv, prefix, pull_options, pull_usage, 0);
+
+   return 0;
+}
diff --git a/git.c b/git.c
index 44374b1..e7a7713 100644
--- a/git.c
+++ b/git.c
@@ -445,6 +445,7 @@ static struct cmd_struct commands[] = {
{ "pickaxe", cmd_blame, RUN_SETUP },
{ "prune", cmd_prune, RUN_SETUP },
{ "prune-packed", cmd_prune_packed, RUN_SETUP },
+   { "pull", cmd_pull, RUN_SETUP | NEED_WORK_TREE },
{ "push", cmd_push, RUN_SETUP },
{ "read-tree", cmd_read_tree, RUN_SETUP },
{ "receive-pack", cmd_receive_pack },
-- 
2.1.4

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


[PATCH v3 06/19] pull: pass verbosity, --progress flags to fetch and merge

2015-06-14 Thread Paul Tan
7f87aff (Teach/Fix pull/fetch -q/-v options, 2008-11-15) taught git-pull
to accept the verbosity -v and -q options and pass them to git-fetch and
git-merge.

Re-implement support for the verbosity flags by adding it to the options
list and introducing argv_push_verbosity() to push the flags into the
argv array used to execute git-fetch and git-merge.

9839018 (fetch and pull: learn --progress, 2010-02-24) and bebd2fd
(pull: propagate --progress to merge, 2011-02-20) taught git-pull to
accept the --progress option and pass it to git-fetch and git-merge.

Use OPT_PASSTHRU() implemented earlier to pass the "--[no-]progress"
command line options to git-fetch and git-merge.

Helped-by: Junio C Hamano 
Signed-off-by: Paul Tan 
---

Notes:
v3

* Re-worded commit message.

 builtin/pull.c | 36 
 1 file changed, 36 insertions(+)

diff --git a/builtin/pull.c b/builtin/pull.c
index 9157536..5d9f2b5 100644
--- a/builtin/pull.c
+++ b/builtin/pull.c
@@ -16,11 +16,35 @@ static const char * const pull_usage[] = {
NULL
 };
 
+/* Shared options */
+static int opt_verbosity;
+static char *opt_progress;
+
 static struct option pull_options[] = {
+   /* Shared options */
+   OPT__VERBOSITY(&opt_verbosity),
+   OPT_PASSTHRU(0, "progress", &opt_progress, NULL,
+   N_("force progress reporting"),
+   PARSE_OPT_NOARG),
+
OPT_END()
 };
 
 /**
+ * Pushes "-q" or "-v" switches into arr to match the opt_verbosity level.
+ */
+static void argv_push_verbosity(struct argv_array *arr)
+{
+   int verbosity;
+
+   for (verbosity = opt_verbosity; verbosity > 0; verbosity--)
+   argv_array_push(arr, "-v");
+
+   for (verbosity = opt_verbosity; verbosity < 0; verbosity++)
+   argv_array_push(arr, "-q");
+}
+
+/**
  * Parses argv into [ [...]], returning their values in `repo`
  * as a string and `refspecs` as a null-terminated array of strings. If `repo`
  * is not provided in argv, it is set to NULL.
@@ -46,6 +70,12 @@ static int run_fetch(const char *repo, const char **refspecs)
int ret;
 
argv_array_pushl(&args, "fetch", "--update-head-ok", NULL);
+
+   /* Shared options */
+   argv_push_verbosity(&args);
+   if (opt_progress)
+   argv_array_push(&args, opt_progress);
+
if (repo) {
argv_array_push(&args, repo);
argv_array_pushv(&args, refspecs);
@@ -65,6 +95,12 @@ static int run_merge(void)
struct argv_array args = ARGV_ARRAY_INIT;
 
argv_array_pushl(&args, "merge", NULL);
+
+   /* Shared options */
+   argv_push_verbosity(&args);
+   if (opt_progress)
+   argv_array_push(&args, opt_progress);
+
argv_array_push(&args, "FETCH_HEAD");
ret = run_command_v_opt(args.argv, RUN_GIT_CMD);
argv_array_clear(&args);
-- 
2.1.4

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


[PATCH v3 00/19] Make git-pull a builtin

2015-06-14 Thread Paul Tan
This is a re-roll of [v2]. Thanks Junio, Stefan for the reviews last round.

Previous versions:

[v1] http://thread.gmane.org/gmane.comp.version-control.git/269258
[v2] http://thread.gmane.org/gmane.comp.version-control.git/270639

git-pull is a commonly executed command to check for new changes in the
upstream repository and, if there are, fetch and integrate them into the
current branch. Currently it is implemented by the shell script git-pull.sh.
However, compared to C, shell scripts have certain deficiencies -- they need to
spawn a lot of processes, introduce a lot of dependencies and cannot take
advantage of git's internal caches.

This series rewrites git-pull.sh into a C builtin, thus improving its
performance and portability. It is part of my GSoC project to rewrite git-pull
and git-am into builtins[1].

[1] https://gist.github.com/pyokagan/1b7b0d1f4dab6ba3cef1


Paul Tan (19):
  parse-options-cb: implement parse_opt_passthru()
  parse-options-cb: implement parse_opt_passthru_argv()
  argv-array: implement argv_array_pushv()
  pull: implement skeletal builtin pull
  pull: implement fetch + merge
  pull: pass verbosity, --progress flags to fetch and merge
  pull: pass git-merge's options to git-merge
  pull: pass git-fetch's options to git-fetch
  pull: error on no merge candidates
  pull: support pull.ff config
  pull: check if in unresolved merge state
  pull: fast-forward working tree if head is updated
  pull: implement pulling into an unborn branch
  pull: set reflog message
  pull: teach git pull about --rebase
  pull: configure --rebase via branch..rebase or pull.rebase
  pull --rebase: exit early when the working directory is dirty
  pull --rebase: error on no merge candidate cases
  pull: remove redirection to git-pull.sh

 Documentation/technical/api-argv-array.txt|   3 +
 Documentation/technical/api-parse-options.txt |  13 +
 Makefile  |   2 +-
 advice.c  |   8 +
 advice.h  |   1 +
 argv-array.c  |   6 +
 argv-array.h  |   1 +
 builtin.h |   1 +
 builtin/pull.c| 881 ++
 git-pull.sh => contrib/examples/git-pull.sh   |   0
 git.c |   1 +
 parse-options-cb.c|  69 ++
 parse-options.h   |   6 +
 13 files changed, 991 insertions(+), 1 deletion(-)
 create mode 100644 builtin/pull.c
 rename git-pull.sh => contrib/examples/git-pull.sh (100%)

-- 
2.1.4

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


[PATCH v3 11/19] pull: check if in unresolved merge state

2015-06-14 Thread Paul Tan
Since d38a30d (Be more user-friendly when refusing to do something
because of conflict., 2010-01-12), git-pull will error out with
user-friendly advices if the user is in the middle of a merge or has
unmerged files.

Re-implement this behavior. While the "has unmerged files" case can be
handled by die_resolve_conflict(), we introduce a new function
die_conclude_merge() for printing a different error message for when
there are no unmerged files but the merge has not been finished.

Signed-off-by: Paul Tan 
---
 advice.c   | 8 
 advice.h   | 1 +
 builtin/pull.c | 9 +
 3 files changed, 18 insertions(+)

diff --git a/advice.c b/advice.c
index 575bec2..4965686 100644
--- a/advice.c
+++ b/advice.c
@@ -96,6 +96,14 @@ void NORETURN die_resolve_conflict(const char *me)
die("Exiting because of an unresolved conflict.");
 }
 
+void NORETURN die_conclude_merge(void)
+{
+   error(_("You have not concluded your merge (MERGE_HEAD exists)."));
+   if (advice_resolve_conflict)
+   advise(_("Please, commit your changes before you can merge."));
+   die(_("Exiting because of unfinished merge."));
+}
+
 void detach_advice(const char *new_name)
 {
const char fmt[] =
diff --git a/advice.h b/advice.h
index 5ecc6c1..b341a55 100644
--- a/advice.h
+++ b/advice.h
@@ -24,6 +24,7 @@ __attribute__((format (printf, 1, 2)))
 void advise(const char *advice, ...);
 int error_resolve_conflict(const char *me);
 extern void NORETURN die_resolve_conflict(const char *me);
+void NORETURN die_conclude_merge(void);
 void detach_advice(const char *new_name);
 
 #endif /* ADVICE_H */
diff --git a/builtin/pull.c b/builtin/pull.c
index 0ddb964..cb5898a 100644
--- a/builtin/pull.c
+++ b/builtin/pull.c
@@ -12,6 +12,7 @@
 #include "run-command.h"
 #include "sha1-array.h"
 #include "remote.h"
+#include "dir.h"
 
 static const char * const pull_usage[] = {
N_("git pull [options] [ [...]]"),
@@ -426,6 +427,14 @@ int cmd_pull(int argc, const char **argv, const char 
*prefix)
if (!opt_ff)
opt_ff = xstrdup_or_null(config_get_ff());
 
+   git_config(git_default_config, NULL);
+
+   if (read_cache_unmerged())
+   die_resolve_conflict("Pull");
+
+   if (file_exists(git_path("MERGE_HEAD")))
+   die_conclude_merge();
+
if (run_fetch(repo, refspecs))
return 1;
 
-- 
2.1.4

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


Re: [PATCH v2 01/11] t6301: for-each-ref tests for ref-filter APIs

2015-06-14 Thread karthik nayak
On Sun, Jun 14, 2015 at 1:42 PM, Matthieu Moy
 wrote:
> Karthik Nayak  writes:
>
>> +test_expect_success 'setup some history and refs' '
>> + test_commit one &&
>> + test_commit two &&
>> + test_commit three &&
>> + git checkout -b side &&
>> + test_commit four &&
>> + git checkout master &&
>> + git update-ref refs/odd/spot master
>
> I think you want more corner-cases here. For example,
> refs/headsfoo/master should not match refs/heads, and it's easy to write
> an incorrect implementation for this => test.

Like you mentioned below, currently it's redundant with t6300 and its
purpose is to add tests for new functionality we provide to for-each-ref
via ref-filter. This is done in the next few patches in this series.

>
>> +'
>> +test_expect_success 'filtering by leading name' '
>
> Blank line between tests please.

Noted. Thanks.

>
>> + cat >expect <<-\EOF &&
>> + refs/heads/master
>> + refs/heads/side
>> + EOF
>> + git for-each-ref --format="%(refname)" refs/heads >actual &&
>> + test_cmp expect actual
>> +'
>
> Isn't this test redundant with the content of t6300-for-each-ref.sh?
>
> At this point, you've done only internal refactoring, so you shouldn't
> need new tests (except to fix coverage holes in existing tests).
>
> I guess you're adding this to build more tests on top, but the commit
> message should clarify this.
>

I'll add a note to the commit message about how this test file is so
that we can integrate
more tests in the future for functionality given to for-each-ref via
ref-filter APIs.

-- 
Regards,
Karthik Nayak
--
To unsubscribe from this list: send the line "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 v8 0/11] Create ref-filter from for-each-ref

2015-06-14 Thread karthik nayak
On Sun, Jun 14, 2015 at 1:34 PM, Matthieu Moy
 wrote:
> karthik nayak  writes:
>
>> The previous version of the patch can be found at :
>> http://thread.gmane.org/gmane.comp.version-control.git/271423
>>
>> Changes :
>> * Removed an unnecessary commit (v7 3/12)
>> * Change a comment in 01/11 (v8)
>
> And change the order of parameters in ref_filter. More precisely the
> diff with v7 is the following, and it looks good to me:
>
> diff --git a/builtin/for-each-ref.c b/builtin/for-each-ref.c
> index e2f15e6..7919206 100644
> --- a/builtin/for-each-ref.c
> +++ b/builtin/for-each-ref.c
> @@ -58,7 +58,7 @@ int cmd_for_each_ref(int argc, const char **argv, const 
> char *prefix)
> memset(&array, 0, sizeof(array));
> memset(&filter, 0, sizeof(filter));
> filter.name_patterns = argv;
> -   filter_refs(&array, FILTER_REFS_ALL | FILTER_REFS_INCLUDE_BROKEN, 
> &filter);
> +   filter_refs(&array, &filter, FILTER_REFS_ALL | 
> FILTER_REFS_INCLUDE_BROKEN);
> ref_array_sort(sorting, &array);
>
> if (!maxcount || array.nr < maxcount)
> diff --git a/ref-filter.c b/ref-filter.c
> index 310ecd6..43502a4 100644
> --- a/ref-filter.c
> +++ b/ref-filter.c
> @@ -818,10 +818,10 @@ static void get_ref_atom_value(struct ref_array_item 
> *ref, int atom, struct atom
>  }
>
>  /*
> - * Return 1 if the refname matches with one of the patterns,
> - * otherwise 0.  The patterns can be literal prefix (e.g. a
> - * refname "refs/heads/master" matches a pattern "refs/heads/")
> - * or a wildcard (e.g. the same ref matches "refs/heads/m*",too).
> + * Return 1 if the refname matches one of the patterns, otherwise 0.
> + * A pattern can be path prefix (e.g. a refname "refs/heads/master"
> + * matches a pattern "refs/heads/") or a wildcard (e.g. the same ref
> + * matches "refs/heads/m*",too).
>   */
>  static int match_name_as_path(const char **pattern, const char *refname)
>  {
> @@ -912,7 +912,7 @@ void ref_array_clear(struct ref_array *array)
>   * as per the given ref_filter structure and finally store the
>   * filtered refs in the ref_array structure.
>   */
> -int filter_refs(struct ref_array *array, unsigned int type, struct 
> ref_filter *filter)
> +int filter_refs(struct ref_array *array, struct ref_filter *filter, unsigned 
> int type)
>  {
> struct ref_filter_cbdata ref_cbdata;
>
> diff --git a/ref-filter.h b/ref-filter.h
> index 6ab2a75..6997984 100644
> --- a/ref-filter.h
> +++ b/ref-filter.h
> @@ -23,7 +23,7 @@ struct atom_value {
>
>  struct ref_sorting {
> struct ref_sorting *next;
> -   int atom; /* index into 'struct atom_value *' array */
> +   int atom; /* index into used_atom array (internal) */
> unsigned reverse : 1;
>  };
>
> @@ -55,7 +55,7 @@ struct ref_filter_cbdata {
>   * as per the given ref_filter structure and finally store the
>   * filtered refs in the ref_array structure.
>   */
> -int filter_refs(struct ref_array *array, unsigned int type, struct 
> ref_filter *filter);
> +int filter_refs(struct ref_array *array, struct ref_filter *filter, unsigned 
> int type);
>  /*  Clear all memory allocated to ref_array */
>  void ref_array_clear(struct ref_array *array);
>  /*  Parse format string and sort specifiers */
>
> --
> Matthieu Moy
> http://www-verimag.imag.fr/~moy/

Thanks for summing it up.

-- 
Regards,
Karthik Nayak
--
To unsubscribe from this list: send the line "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: Need some help on patching buildin-files // was: Looking for feedback and help with a git-mirror for local usage

2015-06-14 Thread David Aguilar
On Fri, Jun 12, 2015 at 12:52:44PM +0200, Bernd Naumann wrote:
> Hello again,
> 
> After digging the code I may have got a clue where to start but I
> would  still appreciate some help from a developer, cause I have never
> learned to write C. (Some basics at school which happened over a
> decade ago.)
> 
> Currently I have questions on:
> 
> * How to patch clone: would cmd_clone() a good place? Or are there
> other calls which might be better. I think about to insert the check
> if a mirror will be setup or just updated, right after dest_exists.

If you'd still like to modify "git clone" itself, then the
"cmd_clone" entry point is certainly the place to start.
I would suggest exploring other alternatives, though.


Is it possible to use a caching HTTP proxy, so that "git clone"
goes through a local caching proxy?  I haven't tried this myself,
so maybe it's not even possible, but that seems like a natural
http-ish solution.


Another idea is to use Git's URL rewriting feature.  If your
clone URLs all follow a similar pattern then they can
automatically be rewritten to point to some other URL.

e.g. in ~/.gitconfig:

[url "file:///home/git/mirror/github.com/"]
insteadOf = "https://github.com/";

This will make git clone from /home/git/mirror/github.com/
whenever it sees https://github.com/ URLs.

This is not perfect because it ends up cloning from your local
copies rather than setting up the references via --mirror, but
at least it avoids hitting the network.  You'll need to
periodically update your local mirrors, though.

If you prefer to keep ~/.gitconfig pristine then you could do it
in a wrapper script by injecting e.g. the "-c" config flags,

git \
-c url.file://foo/bar/.insteadOf=https://github.com/ \
clone ...

> [...snip...]
> > 
> > I often build in example 'openwrt' with various build-scripts which
> > depends heavily on a fresh or clean environment and they omit many
> > sources via `git clone`, which results sometimes in over 100 MB of
> > traffic just for one build. /* Later needed .tar.gz source archives
> > are stored in a symlinked download directory which is supported by
> > 'openwrt/.config' since a few months... to reduce network traffic.
> > */

Why does a rebuild delete existing Git repositories?
That seems like a bad practice, and shouldn't be needed.
If possible, it would be worth improving the build scripts.

For example, a clone can be made pristine by doing
"git reset --hard && git clean -fdx".  Deleting a repository
just so that it can be re-cloned is very wasteful.

> > My connection to the internet is not the fastest in world and 
> > sometimes unstable, so I wanted to have some kind of local bare 
> > repository mirror, which is possible with `git clone --mirror`.
> > 
> > From these repositories I can later clone from, by calling `git 
> > clone --reference /path/to.git `, but I do not wish to edit 
> > all the build-scripts and Makefiles.

Maybe it'd be possible to make just the "git clone" part of the
build scripts configurable?

That'd make it really easy to inject a wrapper script that scans
the arguments and injects the needed --mirror arguments, in the
case that the above options won't work.


> > So I wrote a git wrapper script (`$HOME/bin/git`), which checks if
> >  `git` was called with 'clone', and if so, then it will first 
> > clones the repository as a mirror and then clones from that local 
> > mirror. If the mirror already exists, then it will only be updated 
> > (`git remote update`). This works for now.
> > 
> > [...snip...]
> > 
> > Ok, so far, so good, but the implementation of the current 
> > shell-prototype looks way too hacky [0] and I have found some edge
> >  cases on which my script will fail: The script depends on the
> > fact that the last, or at least the second last argument is a
> > valid git-url, but the following is a valid call, too :
> > 
> > `git --no-pager \ clone g...@github.com:openwrt/packages.git 
> > openwrt-packages --depth 1`
> > 
> > But this is not valid:
> > 
> > `git clone https://github.com/openwrt/packages.git --reference 
> > packages.git packages-2` or `git clone --verbose 
> > https://github.com/openwrt/packages.git packages-2 --reference 
> > packages.git`
> > 
> > 
> > I found out that git-clone actually also can only make a guess
> > what is the url and what not.

Another option is to rewrite the wrapper script in a better language.
For example, Python's argparse module can handle the above cases
with minimal fuss.

Anyways, as I said before, the root problem is really the build
scripts.  I bet modifying the build scripts to reuse existing
git repositories is easier than modifying "git clone".

cheers,
-- 
David
--
To unsubscribe from this list: send the line "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 01/11] t6301: for-each-ref tests for ref-filter APIs

2015-06-14 Thread Matthieu Moy
Karthik Nayak  writes:

> +test_expect_success 'setup some history and refs' '
> + test_commit one &&
> + test_commit two &&
> + test_commit three &&
> + git checkout -b side &&
> + test_commit four &&
> + git checkout master &&
> + git update-ref refs/odd/spot master

I think you want more corner-cases here. For example,
refs/headsfoo/master should not match refs/heads, and it's easy to write
an incorrect implementation for this => test.

> +'
> +test_expect_success 'filtering by leading name' '

Blank line between tests please.

> + cat >expect <<-\EOF &&
> + refs/heads/master
> + refs/heads/side
> + EOF
> + git for-each-ref --format="%(refname)" refs/heads >actual &&
> + test_cmp expect actual
> +'

Isn't this test redundant with the content of t6300-for-each-ref.sh?

At this point, you've done only internal refactoring, so you shouldn't
need new tests (except to fix coverage holes in existing tests).

I guess you're adding this to build more tests on top, but the commit
message should clarify this.

-- 
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 v8 0/11] Create ref-filter from for-each-ref

2015-06-14 Thread Matthieu Moy
karthik nayak  writes:

> The previous version of the patch can be found at :
> http://thread.gmane.org/gmane.comp.version-control.git/271423
>
> Changes :
> * Removed an unnecessary commit (v7 3/12)
> * Change a comment in 01/11 (v8)

And change the order of parameters in ref_filter. More precisely the
diff with v7 is the following, and it looks good to me:

diff --git a/builtin/for-each-ref.c b/builtin/for-each-ref.c
index e2f15e6..7919206 100644
--- a/builtin/for-each-ref.c
+++ b/builtin/for-each-ref.c
@@ -58,7 +58,7 @@ int cmd_for_each_ref(int argc, const char **argv, const char 
*prefix)
memset(&array, 0, sizeof(array));
memset(&filter, 0, sizeof(filter));
filter.name_patterns = argv;
-   filter_refs(&array, FILTER_REFS_ALL | FILTER_REFS_INCLUDE_BROKEN, 
&filter);
+   filter_refs(&array, &filter, FILTER_REFS_ALL | 
FILTER_REFS_INCLUDE_BROKEN);
ref_array_sort(sorting, &array);
 
if (!maxcount || array.nr < maxcount)
diff --git a/ref-filter.c b/ref-filter.c
index 310ecd6..43502a4 100644
--- a/ref-filter.c
+++ b/ref-filter.c
@@ -818,10 +818,10 @@ static void get_ref_atom_value(struct ref_array_item 
*ref, int atom, struct atom
 }
 
 /*
- * Return 1 if the refname matches with one of the patterns,
- * otherwise 0.  The patterns can be literal prefix (e.g. a
- * refname "refs/heads/master" matches a pattern "refs/heads/")
- * or a wildcard (e.g. the same ref matches "refs/heads/m*",too).
+ * Return 1 if the refname matches one of the patterns, otherwise 0.
+ * A pattern can be path prefix (e.g. a refname "refs/heads/master"
+ * matches a pattern "refs/heads/") or a wildcard (e.g. the same ref
+ * matches "refs/heads/m*",too).
  */
 static int match_name_as_path(const char **pattern, const char *refname)
 {
@@ -912,7 +912,7 @@ void ref_array_clear(struct ref_array *array)
  * as per the given ref_filter structure and finally store the
  * filtered refs in the ref_array structure.
  */
-int filter_refs(struct ref_array *array, unsigned int type, struct ref_filter 
*filter)
+int filter_refs(struct ref_array *array, struct ref_filter *filter, unsigned 
int type)
 {
struct ref_filter_cbdata ref_cbdata;
 
diff --git a/ref-filter.h b/ref-filter.h
index 6ab2a75..6997984 100644
--- a/ref-filter.h
+++ b/ref-filter.h
@@ -23,7 +23,7 @@ struct atom_value {
 
 struct ref_sorting {
struct ref_sorting *next;
-   int atom; /* index into 'struct atom_value *' array */
+   int atom; /* index into used_atom array (internal) */
unsigned reverse : 1;
 };
 
@@ -55,7 +55,7 @@ struct ref_filter_cbdata {
  * as per the given ref_filter structure and finally store the
  * filtered refs in the ref_array structure.
  */
-int filter_refs(struct ref_array *array, unsigned int type, struct ref_filter 
*filter);
+int filter_refs(struct ref_array *array, struct ref_filter *filter, unsigned 
int type);
 /*  Clear all memory allocated to ref_array */
 void ref_array_clear(struct ref_array *array);
 /*  Parse format string and sort specifiers */

-- 
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 11/19] pull: check if in unresolved merge state

2015-06-14 Thread Paul Tan
On Thu, Jun 11, 2015 at 1:14 AM, Junio C Hamano  wrote:
> I (or at least some part of me) actually view git_config_get_*() as
> "if you are only going to peek a few variables, you do not have to
> do the looping yourself" convenience, which leads me (or at least
> that part of me) to say "if you are doing the looping anyway, you
> may be better off picking up the variables you care about yourself
> in that loop".

Not just a convenience, but I personally find that callback functions
usually leads to code that is harder to understand because of the use
of static/global variables to preserve state and the fact that it is
harder to break it up into smaller functions to reason about. This is
just a matter of taste though, so I don't have strong feelings about
it.

Besides, there is a greater technical reason why we should not use
git_config(): It essentially performs a linear search[1], while the
git_config_get_*() functions do a constant-time lookup. Ideally, we
should remove uses of git_config() for users that have no need to
iterate over all the configuration entries.

[1] Since we do a strcmp() for every supported config setting, for
every config entry.

I should emphasize that the call to git_config(git_default_config,
NULL) is just a workaround to load the advice.* settings. In fact,
git_default_config() only peeks at a few config settings anyway, and
can be re-written to not iterate over all the user's config entries.
As such, I don't see why the builtin/pull.c code should be written to
support the git_config() way of doing things, even if we have to use
the workaround of calling git_config(). It's like saying: we have a
bad solution, now let's make it worse ;-)

> By calling git_config() before calling any git_config_get_*()
> functions, you would be priming the cache layer with the entire
> contents of the configuration files anyway, so later calls to
> git_config_get_*() will read from that cache, so there is no
> performance penalty in mixing the two methods to access
> configuration data.  That is why I felt less certain that the
> suggestion to stick to one method (instead of mixing the two) is a
> good thing to do (hence "less certain 'might'").

Right, although I think that the performance penalty due to using
git_config() is greater, and switching all the git_config_get_*()
calls to use it would just make it worse.

By the way, I got the idea that git development was moving towards
replacing use of git_config() from 5801d3b (builtin/gc.c: replace
`git_config()` with `git_config_get_*()` family, 2014-08-07).

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