[PATCH v3 5/6] push --force-with-lease: tie it all together

2013-07-23 Thread Junio C Hamano
This teaches the deepest part of the callchain for git push (and
git send-pack) to enforce the old value of the ref must be this,
otherwise fail this push (aka compare-and-swap / --lockref).

Signed-off-by: Junio C Hamano gits...@pobox.com
---
 builtin/send-pack.c |  5 +
 remote.c| 49 -
 remote.h|  1 +
 send-pack.c |  1 +
 transport-helper.c  |  6 ++
 transport.c |  5 +
 6 files changed, 54 insertions(+), 13 deletions(-)

diff --git a/builtin/send-pack.c b/builtin/send-pack.c
index 6027ead..41dc512 100644
--- a/builtin/send-pack.c
+++ b/builtin/send-pack.c
@@ -55,6 +55,11 @@ static void print_helper_status(struct ref *ref)
msg = needs force;
break;
 
+   case REF_STATUS_REJECT_STALE:
+   res = error;
+   msg = stale info;
+   break;
+
case REF_STATUS_REJECT_ALREADY_EXISTS:
res = error;
msg = already exists;
diff --git a/remote.c b/remote.c
index 52e3a12..922822c 100644
--- a/remote.c
+++ b/remote.c
@@ -1396,12 +1396,13 @@ int match_push_refs(struct ref *src, struct ref **dst,
 }
 
 void set_ref_status_for_push(struct ref *remote_refs, int send_mirror,
-   int force_update)
+int force_update)
 {
struct ref *ref;
 
for (ref = remote_refs; ref; ref = ref-next) {
int force_ref_update = ref-force || force_update;
+   int reject_reason = 0;
 
if (ref-peer_ref)
hashcpy(ref-new_sha1, ref-peer_ref-new_sha1);
@@ -1416,6 +1417,26 @@ void set_ref_status_for_push(struct ref *remote_refs, 
int send_mirror,
}
 
/*
+* Bypass the usual must fast-forward check but
+* replace it with a weaker the old value must be
+* this value we observed.  If the remote ref has
+* moved and is now different from what we expect,
+* reject any push.
+*
+* It also is an error if the user told us to check
+* with the remote-tracking branch to find the value
+* to expect, but we did not have such a tracking
+* branch.
+*/
+   if (ref-expect_old_sha1) {
+   if (ref-expect_old_no_trackback ||
+   hashcmp(ref-old_sha1, ref-old_sha1_expect))
+   reject_reason = REF_STATUS_REJECT_STALE;
+   }
+
+   /*
+* The usual must fast-forward rules.
+*
 * Decide whether an individual refspec A:B can be
 * pushed.  The push will succeed if any of the
 * following are true:
@@ -1433,24 +1454,26 @@ void set_ref_status_for_push(struct ref *remote_refs, 
int send_mirror,
 * passing the --force argument
 */
 
-   if (!ref-deletion  !is_null_sha1(ref-old_sha1)) {
-   int why = 0; /* why would this push require --force? */
-
+   else if (!ref-deletion  !is_null_sha1(ref-old_sha1)) {
if (!prefixcmp(ref-name, refs/tags/))
-   why = REF_STATUS_REJECT_ALREADY_EXISTS;
+   reject_reason = 
REF_STATUS_REJECT_ALREADY_EXISTS;
else if (!has_sha1_file(ref-old_sha1))
-   why = REF_STATUS_REJECT_FETCH_FIRST;
+   reject_reason = REF_STATUS_REJECT_FETCH_FIRST;
else if (!lookup_commit_reference_gently(ref-old_sha1, 
1) ||
 !lookup_commit_reference_gently(ref-new_sha1, 
1))
-   why = REF_STATUS_REJECT_NEEDS_FORCE;
+   reject_reason = REF_STATUS_REJECT_NEEDS_FORCE;
else if (!ref_newer(ref-new_sha1, ref-old_sha1))
-   why = REF_STATUS_REJECT_NONFASTFORWARD;
-
-   if (!force_ref_update)
-   ref-status = why;
-   else if (why)
-   ref-forced_update = 1;
+   reject_reason = 
REF_STATUS_REJECT_NONFASTFORWARD;
}
+
+   /*
+* --force will defeat any rejection implemented
+* by the rules above.
+*/
+   if (!force_ref_update)
+   ref-status = reject_reason;
+   else if (reject_reason)
+   ref-forced_update = 1;
}
 }
 
diff --git a/remote.h b/remote.h
index ca3c8c8..6c42554 100644
--- a/remote.h
+++ b/remote.h
@@ -107,6 +107,7 @@ struct ref {
  

[PATCH v3 4/6] push --force-with-lease: implement logic to populate old_sha1_expect[]

2013-07-23 Thread Junio C Hamano
This plugs the push_cas_option data collected by the command line
option parser to the transport system with a new function
apply_push_cas(), which is called after match_push_refs() has
already been called.

At this point, we know which remote we are talking to, and what
remote refs we are going to update, so we can fill in the details
that may have been missing from the command line, such as

 (1) what abbreviated refname the user gave us matches the actual
 refname at the remote; and

 (2) which remote-tracking branch in our local repository to read
 the value of the object to expect at the remote.

to populate the old_sha1_expect[] field of each of the remote ref.
As stated in the documentation, the use of remote-tracking branch
as the default is a tentative one, and we may come up with a better
logic as we gain experience.

Still nobody uses this information, which is the topic of the next
patch.

Signed-off-by: Junio C Hamano gits...@pobox.com
---
 builtin/push.c  |  7 ++
 builtin/send-pack.c |  3 +++
 remote.c| 61 +
 remote.h|  6 ++
 transport.c |  6 ++
 transport.h |  4 
 6 files changed, 87 insertions(+)

diff --git a/builtin/push.c b/builtin/push.c
index 31a5ba0..2fd0a70 100644
--- a/builtin/push.c
+++ b/builtin/push.c
@@ -299,6 +299,13 @@ static int push_with_options(struct transport *transport, 
int flags)
if (thin)
transport_set_option(transport, TRANS_OPT_THIN, yes);
 
+   if (!is_empty_cas(cas)) {
+   if (!transport-smart_options)
+   die(underlying transport does not support --%s option,
+   CAS_OPT_NAME);
+   transport-smart_options-cas = cas;
+   }
+
if (verbosity  0)
fprintf(stderr, _(Pushing to %s\n), transport-url);
err = transport_push(transport, refspec_nr, refspec, flags,
diff --git a/builtin/send-pack.c b/builtin/send-pack.c
index a23b26d..6027ead 100644
--- a/builtin/send-pack.c
+++ b/builtin/send-pack.c
@@ -242,6 +242,9 @@ int cmd_send_pack(int argc, const char **argv, const char 
*prefix)
if (match_push_refs(local_refs, remote_refs, nr_refspecs, refspecs, 
flags))
return -1;
 
+   if (!is_empty_cas(cas))
+   apply_push_cas(cas, remote, remote_refs);
+
set_ref_status_for_push(remote_refs, args.send_mirror,
args.force_update);
 
diff --git a/remote.c b/remote.c
index 0d38353..52e3a12 100644
--- a/remote.c
+++ b/remote.c
@@ -1978,3 +1978,64 @@ int parseopt_push_cas_option(const struct option *opt, 
const char *arg, int unse
 {
return parse_push_cas_option(opt-value, arg, unset);
 }
+
+int is_empty_cas(const struct push_cas_option *cas)
+{
+   return !cas-use_tracking_for_rest  !cas-nr;
+}
+
+/*
+ * Look at remote.fetch refspec and see if we have a remote
+ * tracking branch for the refname there.  Fill its current
+ * value in sha1[].
+ * If we cannot do so, return negative to signal an error.
+ */
+static int remote_tracking(struct remote *remote, const char *refname,
+  unsigned char sha1[20])
+{
+   char *dst;
+
+   dst = apply_refspecs(remote-fetch, remote-fetch_refspec_nr, refname);
+   if (!dst)
+   return -1; /* no tracking ref for refname at remote */
+   if (read_ref(dst, sha1))
+   return -1; /* we know what the tracking ref is but we cannot 
read it */
+   return 0;
+}
+
+static void apply_cas(struct push_cas_option *cas,
+ struct remote *remote,
+ struct ref *ref)
+{
+   int i;
+
+   /* Find an explicit --option=name[:value] entry */
+   for (i = 0; i  cas-nr; i++) {
+   struct push_cas *entry = cas-entry[i];
+   if (!refname_match(entry-refname, ref-name, 
ref_rev_parse_rules))
+   continue;
+   ref-expect_old_sha1 = 1;
+   if (!entry-use_tracking)
+   hashcpy(ref-old_sha1_expect, cas-entry[i].expect);
+   else if (remote_tracking(remote, ref-name, 
ref-old_sha1_expect))
+   ref-expect_old_no_trackback = 1;
+   return;
+   }
+
+   /* Are we using --option to cover all? */
+   if (!cas-use_tracking_for_rest)
+   return;
+
+   ref-expect_old_sha1 = 1;
+   if (remote_tracking(remote, ref-name, ref-old_sha1_expect))
+   ref-expect_old_no_trackback = 1;
+}
+
+void apply_push_cas(struct push_cas_option *cas,
+   struct remote *remote,
+   struct ref *remote_refs)
+{
+   struct ref *ref;
+   for (ref = remote_refs; ref; ref = ref-next)
+   apply_cas(cas, remote, ref);
+}
diff --git a/remote.h b/remote.h
index 843c3ce..ca3c8c8 100644
--- a/remote.h
+++ b/remote.h
@@ -77,10 +77,13 @@ struct ref {
struct ref 

[PATCH v3 0/6] git push --cas/--lockref renamed to --force-with-lease

2013-07-23 Thread Junio C Hamano
This is mostly unchanged since the previous round, except that

 * The option is spelled --force-with-lease=ref:expect.
   Nobody liked cas as it was too technical, many disliked
   lockref because lock sounded as if push by others were
   excluded by it while in fact this is to fail us.

   The final name implies that it is related to the --force that
   breaks the must fast-forward safety, but with-lease part
   conveys that there is some reservation with the forcing.  The
   observation you make before you start rebasing (or you ensure
   that everything is expendable and decide to delete) is like
   taking a lease on the ref, and as long as the lease is not
   broken by others, you can push a non-fast-forward history to
   replace what is at the remote.

 * The logic to choose default when the option is not given with an
   explicit expected value is still the remote-tracking branch for
   the ref being updated, but the documentation warns users against
   relying on that semantics, as it was shown to be fragile during
   the discussion, and hopefully we will come up with a better and
   more robust one to replace it.

The first two preparatory patches are the same since v2.  For the
remainder, other than changes necessary to rename the option, the
documentation part of [PATCH 3/6] has been updated to mark forms
without explicit expect value as experimental.

Junio C Hamano (6):
  cache.h: move remote/connect API out of it
  builtin/push.c: use OPT_BOOL, not OPT_BOOLEAN
  remote.c: add command line option parser for --force-with-lease
  push --force-with-lease: implement logic to populate old_sha1_expect[]
  push --force-with-lease: tie it all together
  t5533: test push --force-with-lease

 Documentation/git-push.txt |  77 +++---
 builtin/fetch-pack.c   |   2 +
 builtin/push.c |  19 -
 builtin/receive-pack.c |   1 +
 builtin/send-pack.c|  26 +++
 cache.h|  62 ---
 connect.c  |   1 +
 connect.h  |  13 
 fetch-pack.c   |   1 +
 fetch-pack.h   |   1 +
 refs.c |   8 --
 remote.c   | 175 +
 remote.h   |  83 
 send-pack.c|   2 +
 t/t5533-push-cas.sh| 189 +
 transport-helper.c |   6 ++
 transport.c|  13 
 transport.h|   5 ++
 upload-pack.c  |   1 +
 19 files changed, 588 insertions(+), 97 deletions(-)
 create mode 100644 connect.h
 create mode 100755 t/t5533-push-cas.sh

-- 
1.8.3.4-980-g8decd39

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


[PATCH v3 2/6] builtin/push.c: use OPT_BOOL, not OPT_BOOLEAN

2013-07-23 Thread Junio C Hamano
The command line parser of git push for --tags, --delete, and
--thin options still used outdated OPT_BOOLEAN.  Because these
options do not give escalating levels when given multiple times,
they should use OPT_BOOL.

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

diff --git a/builtin/push.c b/builtin/push.c
index 2d84d10..342d792 100644
--- a/builtin/push.c
+++ b/builtin/push.c
@@ -427,15 +427,15 @@ int cmd_push(int argc, const char **argv, const char 
*prefix)
OPT_BIT( 0 , all, flags, N_(push all refs), 
TRANSPORT_PUSH_ALL),
OPT_BIT( 0 , mirror, flags, N_(mirror all refs),
(TRANSPORT_PUSH_MIRROR|TRANSPORT_PUSH_FORCE)),
-   OPT_BOOLEAN( 0, delete, deleterefs, N_(delete refs)),
-   OPT_BOOLEAN( 0 , tags, tags, N_(push tags (can't be used 
with --all or --mirror))),
+   OPT_BOOL( 0, delete, deleterefs, N_(delete refs)),
+   OPT_BOOL( 0 , tags, tags, N_(push tags (can't be used with 
--all or --mirror))),
OPT_BIT('n' , dry-run, flags, N_(dry run), 
TRANSPORT_PUSH_DRY_RUN),
OPT_BIT( 0,  porcelain, flags, N_(machine-readable 
output), TRANSPORT_PUSH_PORCELAIN),
OPT_BIT('f', force, flags, N_(force updates), 
TRANSPORT_PUSH_FORCE),
{ OPTION_CALLBACK, 0, recurse-submodules, flags, N_(check),
N_(control recursive pushing of submodules),
PARSE_OPT_OPTARG, option_parse_recurse_submodules },
-   OPT_BOOLEAN( 0 , thin, thin, N_(use thin pack)),
+   OPT_BOOL( 0 , thin, thin, N_(use thin pack)),
OPT_STRING( 0 , receive-pack, receivepack, receive-pack, 
N_(receive pack program)),
OPT_STRING( 0 , exec, receivepack, receive-pack, 
N_(receive pack program)),
OPT_BIT('u', set-upstream, flags, N_(set upstream for git 
pull/status),
-- 
1.8.3.4-980-g8decd39

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


[PATCH v3 1/6] cache.h: move remote/connect API out of it

2013-07-23 Thread Junio C Hamano
The definition of struct ref in cache.h, a header file so
central to the system, always confused me.  This structure is not
about the local ref used by sha1-name API to name local objects.

It is what refspecs are expanded into, after finding out what refs
the other side has, to define what refs are updated after object
transfer succeeds to what values.  It belongs to remote.h together
with struct refspec.

While we are at it, also move the types and functions related to the
Git transport connection to a new header file connect.h

Signed-off-by: Junio C Hamano gits...@pobox.com
---
 builtin/fetch-pack.c   |  2 ++
 builtin/receive-pack.c |  1 +
 builtin/send-pack.c|  1 +
 cache.h| 62 --
 connect.c  |  1 +
 connect.h  | 13 +++
 fetch-pack.c   |  1 +
 fetch-pack.h   |  1 +
 refs.c |  8 ---
 remote.c   |  8 +++
 remote.h   | 54 +++
 send-pack.c|  1 +
 transport.c|  2 ++
 transport.h|  1 +
 upload-pack.c  |  1 +
 15 files changed, 87 insertions(+), 70 deletions(-)
 create mode 100644 connect.h

diff --git a/builtin/fetch-pack.c b/builtin/fetch-pack.c
index aba4465..c6888c6 100644
--- a/builtin/fetch-pack.c
+++ b/builtin/fetch-pack.c
@@ -1,6 +1,8 @@
 #include builtin.h
 #include pkt-line.h
 #include fetch-pack.h
+#include remote.h
+#include connect.h
 
 static const char fetch_pack_usage[] =
 git fetch-pack [--all] [--stdin] [--quiet|-q] [--keep|-k] [--thin] 
diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c
index e3eb5fc..7434d9b 100644
--- a/builtin/receive-pack.c
+++ b/builtin/receive-pack.c
@@ -8,6 +8,7 @@
 #include commit.h
 #include object.h
 #include remote.h
+#include connect.h
 #include transport.h
 #include string-list.h
 #include sha1-array.h
diff --git a/builtin/send-pack.c b/builtin/send-pack.c
index 152c4ea..e86d3b5 100644
--- a/builtin/send-pack.c
+++ b/builtin/send-pack.c
@@ -5,6 +5,7 @@
 #include sideband.h
 #include run-command.h
 #include remote.h
+#include connect.h
 #include send-pack.h
 #include quote.h
 #include transport.h
diff --git a/cache.h b/cache.h
index dd0fb33..cb2891d 100644
--- a/cache.h
+++ b/cache.h
@@ -1035,68 +1035,6 @@ struct pack_entry {
struct packed_git *p;
 };
 
-struct ref {
-   struct ref *next;
-   unsigned char old_sha1[20];
-   unsigned char new_sha1[20];
-   char *symref;
-   unsigned int
-   force:1,
-   forced_update:1,
-   deletion:1,
-   matched:1;
-
-   /*
-* Order is important here, as we write to FETCH_HEAD
-* in numeric order. And the default NOT_FOR_MERGE
-* should be 0, so that xcalloc'd structures get it
-* by default.
-*/
-   enum {
-   FETCH_HEAD_MERGE = -1,
-   FETCH_HEAD_NOT_FOR_MERGE = 0,
-   FETCH_HEAD_IGNORE = 1
-   } fetch_head_status;
-
-   enum {
-   REF_STATUS_NONE = 0,
-   REF_STATUS_OK,
-   REF_STATUS_REJECT_NONFASTFORWARD,
-   REF_STATUS_REJECT_ALREADY_EXISTS,
-   REF_STATUS_REJECT_NODELETE,
-   REF_STATUS_REJECT_FETCH_FIRST,
-   REF_STATUS_REJECT_NEEDS_FORCE,
-   REF_STATUS_UPTODATE,
-   REF_STATUS_REMOTE_REJECT,
-   REF_STATUS_EXPECTING_REPORT
-   } status;
-   char *remote_status;
-   struct ref *peer_ref; /* when renaming */
-   char name[FLEX_ARRAY]; /* more */
-};
-
-#define REF_NORMAL (1u  0)
-#define REF_HEADS  (1u  1)
-#define REF_TAGS   (1u  2)
-
-extern struct ref *find_ref_by_name(const struct ref *list, const char *name);
-
-#define CONNECT_VERBOSE   (1u  0)
-extern struct child_process *git_connect(int fd[2], const char *url, const 
char *prog, int flags);
-extern int finish_connect(struct child_process *conn);
-extern int git_connection_is_socket(struct child_process *conn);
-struct extra_have_objects {
-   int nr, alloc;
-   unsigned char (*array)[20];
-};
-extern struct ref **get_remote_heads(int in, char *src_buf, size_t src_len,
-struct ref **list, unsigned int flags,
-struct extra_have_objects *);
-extern int server_supports(const char *feature);
-extern int parse_feature_request(const char *features, const char *feature);
-extern const char *server_feature_value(const char *feature, int *len_ret);
-extern const char *parse_feature_value(const char *feature_list, const char 
*feature, int *len_ret);
-
 extern struct packed_git *parse_pack_index(unsigned char *sha1, const char 
*idx_path);
 
 /* A hook for count-objects to report invalid files in pack directory */
diff --git a/connect.c b/connect.c
index a0783d4..a80ebd3 100644
--- a/connect.c
+++ b/connect.c
@@ -5,6 +5,7 @@

[PATCH v3 6/6] t5533: test push --force-with-lease

2013-07-23 Thread Junio C Hamano
Prepare two repositories, src and dst, the latter of which is a
clone of the former (with tracking branches), and push from the
latter into the former, with various --force-with-lease options.

Signed-off-by: Junio C Hamano gits...@pobox.com
---
 t/t5533-push-cas.sh | 189 
 1 file changed, 189 insertions(+)
 create mode 100755 t/t5533-push-cas.sh

diff --git a/t/t5533-push-cas.sh b/t/t5533-push-cas.sh
new file mode 100755
index 000..ba20d83
--- /dev/null
+++ b/t/t5533-push-cas.sh
@@ -0,0 +1,189 @@
+#!/bin/sh
+
+test_description='compare  swap push force/delete safety'
+
+. ./test-lib.sh
+
+setup_srcdst_basic () {
+   rm -fr src dst 
+   git clone --no-local . src 
+   git clone --no-local src dst 
+   (
+   cd src  git checkout HEAD^0
+   )
+}
+
+test_expect_success setup '
+   : create template repository
+   test_commit A 
+   test_commit B 
+   test_commit C
+'
+
+test_expect_success 'push to update (protected)' '
+   setup_srcdst_basic 
+   (
+   cd dst 
+   test_commit D 
+   test_must_fail git push --force-with-lease=master:master origin 
master
+   ) 
+   git ls-remote . refs/heads/master expect 
+   git ls-remote src refs/heads/master actual 
+   test_cmp expect actual
+'
+
+test_expect_success 'push to update (protected, forced)' '
+   setup_srcdst_basic 
+   (
+   cd dst 
+   test_commit D 
+   git push --force --force-with-lease=master:master origin master
+   ) 
+   git ls-remote dst refs/heads/master expect 
+   git ls-remote src refs/heads/master actual 
+   test_cmp expect actual
+'
+
+test_expect_success 'push to update (protected, tracking)' '
+   setup_srcdst_basic 
+   (
+   cd src 
+   git checkout master 
+   test_commit D 
+   git checkout HEAD^0
+   ) 
+   git ls-remote src refs/heads/master expect 
+   (
+   cd dst 
+   test_commit E 
+   git ls-remote . refs/remotes/origin/master expect 
+   test_must_fail git push --force-with-lease=master origin master 

+   git ls-remote . refs/remotes/origin/master actual 
+   test_cmp expect actual
+   ) 
+   git ls-remote src refs/heads/master actual 
+   test_cmp expect actual
+'
+
+test_expect_success 'push to update (protected, tracking, forced)' '
+   setup_srcdst_basic 
+   (
+   cd src 
+   git checkout master 
+   test_commit D 
+   git checkout HEAD^0
+   ) 
+   (
+   cd dst 
+   test_commit E 
+   git ls-remote . refs/remotes/origin/master expect 
+   git push --force --force-with-lease=master origin master
+   ) 
+   git ls-remote dst refs/heads/master expect 
+   git ls-remote src refs/heads/master actual 
+   test_cmp expect actual
+'
+
+test_expect_success 'push to update (allowed)' '
+   setup_srcdst_basic 
+   (
+   cd dst 
+   test_commit D 
+   git push --force-with-lease=master:master^ origin master
+   ) 
+   git ls-remote dst refs/heads/master expect 
+   git ls-remote src refs/heads/master actual 
+   test_cmp expect actual
+'
+
+test_expect_success 'push to update (allowed, tracking)' '
+   setup_srcdst_basic 
+   (
+   cd dst 
+   test_commit D 
+   git push --force-with-lease=master origin master
+   ) 
+   git ls-remote dst refs/heads/master expect 
+   git ls-remote src refs/heads/master actual 
+   test_cmp expect actual
+'
+
+test_expect_success 'push to update (allowed even though no-ff)' '
+   setup_srcdst_basic 
+   (
+   cd dst 
+   git reset --hard HEAD^ 
+   test_commit D 
+   git push --force-with-lease=master origin master
+   ) 
+   git ls-remote dst refs/heads/master expect 
+   git ls-remote src refs/heads/master actual 
+   test_cmp expect actual
+'
+
+test_expect_success 'push to delete (protected)' '
+   setup_srcdst_basic 
+   git ls-remote src refs/heads/master expect 
+   (
+   cd dst 
+   test_must_fail git push --force-with-lease=master:master^ 
origin :master
+   ) 
+   git ls-remote src refs/heads/master actual 
+   test_cmp expect actual
+'
+
+test_expect_success 'push to delete (protected, forced)' '
+   setup_srcdst_basic 
+   (
+   cd dst 
+   git push --force --force-with-lease=master:master^ origin 
:master
+   ) 
+   expect 
+   git ls-remote src refs/heads/master actual 
+   test_cmp expect actual
+'
+
+test_expect_success 'push to delete (allowed)' '
+   setup_srcdst_basic 
+   (
+   cd 

[PATCH v3 3/6] remote.c: add command line option parser for --force-with-lease

2013-07-23 Thread Junio C Hamano
Update git push and git send-pack to parse this commnd line
option.

The intended sematics is:

 * --force-with-lease alone, without specifying the details, will
   protect _all_ remote refs that are going to be updated by
   requiring their current value to be the same as some reasonable
   default, unless otherwise specified;

 * --force-with-lease=refname, without specifying the expected
   value, will protect that refname, if it is going to be updated,
   by requiring its current value to be the same as some reasonable
   default.

 * --force-with-lease=refname:value will protect that refname, if
   it is going to be updated, by requiring its current value to be
   the same as the specified value; and

 * --no-force-with-lease will cancel all the previous --force-with-lease on 
the
   command line.

For now, some reasonable default is tentatively defined as the
value of the remote-tracking branch we have for the ref of the
remote being updated, and it is an error if we do not have such a
remote-tracking branch.  But this is known to be fragile, its use is
not yet recommended, and hopefully we will find more reasonable
default as we gain experience with this feature.  The manual marks
the feature as experimental unless the expected value is specified
explicitly for this reason.

Because the command line options are parsed _before_ we know which
remote we are pushing to, there needs further processing to the
parsed data after we instantiate the transport object to:

 * expand refname given by the user to a full refname to be
   matched with the list of struct ref used in match_push_refs()
   and set_ref_status_for_push(); and

 * learning the actual local ref that is the remote-tracking branch
   for the specified remote ref.

Further, some processing need to be deferred until we find the set
of remote refs and match_push_refs() returns in order to find the
ones that need to be checked after explicit ones have been processed
for --force-with-lease (no specific details).

These post-processing will be the topic of the next patch.

This option was originally called cas (for compare and swap),
the name which nobody liked because it was too technical.  The
second attempt called it lockref (because it is conceptually like
pushing after taking a lock) but the word lock was hated because
it implied that it may reject push by others, which is not the way
this option works.  This round calls it force-with-lease.  You
assume you took the lease on the ref when you fetched to decide what
the rebased history should be, and you can push back only if the
lease has not been broken.

Signed-off-by: Junio C Hamano gits...@pobox.com
---
 Documentation/git-push.txt | 77 +++---
 builtin/push.c |  6 
 builtin/send-pack.c| 17 ++
 remote.c   | 57 ++
 remote.h   | 22 +
 5 files changed, 168 insertions(+), 11 deletions(-)

diff --git a/Documentation/git-push.txt b/Documentation/git-push.txt
index f7dfe48..e2992f1 100644
--- a/Documentation/git-push.txt
+++ b/Documentation/git-push.txt
@@ -11,6 +11,7 @@ SYNOPSIS
 [verse]
 'git push' [--all | --mirror | --tags] [--follow-tags] [-n | --dry-run] 
[--receive-pack=git-receive-pack]
   [--repo=repository] [-f | --force] [--prune] [-v | --verbose] [-u 
| --set-upstream]
+  [--force-with-lease[=refname[:expect]]]
   [--no-verify] [repository [refspec...]]
 
 DESCRIPTION
@@ -130,21 +131,75 @@ already exists on the remote side.
repository over ssh, and you do not have the program in
a directory on the default $PATH.
 
+--[no-]force-with-lease::
+--force-with-lease=refname::
+--force-with-lease=refname:expect::
+   Usually, git push refuses to update a remote ref that is
+   not an ancestor of the local ref used to overwrite it.
++
+This option bypasses the check, but instead requires that the
+current value of the ref to be the expected value.  git push
+fails otherwise.
++
+Imagine that you have to rebase what you have already published.
+You will have to bypass the must fast-forward rule in order to
+replace the history you originally published with the rebased history.
+If somebody else built on top of your original history while you are
+rebasing, the tip of the branch at the remote may advance with her
+commit, and blindly pushing with `--force` will lose her work.
++
+This option allows you to say that you expect the history you are
+updating is what you rebased and want to replace. If the remote ref
+still points at the commit you specified, you can be sure that no
+other people did anything to the ref (it is like taking a lease on
+the ref without explicitly locking it, and you update the ref while
+making sure that your earlier lease is still valid).
++
+`--force-with-lease` alone, without specifying the details, will protect
+all remote refs that are going to be updated by requiring 

Re: What's cooking in git.git (Jul 2013, #03; Tue, 9)

2013-07-23 Thread Ramkumar Ramachandra
Junio C Hamano wrote:
 * mv/merge-ff-tristate (2013-07-02) 1 commit
   (merged to 'next' on 2013-07-09 at c32b95d)
  + merge: handle --ff/--no-ff/--ff-only as a tri-state option

Sorry I didn't notice sooner, but I was confused by the second test
title this added:

test_expect_success 'option --ff-only overwrites merge.ff=only config' '
git reset --hard c0 
test_config merge.ff only 
git merge --no-ff c1
'

How is --ff-only overwriting merge.ff=only here?  Was it a typo?

-- 8 --
diff --git a/t/t7600-merge.sh b/t/t7600-merge.sh
index 3ff5fb8..aea8137 100755
--- a/t/t7600-merge.sh
+++ b/t/t7600-merge.sh
@@ -502,7 +502,7 @@ test_expect_success 'option --ff-only overwrites --no-ff' '
test_must_fail git merge --no-ff --ff-only c2
 '

-test_expect_success 'option --ff-only overwrites merge.ff=only config' '
+test_expect_success 'option --no-ff overwrites merge.ff=only config' '
git reset --hard c0 
test_config merge.ff only 
git merge --no-ff c1
--
To unsubscribe from this list: send the line 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] log: use true parents for diff even when rewriting

2013-07-23 Thread Thomas Rast
Junio C Hamano gits...@pobox.com writes:

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

 When using pathspec filtering in combination with diff-based log
 output, parent simplification happens before the diff is computed.
 The diff is therefore against the *simplified* parents.

 This works okay, arguably by accident, in the normal case: the pruned
 commits did not affect the paths being filtered, so the diff against
 the prune-result is the same as against the diff against the true
 parents.

 However, --full-diff breaks this guarantee, and indeed gives pretty
 spectacular results when comparing the output of

   git log --graph --stat ...
   git log --graph --full-diff --stat ...

 (--graph internally kicks in parent simplification, much like
 --parents).

Hmm, I stopped writing the message midway through.  There should be
another two paragraphs here about storing the original parent list on
the side for later use when showing the diff.

 Perhaps like this.  It's getting a bit late, so I'm not sure if I'm
 missing another user of the true parent list, but it does fix the
 issue you reported.

 Conceptually I can see how this will change the history
 simplification in the vertical direction (skipping the ancestry
 chain and jumping directly to the closest grandparent that touched
 the specified path), but I am not sure how well this interacts with
 history simplification in the horizontal direciton (culling
 irrelevant side branches from the merge).

But isn't that similarly confusing for the user as Uwe's original
problem?  Suddenly we'd be showing a merge commit as an ordinary one,
simply because the merged history did not affect the filtered
pathspecs.  Thus we would show everything that has been merged on the
*other* files as a big diff.  Would that be useful?  It would certainly
be a big difference in how the commit is shown.

 I also have to wonder if we always want to incur this save-parents
 overhead, or we are better off limiting it to only when --full-diff
 is in effect.

I haven't quite convinced myself that it is 100% safe to use the
rewritten parents when --full-diff is not in effect...

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


Re: [PATCH] log: use true parents for diff even when rewriting

2013-07-23 Thread Uwe Kleine-König
Hello Thomas,

On Tue, Jul 23, 2013 at 09:27:06AM +0200, Thomas Rast wrote:
 Junio C Hamano gits...@pobox.com writes:
  Conceptually I can see how this will change the history
  simplification in the vertical direction (skipping the ancestry
  chain and jumping directly to the closest grandparent that touched
  the specified path), but I am not sure how well this interacts with
  history simplification in the horizontal direciton (culling
  irrelevant side branches from the merge).
 
 But isn't that similarly confusing for the user as Uwe's original
 problem?  Suddenly we'd be showing a merge commit as an ordinary one,
 simply because the merged history did not affect the filtered
 pathspecs.  Thus we would show everything that has been merged on the
 *other* files as a big diff.  Would that be useful?  It would certainly
 be a big difference in how the commit is shown.
the merge is only included in the output if on both parent paths the
file is touched. So this is a non-issue, isn't it? (Well, only if it has
more than 2 parents and not all ancestor paths touch the file, the
number of parents shown is changed.)

Best regards
Uwe

-- 
Pengutronix e.K.   | Uwe Kleine-König|
Industrial Linux Solutions | http://www.pengutronix.de/  |
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: What's cooking in git.git (Jul 2013, #03; Tue, 9)

2013-07-23 Thread Miklos Vajna
Hi,

On Tue, Jul 23, 2013 at 12:53:25PM +0530, Ramkumar Ramachandra 
artag...@gmail.com wrote:
 Junio C Hamano wrote:
  * mv/merge-ff-tristate (2013-07-02) 1 commit
(merged to 'next' on 2013-07-09 at c32b95d)
   + merge: handle --ff/--no-ff/--ff-only as a tri-state option
 
 Sorry I didn't notice sooner, but I was confused by the second test
 title this added:
 
 test_expect_success 'option --ff-only overwrites merge.ff=only config' '
   git reset --hard c0 
   test_config merge.ff only 
   git merge --no-ff c1
 '
 
 How is --ff-only overwriting merge.ff=only here?  Was it a typo?

Yes, it's a typo in the test name. Thanks for spotting that!

Miklos


signature.asc
Description: Digital signature


[PATCH] rm: do not set a variable twice without intermediate reading.

2013-07-23 Thread Stefan Beller
Just the next line assigns a non-null value to seen.

Signed-off-by: Stefan Beller stefanbel...@googlemail.com
---
 builtin/rm.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/builtin/rm.c b/builtin/rm.c
index 5b63d3f..df85f98 100644
--- a/builtin/rm.c
+++ b/builtin/rm.c
@@ -316,7 +316,6 @@ int cmd_rm(int argc, const char **argv, const char *prefix)
parse_pathspec(pathspec, 0, PATHSPEC_PREFER_CWD, prefix, argv);
refresh_index(the_index, REFRESH_QUIET, pathspec, NULL, NULL);
 
-   seen = NULL;
seen = xcalloc(pathspec.nr, 1);
 
for (i = 0; i  active_nr; i++) {
-- 
1.8.3.3.1135.ge2c9e63

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


Re: [PATCH v3 0/6]

2013-07-23 Thread Jakub Narebski
Junio C Hamano gitster at pobox.com writes:

 
 This is mostly unchanged since the previous round, except that
 
  * The option is spelled --force-with-lease=ref:expect.
Nobody liked cas as it was too technical, many disliked
lockref because lock sounded as if push by others were
excluded by it while in fact this is to fail us.

Perhaps --force-gently ? :-)

-- 
Jakub Narębski

--
To unsubscribe from this list: send the line 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] open_istream: remove unneeded check for null pointer

2013-07-23 Thread Stefan Beller
'st' is allocated via xmalloc a few lines before and passed to
the stream opening functions.
The xmalloc function is written in a way that either 'st' is allocated
valid memory or xmalloc already dies.
The function calls to open_istream_* do not change 'st', as the pointer is
passed by reference and not a pointer of a pointer.

Hence 'st' cannot be null at that part of the code.

Signed-off-by: Stefan Beller stefanbel...@googlemail.com
---
 streaming.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/streaming.c b/streaming.c
index acc07a6..debe904 100644
--- a/streaming.c
+++ b/streaming.c
@@ -144,17 +144,17 @@ struct git_istream *open_istream(const unsigned char 
*sha1,
 
st = xmalloc(sizeof(*st));
if (open_istream_tbl[src](st, oi, real, type)) {
if (open_istream_incore(st, oi, real, type)) {
free(st);
return NULL;
}
}
-   if (st  filter) {
+   if (filter) {
/* Add  !is_null_stream_filter(filter) for performance */
struct git_istream *nst = attach_stream_filter(st, filter);
if (!nst)
close_istream(st);
st = nst;
}
 
*size = st-size;
-- 
1.8.3.3.1135.ge2c9e63

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


[PATCH 1/5] range-set: fix sort_and_merge_range_set() corner case bug

2013-07-23 Thread Eric Sunshine
When handed an empty range_set (range_set.nr == 0),
sort_and_merge_range_set() incorrectly sets range_set.nr to 1 at exit.
Subsequent range_set functions then access the bogus range at element
zero and crash or throw an assertion failure. Fix this bug.

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

This bug could have been fixed with a simple conditional rather than
changing the for() loop to start at 0. I did it this way, however,
because the next fix (range-set: satisfy non-empty ranges invariant)
also needs the for() loop starting at 0. Thus, by changing the for()
loop here, the subsequent fix becomes much more obvious and easy to
read.

 line-log.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/line-log.c b/line-log.c
index 8cc29a0..5234879 100644
--- a/line-log.c
+++ b/line-log.c
@@ -110,12 +110,12 @@ static void range_set_check_invariants(struct range_set 
*rs)
 static void sort_and_merge_range_set(struct range_set *rs)
 {
int i;
-   int o = 1; /* output cursor */
+   int o = 0; /* output cursor */
 
qsort(rs-ranges, rs-nr, sizeof(struct range), range_cmp);
 
-   for (i = 1; i  rs-nr; i++) {
-   if (rs-ranges[i].start = rs-ranges[o-1].end) {
+   for (i = 0; i  rs-nr; i++) {
+   if (o  0  rs-ranges[i].start = rs-ranges[o-1].end) {
if (rs-ranges[o-1].end  rs-ranges[i].end)
rs-ranges[o-1].end = rs-ranges[i].end;
} else {
-- 
1.8.3.4.1120.gc240c48

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


[PATCH 4/5] t4211: demonstrate crash when first -L encountered is empty range

2013-07-23 Thread Eric Sunshine
Signed-off-by: Eric Sunshine sunsh...@sunshineco.com
---
 t/t4211-line-log.sh | 5 +
 1 file changed, 5 insertions(+)

diff --git a/t/t4211-line-log.sh b/t/t4211-line-log.sh
index 12814c0..7616365 100755
--- a/t/t4211-line-log.sh
+++ b/t/t4211-line-log.sh
@@ -72,4 +72,9 @@ test_expect_success '-L {empty-range} (any -L)' '
git log -L1,1:b.c -L$n:b.c
 '
 
+test_expect_failure '-L {empty-range} (first -L)' '
+   n=$(expr $(cat b.c | wc -l) + 1) 
+   git log -L$n:b.c
+'
+
 test_done
-- 
1.8.3.4.1120.gc240c48

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


[PATCH 2/5] t4211: demonstrate empty -L range crash

2013-07-23 Thread Eric Sunshine
Signed-off-by: Eric Sunshine sunsh...@sunshineco.com
---
 t/t4211-line-log.sh | 8 
 1 file changed, 8 insertions(+)

diff --git a/t/t4211-line-log.sh b/t/t4211-line-log.sh
index 7776f93..1db1edd 100755
--- a/t/t4211-line-log.sh
+++ b/t/t4211-line-log.sh
@@ -64,4 +64,12 @@ test_bad_opts -L 1,1000:b.c has only.*lines
 test_bad_opts -L :b.c argument.*not of the form
 test_bad_opts -L :foo:b.c no match
 
+# There is a separate bug when an empty -L range is the first -L encountered,
+# thus to demonstrate this particular bug, the empty -L range must follow a
+# non-empty -L range.
+test_expect_failure '-L {empty-range} (any -L)' '
+   n=$(expr $(cat b.c | wc -l) + 1) 
+   git log -L1,1:b.c -L$n:b.c
+'
+
 test_done
-- 
1.8.3.4.1120.gc240c48

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


[PATCH 3/5] range-set: satisfy non-empty ranges invariant

2013-07-23 Thread Eric Sunshine
range-set invariants are: ranges must be (1) non-empty, (2) disjoint,
(3) sorted in ascending order.

During processing, various range-set utility functions break the
invariants (for instance, by adding empty ranges), with the
expectation that a finalizing sort_and_merge_range_set() will restore
sanity.

sort_and_merge_range_set(), however, neglects to fold out empty
ranges, thus it fails to satisfy the non-empty constraint. Subsequent
range-set functions crash or throw an assertion failure upon
encountering such an anomaly. Rectify the situation by having
sort_and_merge_range_set() fold out empty ranges.

Signed-off-by: Eric Sunshine sunsh...@sunshineco.com
---
 line-log.c  | 2 ++
 t/t4211-line-log.sh | 2 +-
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/line-log.c b/line-log.c
index 5234879..6f94d56 100644
--- a/line-log.c
+++ b/line-log.c
@@ -115,6 +115,8 @@ static void sort_and_merge_range_set(struct range_set *rs)
qsort(rs-ranges, rs-nr, sizeof(struct range), range_cmp);
 
for (i = 0; i  rs-nr; i++) {
+   if (rs-ranges[i].start == rs-ranges[i].end)
+   continue;
if (o  0  rs-ranges[i].start = rs-ranges[o-1].end) {
if (rs-ranges[o-1].end  rs-ranges[i].end)
rs-ranges[o-1].end = rs-ranges[i].end;
diff --git a/t/t4211-line-log.sh b/t/t4211-line-log.sh
index 1db1edd..12814c0 100755
--- a/t/t4211-line-log.sh
+++ b/t/t4211-line-log.sh
@@ -67,7 +67,7 @@ test_bad_opts -L :foo:b.c no match
 # There is a separate bug when an empty -L range is the first -L encountered,
 # thus to demonstrate this particular bug, the empty -L range must follow a
 # non-empty -L range.
-test_expect_failure '-L {empty-range} (any -L)' '
+test_expect_success '-L {empty-range} (any -L)' '
n=$(expr $(cat b.c | wc -l) + 1) 
git log -L1,1:b.c -L$n:b.c
 '
-- 
1.8.3.4.1120.gc240c48

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


[PATCH 5/5] line-log: fix log -LN crash when N is last line of file

2013-07-23 Thread Eric Sunshine
range-set invariants are: ranges must be (1) non-empty, (2) disjoint,
(3) sorted in ascending order.

line_log_data_insert() breaks the non-empty invariant under the
following conditions: the incoming range is empty and the pathname
attached to the range has not yet been encountered. In this case,
line_log_data_insert() assigns the empty range to a new line_log_data
record without taking any action to ensure that the empty range is
eventually folded out.  Subsequent range-set functions crash or throw an
assertion failure upon encountering such an anomaly.  Fix this bug.

Signed-off-by: Eric Sunshine sunsh...@sunshineco.com
---
 line-log.c  | 1 +
 t/t4211-line-log.sh | 2 +-
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/line-log.c b/line-log.c
index 6f94d56..c2d01dc 100644
--- a/line-log.c
+++ b/line-log.c
@@ -299,6 +299,7 @@ static void line_log_data_insert(struct line_log_data 
**list,
p = xcalloc(1, sizeof(struct line_log_data));
p-path = path;
range_set_append(p-ranges, begin, end);
+   sort_and_merge_range_set(p-ranges);
if (ip) {
p-next = ip-next;
ip-next = p;
diff --git a/t/t4211-line-log.sh b/t/t4211-line-log.sh
index 7616365..94267d7 100755
--- a/t/t4211-line-log.sh
+++ b/t/t4211-line-log.sh
@@ -72,7 +72,7 @@ test_expect_success '-L {empty-range} (any -L)' '
git log -L1,1:b.c -L$n:b.c
 '
 
-test_expect_failure '-L {empty-range} (first -L)' '
+test_expect_success '-L {empty-range} (first -L)' '
n=$(expr $(cat b.c | wc -l) + 1) 
git log -L$n:b.c
 '
-- 
1.8.3.4.1120.gc240c48

--
To unsubscribe from this list: send the line 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 05/16] fetch-pack: support fetching from a shallow repository

2013-07-23 Thread Duy Nguyen
On Tue, Jul 23, 2013 at 9:06 AM, Duy Nguyen pclo...@gmail.com wrote:
 Another is reject new shallow history (i.e.
 no additions to .git/shallow) unless the user explicitly asks so
 either via --depth or a new option --shallow. This does not mean that
 fetching from a shallow clone always fails without either of those
 options.

The above was at pack level when I wrote that, although I think, from
the user perspective, rejecting at ref level makes more sense. That is
if a fetch request returns one ref update with incremental updates and
one with new shallow history, instead of rejecting the whole request,
we reject the second ref update and accept the first one.
--
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 0/5] range-set and line-log bug fixes

2013-07-23 Thread Thomas Rast
Eric Sunshine sunsh...@sunshineco.com writes:

 While implementing multiple -L support for git-blame, I encountered
 several bugs in range-set and line-log resulting in crashes. This
 series fixes those bugs.

Acked-by: Thomas Rast tr...@inf.ethz.ch

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


Re: [PATCH gitk 0/4] gitk support for git log -L

2013-07-23 Thread Thomas Rast
Thomas Rast tr...@inf.ethz.ch writes:

 Now that git log -L has hit master, I figure it's time to discuss the
 corresponding change to gitk.

Paul, any news on this?  Any chance we can get it into the next release,
since that will also be the first release to ship with 'git log -L'?

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


Re: What's cooking in git.git (Jul 2013, #03; Tue, 9)

2013-07-23 Thread Junio C Hamano
Miklos Vajna vmik...@suse.cz writes:

 How is --ff-only overwriting merge.ff=only here?  Was it a typo?

 Yes, it's a typo in the test name. Thanks for spotting that!

Thanks, will do this:

Subject: [PATCH] t7600: fix typo in test title

Spotted by Ram, confirmed by Miklos.

Signed-off-by: Junio C Hamano gits...@pobox.com
---
 t/t7600-merge.sh | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/t/t7600-merge.sh b/t/t7600-merge.sh
index 3ff5fb8..10aa028 100755
--- a/t/t7600-merge.sh
+++ b/t/t7600-merge.sh
@@ -502,7 +502,7 @@ test_expect_success 'option --ff-only overwrites --no-ff' '
test_must_fail git merge --no-ff --ff-only c2
 '
 
-test_expect_success 'option --ff-only overwrites merge.ff=only config' '
+test_expect_success 'option --no-ff overrides merge.ff=only config' '
git reset --hard c0 
test_config merge.ff only 
git merge --no-ff c1
-- 
1.8.3.4-985-g5661af8

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


Re: [PATCH 2/5] t4211: demonstrate empty -L range crash

2013-07-23 Thread SZEDER Gábor
On Tue, Jul 23, 2013 at 10:28:05AM -0400, Eric Sunshine wrote:
 Signed-off-by: Eric Sunshine sunsh...@sunshineco.com
 ---
  t/t4211-line-log.sh | 8 
  1 file changed, 8 insertions(+)
 
 diff --git a/t/t4211-line-log.sh b/t/t4211-line-log.sh
 index 7776f93..1db1edd 100755
 --- a/t/t4211-line-log.sh
 +++ b/t/t4211-line-log.sh
 @@ -64,4 +64,12 @@ test_bad_opts -L 1,1000:b.c has only.*lines
  test_bad_opts -L :b.c argument.*not of the form
  test_bad_opts -L :foo:b.c no match
  
 +# There is a separate bug when an empty -L range is the first -L encountered,
 +# thus to demonstrate this particular bug, the empty -L range must follow a
 +# non-empty -L range.
 +test_expect_failure '-L {empty-range} (any -L)' '
 + n=$(expr $(cat b.c | wc -l) + 1) 

You could avoid the 'cat' here and patch in 4/5 by doing $(wc -l b.c).

(Side question: the test suite is full with similar constructs, i.e.
redirecting file contents to stdin, but why not just use wc -l b.c,
i.e. let wc open the file?)

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


Re: [PATCH v2 3/3] Update po/ja.po

2013-07-23 Thread Junio C Hamano
Yamada Saburo devil.tamac...@gmail.com writes:

 -#: git-gui.sh:2893
 +#: git-gui.sh:2983 git-gui.sh:3115
 +msgid Usage
 +msgstr 使用状況
 Is this correct?  I am not familiar with the context this string
 appears, but shouldn't it be 使い方?

 It is a title of the error box which does not have seeing mostly.
 Therefore, I do not understand.
 However, If you wish, it can correct with you yourself another patch later.

Untranslated Usage may be understood many Japanese computer users,
but if that label is to show How to Use, then 使用状況 (whose
literal back-translation is Usage Status) is a label that makes
things worse, I think. Between this translation and leaving it
untranslated, we may even be better off with the latter.

As the objective of our discussion is to make git-gui's translated
messages better, I _will_ point out an iffy translation that may
make things worse.  It does not have anything to do with what I
wish.

 -#: lib/choose_repository.tcl:490
 +#: lib/choose_repository.tcl:489
  msgid Target Directory:
 -msgstr 先ディレクトリ:
 +msgstr 保存ディレクトリ:
 I think this is better translation than the original (the Target is
 about where the new clone appears), but a few lines above we see
 Source Location, which may want to be reworded.  Perhaps
 クローン元リポジトリ
 クローン先リポジトリ
 ???

 保存ディレクトリ(Save Directory) is better. 先ディレクトリ is very bad.

I already said the original is bad, no?  Cloning to a new place is
different from Save, and that is why I found that word 保存
iffy.

In short, the translated text is far more alarming than the original
phrasing.

 Is free translation impossible?

What do you mean free translation?  Apparently you do not mean
free as in free beer, as we are both doing these on our own
time, not as a paid task.

Do you mean I can do whatever I, Yamada Saburo, wish to do?

It almost appears to me that your position is that any words, as
long as they are written in Japanese, are better than leaving them
in English, even if they are misleading.  I do not think that helps
our users.

The list discussion is somebody posts a patch, other people eyeball
and suggest improvements, and they collaborate to reach a good
result.  I am involved in the review of this patch not as the Git
maintainer but as somebody who happens to read Japanese, so as I
already said, what I wish does not matter much---what matters is
that the result does not make things worse than leaving them in the
original, untranslated.

I only commented on points in your patch that looked misleading to
those who only get the translated Japanese, without commenting on
others.
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v3 0/6]

2013-07-23 Thread Junio C Hamano
Jakub Narebski jna...@gmail.com writes:

 Junio C Hamano gitster at pobox.com writes:

 
 This is mostly unchanged since the previous round, except that
 
  * The option is spelled --force-with-lease=ref:expect.
Nobody liked cas as it was too technical, many disliked
lockref because lock sounded as if push by others were
excluded by it while in fact this is to fail us.

 Perhaps --force-gently ? :-)

Hmph.  But we usually use gently to mean do not give the end user
an error message--the caller handles the error itself.

While the option lets you break the usual must fast-forward rule,
it is more precise in that the remote ref must be pointing at not
just any ancestor of what you are pushing, but has to be at the
exact commit you specify.

E.g. if you have built one commit on top of the shared branch, and
try to push it with push --cas=pu:HEAD^ HEAD:pu (because you know
one commit before the tip is where you started from), your push will
be rejected if somebody else did an equivalent of reset HEAD~3 on
the receiving end (perhaps because the top commits recorded some
material inappropriate for the project).  Your new commit is still a
decendant of that rewound tip, and usual must fast-forward rule
would accept the push, but with push --cas=pu:HEAD^ HEAD:pu, you
will notice that somebody wanted to rewind the tip and pushing your
work that contains these dropped commit contradicts with that wish.

So I dunno.
--
To unsubscribe from this list: send the line 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] rm: do not set a variable twice without intermediate reading.

2013-07-23 Thread Junio C Hamano
Stefan Beller stefanbel...@googlemail.com writes:

 Just the next line assigns a non-null value to seen.

 Signed-off-by: Stefan Beller stefanbel...@googlemail.com
 ---
  builtin/rm.c | 1 -
  1 file changed, 1 deletion(-)

 diff --git a/builtin/rm.c b/builtin/rm.c
 index 5b63d3f..df85f98 100644
 --- a/builtin/rm.c
 +++ b/builtin/rm.c
 @@ -316,7 +316,6 @@ int cmd_rm(int argc, const char **argv, const char 
 *prefix)
   parse_pathspec(pathspec, 0, PATHSPEC_PREFER_CWD, prefix, argv);
   refresh_index(the_index, REFRESH_QUIET, pathspec, NULL, NULL);
  
 - seen = NULL;
   seen = xcalloc(pathspec.nr, 1);
  
   for (i = 0; i  active_nr; i++) {

Interesting. This is ancient and dates back to 7612a1ef (git-rm:
honor -n flag., 2006-06-08).

--
To unsubscribe from this list: send the line 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] rm: do not set a variable twice without intermediate reading.

2013-07-23 Thread Stefan Beller
On 07/23/2013 08:32 PM, Junio C Hamano wrote:
 Stefan Beller stefanbel...@googlemail.com writes:
 
 Just the next line assigns a non-null value to seen.

 Signed-off-by: Stefan Beller stefanbel...@googlemail.com
 ---
  builtin/rm.c | 1 -
  1 file changed, 1 deletion(-)

 diff --git a/builtin/rm.c b/builtin/rm.c
 index 5b63d3f..df85f98 100644
 --- a/builtin/rm.c
 +++ b/builtin/rm.c
 @@ -316,7 +316,6 @@ int cmd_rm(int argc, const char **argv, const char 
 *prefix)
  parse_pathspec(pathspec, 0, PATHSPEC_PREFER_CWD, prefix, argv);
  refresh_index(the_index, REFRESH_QUIET, pathspec, NULL, NULL);
  
 -seen = NULL;
  seen = xcalloc(pathspec.nr, 1);
  
  for (i = 0; i  active_nr; i++) {
 
 Interesting. This is ancient and dates back to 7612a1ef (git-rm:
 honor -n flag., 2006-06-08).
 

Well the removed line itself maybe, but the next line ... as well.

The next line seen = xcalloc(...) was introduced in 29211a93c14
(2013-07-14) and was changed 4 or 5 times before (changing the
the malloc function to xmalloc and then to xcalloc.
I suppose these changes did not pay attention to the local area
around, but rather were interested in making the memory allocation
fast or safe in many places.


Originally it comes from d9b814cc97 (by Linus), which introduced:
+   seen = NULL;
+   if (pathspec) {
+   for (i = 0; pathspec[i] ; i++)
+   /* nothing */;
+   seen = xmalloc(i);
+   memset(seen, 0, i);
+   }

Then in 7612a1efdb0c the second seen assignment was made unconditional.
And since then it has been not noticed. ;)

However that being said, I am currently playing around with different
code analyzers (find dead code, possible null pointers, and such),
and the coding style of git is very different to what I am used to
(and what the tools are used to as well, lots of false positives).

Personally the coding style of git often reminds me to 'C as a
macro-assembler' rather than 'C as a high level programming
language'.

Stefan




--
To unsubscribe from this list: send the line 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] rm: do not set a variable twice without intermediate reading.

2013-07-23 Thread Junio C Hamano
Stefan Beller stefanbel...@googlemail.com writes:

 On 07/23/2013 08:32 PM, Junio C Hamano wrote:
 Interesting. This is ancient and dates back to 7612a1ef (git-rm:
 honor -n flag., 2006-06-08).
 Originally it comes from d9b814cc97 (by Linus), which introduced:
 + seen = NULL;
 + if (pathspec) {
 + for (i = 0; pathspec[i] ; i++)
 + /* nothing */;
 + seen = xmalloc(i);
 + memset(seen, 0, i);
 + }

 Then in 7612a1efdb0c the second seen assignment was made unconditional.

That is why I blamed the bug to 7612a1ef.  Before that, without pathspec,
directory traversal function were told not to report which ones were
seen and which ones were not by passing seen=NULL.


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


Re: [PATCH 2/5] t4211: demonstrate empty -L range crash

2013-07-23 Thread Junio C Hamano
SZEDER Gábor sze...@ira.uka.de writes:

 You could avoid the 'cat' here and patch in 4/5 by doing $(wc -l b.c).

Correct.

 (Side question: the test suite is full with similar constructs, i.e.
 redirecting file contents to stdin, but why not just use wc -l b.c,
 i.e. let wc open the file?)

wc -l b.c is the correct form for the purpose of these tests;
otherwise you will see the filename in the output, and you need to
somehow strip it if you are only interested in the line count.
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


getting git from kernel.org is failing

2013-07-23 Thread Stefan Beller
git clone https://git.kernel.org/cgit/git/git.git
Cloning into 'git'...
error: Unable to get pack index 
https://git.kernel.org/cgit/git/git.git/objects/pack/pack-1e2bca8b5127039cff42b1cd3d47767fb577cd4f.idx
error: Unable to get pack file 
https://git.kernel.org/cgit/git/git.git/objects/pack/pack-6bfd3af75af71d7bf66a80d6374ac09245ad3ce5.pack
The requested URL returned error: 404 Not found
error: Unable to find bce6db96a333c2d47b07580c5a9207cf10935378 under 
https://git.kernel.org/cgit/git/git.git
Cannot obtain needed blob bce6db96a333c2d47b07580c5a9207cf10935378
while processing commit 5addd1c7531cc644787cd562a3c22a3b714c7d77.
error: Fetch failed.

as reported by ivegy on freenode/#git-devel

Stefan



signature.asc
Description: OpenPGP digital signature


Re: [PATCH v2 15/16] config: add core.noshallow to prevent turning a repo into a shallow one

2013-07-23 Thread Philip Oakley

From: Duy Nguyen pclo...@gmail.com
Sent: Tuesday, July 23, 2013 2:28 AM
On Tue, Jul 23, 2013 at 2:23 AM, Philip Oakley philipoak...@iee.org 
wrote:

From: Nguyễn Thái Ngọc Duy pclo...@gmail.com
Subject: [PATCH v2 15/16] config: add core.noshallow to prevent 
turning a

repo into a shallow one

Surely this should be the default now that it is possible to corrupt 
a
golden repo by pushing/fetching a shallow repository to it and it 
then

becomes shallow, and all the followers become shallow as well, with
consequent problems (IIUC) [PATCH v2 05/16].

It would be just as easy to change the config to core.allowshallow 
which
then must be enabled by the user, and can be mentioned in the shallow 
clone

option's documentation.


Clarification, it's not really corrupt. If you have full history
from a ref A, fetching from another shallow clone does not touch the
history of ref A at all



  (that is if you do _not_ specify --depth).


I hadn't appreciated this conditional.

It
may add a a shallow ref B, which is the reason the whole repo becomes
shallow.
I had read the initial commit message (in 05/16) as implying that it was 
possible to fool someone into pulling a shallow repo and that would make 
their repo just as shallow (that's without a --depth argument to the 
command). Had that been the case then it would have been possible to 
loose some data from deep in the DAG. Glad to hear I was mistaken. 
Perhaps if your comment above is included in the commit message to 
ensure that clarification is there.



The same goes for push. This is not implemented, but I'm
thinking of adding clean .git/shallow to git repack -ad. Then if you
delete ref B and repack -ad, the repo could become full again.

But yeah, maybe defaulting to no shallow is better. Will do so in the
reroll unless someone objects.
--
Duy
--
Philip 


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


Re: [PATCH] log: use true parents for diff even when rewriting

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

 +define_commit_slab(saved_parents, struct commit_list *);
 +struct saved_parents saved_parents_slab;
 +static int saved_parents_initialized;
 +
 +void save_parents(struct commit *commit)
 +{
 + struct commit_list **pp;
 +
 + if (!saved_parents_initialized) {
 + init_saved_parents(saved_parents_slab);
 + saved_parents_initialized = 1;
 + }
 +
 + pp = saved_parents_at(saved_parents_slab, commit);
 + assert(*pp == NULL);
 + *pp = copy_commit_list(commit-parents);
 +}
 +
 +struct commit_list *get_saved_parents(struct commit *commit)

Use const struct commit * here, as combine-diff.c has a const pointer.

 +{
 + if (!saved_parents_initialized)
 + return commit-parents;
 +
 + return *saved_parents_at(saved_parents_slab, commit);
 +}

clear_commit_slab() is not used, failing -Wunused -Werror compilation.

 diff --git a/revision.h b/revision.h
 index 95859ba..0717518 100644
 --- a/revision.h
 +++ b/revision.h
 @@ -273,4 +273,19 @@ enum rewrite_result {
  
  extern int rewrite_parents(struct rev_info *revs, struct commit *commit,
   rewrite_parent_fn_t rewrite_parent);
 +
 +/*
 + * Save a copy of the parent list, and return the saved copy.  This is
 + * used by the log machinery to retrieve the original parents when
 + * commit-parents has been modified by history simpification.
 + *
 + * You may only call save_parents() once per commit (this is checked
 + * for non-root commits).
 + *
 + * get_original_parents() will transparently return commit-parents if
 + * history simplification is off.
 + */
 +extern void save_parents(struct commit *commit);
 +extern struct commit_list *get_original_parents(struct commit *commit);
 +

s/_original/_saved/ here, and const struct commit *.

By the way, when the only single parameter is a named type, you can
safely omit the name of the parameter from the declaration without
losing clarity.

  #endif
 diff --git a/t/t6012-rev-list-simplify.sh b/t/t6012-rev-list-simplify.sh
 index 57ce239..fde5e71 100755
 --- a/t/t6012-rev-list-simplify.sh
 +++ b/t/t6012-rev-list-simplify.sh
 @@ -127,4 +127,10 @@ test_expect_success 'full history simplification without 
 parent' '
   }
  '
  
 +test_expect_success '--full-diff is not affected by --parents' '
 + git log -p --pretty=%H --full-diff -- file expected 
 + git log -p --pretty=%H --full-diff --parents -- file actual 
 + test_cmp expected actual
 +'
 +
  test_done
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: getting git from kernel.org is failing

2013-07-23 Thread Fredrik Gustafsson
On Tue, Jul 23, 2013 at 09:41:44PM +0200, Stefan Beller wrote:
 git clone https://git.kernel.org/cgit/git/git.git
 Cloning into 'git'...
 error: Unable to get pack index 
 https://git.kernel.org/cgit/git/git.git/objects/pack/pack-1e2bca8b5127039cff42b1cd3d47767fb577cd4f.idx
 error: Unable to get pack file 
 https://git.kernel.org/cgit/git/git.git/objects/pack/pack-6bfd3af75af71d7bf66a80d6374ac09245ad3ce5.pack
 The requested URL returned error: 404 Not found
 error: Unable to find bce6db96a333c2d47b07580c5a9207cf10935378 under 
 https://git.kernel.org/cgit/git/git.git
 Cannot obtain needed blob bce6db96a333c2d47b07580c5a9207cf10935378
 while processing commit 5addd1c7531cc644787cd562a3c22a3b714c7d77.
 error: Fetch failed.
 
 as reported by ivegy on freenode/#git-devel
 
 Stefan
 

Confirmed (tested both with and without trailing /, IIRC there was some
configuration change recently that effect that):
iveqy@kolya:~/slask/git$ git clone
https://git.kernel.org/cgit/git/git.git/
Klonar till git...
error: Unable to get pack index
https://git.kernel.org/cgit/git/git.git/objects/pack/pack-1e2bca8b5127039cff42b1cd3d47767fb577cd4f.idx
^C
iveqy@kolya:~/slask/git$ git clone
https://git.kernel.org/cgit/git/git.git
Klonar till git...
error: Unable to get pack index
https://git.kernel.org/cgit/git/git.git/objects/pack/pack-1e2bca8b5127039cff42b1cd3d47767fb577cd4f.idx
error: Unable to find d6b65e204c6009e5c30f358810198319b70eda25 under
https://git.kernel.org/cgit/git/git.git
Cannot obtain needed blob d6b65e204c6009e5c30f358810198319b70eda25
while processing commit 5addd1c7531cc644787cd562a3c22a3b714c7d77.
error: Fetch failed.
fatal: Reading from helper 'git-remote-https' failed
iveqy@kolya:~/slask/git$ 


-- 
Med vänliga hälsningar
Fredrik Gustafsson

tel: 0733-608274
e-post: iv...@iveqy.com
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 2/5] t4211: demonstrate empty -L range crash

2013-07-23 Thread SZEDER Gábor
On Tue, Jul 23, 2013 at 12:03:05PM -0700, Junio C Hamano wrote:
 SZEDER Gábor sze...@ira.uka.de writes:
  (Side question: the test suite is full with similar constructs, i.e.
  redirecting file contents to stdin, but why not just use wc -l b.c,
  i.e. let wc open the file?)
 
 wc -l b.c is the correct form for the purpose of these tests;
 otherwise you will see the filename in the output, and you need to
 somehow strip it if you are only interested in the line count.

Facepalm, that should have been obvious...

--
To unsubscribe from this list: send the line 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: getting git from kernel.org is failing

2013-07-23 Thread Jeff King
On Tue, Jul 23, 2013 at 10:06:05PM +0200, Fredrik Gustafsson wrote:

 Confirmed (tested both with and without trailing /, IIRC there was some
 configuration change recently that effect that):
 iveqy@kolya:~/slask/git$ git clone
 https://git.kernel.org/cgit/git/git.git/
 Klonar till git...
 error: Unable to get pack index
 https://git.kernel.org/cgit/git/git.git/objects/pack/pack-1e2bca8b5127039cff42b1cd3d47767fb577cd4f.idx

That's weird. We shouldn't be fetching an index at all unless dumb http
is in use. When I try to clone from the URL above, I also get shunted to
dumb-http (and the repo on the server appears to be poorly packed).

But if I go to:

  https://git.kernel.org/pub/scm/git/git.git

then smart HTTP works fine. I wonder if there is a problem in the cgit
setup on kernel.org (or if it was even intended that you could fetch
from the cgit URL at all; the cgit page shows the clone URLs in
/pub/scm/git).

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


Re: getting git from kernel.org is failing

2013-07-23 Thread Jonathan Nieder
Jeff King wrote:

 then smart HTTP works fine. I wonder if there is a problem in the cgit
 setup on kernel.org (or if it was even intended that you could fetch
 from the cgit URL at all; the cgit page shows the clone URLs in
 /pub/scm/git).

I didn't think cgit URLs were meant to be clonable, but since
ls-remote works on them, it seems I thought wrong. :)  Odd.

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


[PATCH] http: Add http.savecookies option to write out HTTP cookies

2013-07-23 Thread dborowitz
From: Dave Borowitz dborow...@google.com

HTTP servers may send Set-Cookie headers in a response and expect them
to be set on subsequent requests. By default, libcurl behavior is to
store such cookies in memory and reuse them across requests within a
single session. However, it may also make sense, depending on the
server and the cookies, to store them across sessions. Provide users
an option to enable this behavior, writing cookies out to the same
file specified in http.cookiefile.
---
 Documentation/config.txt |  6 +-
 http.c   |  7 +++
 t/lib-httpd/apache.conf  |  8 
 t/t5551-http-fetch.sh| 18 ++
 4 files changed, 38 insertions(+), 1 deletion(-)

diff --git a/Documentation/config.txt b/Documentation/config.txt
index e0b923f..e935447 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -1456,7 +1456,11 @@ http.cookiefile::
of the file to read cookies from should be plain HTTP headers or
the Netscape/Mozilla cookie file format (see linkgit:curl[1]).
NOTE that the file specified with http.cookiefile is only used as
-   input. No cookies will be stored in the file.
+   input unless http.saveCookies is set.
+
+http.savecookies::
+   If set, store cookies received during requests to the file specified by
+   http.cookiefile. Has no effect if http.cookiefile is unset.
 
 http.sslVerify::
Whether to verify the SSL certificate when fetching or pushing
diff --git a/http.c b/http.c
index 2d086ae..2fbf986 100644
--- a/http.c
+++ b/http.c
@@ -45,6 +45,7 @@ static long curl_low_speed_time = -1;
 static int curl_ftp_no_epsv;
 static const char *curl_http_proxy;
 static const char *curl_cookie_file;
+static int curl_save_cookies;
 static struct credential http_auth = CREDENTIAL_INIT;
 static int http_proactive_auth;
 static const char *user_agent;
@@ -200,6 +201,10 @@ static int http_options(const char *var, const char 
*value, void *cb)
 
if (!strcmp(http.cookiefile, var))
return git_config_string(curl_cookie_file, var, value);
+   if (!strcmp(http.savecookies, var)) {
+   curl_save_cookies = git_config_bool(var, value);
+   return 0;
+   }
 
if (!strcmp(http.postbuffer, var)) {
http_post_buffer = git_config_int(var, value);
@@ -513,6 +518,8 @@ struct active_request_slot *get_active_slot(void)
slot-callback_data = NULL;
slot-callback_func = NULL;
curl_easy_setopt(slot-curl, CURLOPT_COOKIEFILE, curl_cookie_file);
+   if (curl_save_cookies)
+   curl_easy_setopt(slot-curl, CURLOPT_COOKIEJAR, 
curl_cookie_file);
curl_easy_setopt(slot-curl, CURLOPT_HTTPHEADER, pragma_header);
curl_easy_setopt(slot-curl, CURLOPT_ERRORBUFFER, curl_errorstr);
curl_easy_setopt(slot-curl, CURLOPT_CUSTOMREQUEST, NULL);
diff --git a/t/lib-httpd/apache.conf b/t/lib-httpd/apache.conf
index dd17e3a..397c480 100644
--- a/t/lib-httpd/apache.conf
+++ b/t/lib-httpd/apache.conf
@@ -22,6 +22,9 @@ ErrorLog error.log
 IfModule !mod_version.c
LoadModule version_module modules/mod_version.so
 /IfModule
+IfModule !mod_headers.c
+   LoadModule headers_module modules/mod_headers.so
+/IfModule
 
 IfVersion  2.4
 LockFile accept.lock
@@ -87,6 +90,11 @@ Alias /auth/dumb/ www/auth/dumb/
SetEnv GIT_HTTP_EXPORT_ALL
SetEnv GIT_NAMESPACE ns
 /LocationMatch
+LocationMatch /smart_cookies/
+   SetEnv GIT_EXEC_PATH ${GIT_EXEC_PATH}
+   SetEnv GIT_HTTP_EXPORT_ALL
+   Header set Set-Cookie name=value
+/LocationMatch
 ScriptAliasMatch /smart_*[^/]*/(.*) ${GIT_EXEC_PATH}/git-http-backend/$1
 ScriptAlias /broken_smart/ broken-smart-http.sh/
 Directory ${GIT_EXEC_PATH}
diff --git a/t/t5551-http-fetch.sh b/t/t5551-http-fetch.sh
index 55a866a..287d22b 100755
--- a/t/t5551-http-fetch.sh
+++ b/t/t5551-http-fetch.sh
@@ -187,6 +187,24 @@ test_expect_success 'dumb clone via http-backend respects 
namespace' '
test_cmp expect actual
 '
 
+cat cookies.txt EOF
+127.0.0.1  FALSE   /smart_cookies/ FALSE   0   othername   
othervalue
+EOF
+cat expect_cookies.txt EOF
+# Netscape HTTP Cookie File
+# http://curl.haxx.se/docs/http-cookies.html
+# This file was generated by libcurl! Edit at your own risk.
+
+127.0.0.1  FALSE   /smart_cookies/ FALSE   0   othername   
othervalue
+127.0.0.1  FALSE   /smart_cookies/repo.git/info/   FALSE   0   name
value
+EOF
+test_expect_success 'cookies stored in http.cookiefile when http.savecookies 
set' '
+   git config http.cookiefile cookies.txt 
+   git config http.savecookies true 
+   git ls-remote $HTTPD_URL/smart_cookies/repo.git master 
+   test_cmp expect_cookies.txt cookies.txt
+'
+
 test -n $GIT_TEST_LONG  test_set_prereq EXPENSIVE
 
 test_expect_success EXPENSIVE 'create 50,000 tags in the repo' '
-- 
1.8.3.2

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

Re: getting git from kernel.org is failing

2013-07-23 Thread John Keeping
On Tue, Jul 23, 2013 at 01:40:05PM -0700, Jonathan Nieder wrote:
 Jeff King wrote:
 
  then smart HTTP works fine. I wonder if there is a problem in the cgit
  setup on kernel.org (or if it was even intended that you could fetch
  from the cgit URL at all; the cgit page shows the clone URLs in
  /pub/scm/git).
 
 I didn't think cgit URLs were meant to be clonable, but since
 ls-remote works on them, it seems I thought wrong. :)  Odd.

CGit has a config option enable-http-clone which causes it to act as
an endpoint for the dumb HTTP protocol.  That option defaults to on,
so I suspect that kernel.org has just left it at the default.
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v3 0/6]

2013-07-23 Thread Philip Oakley

From: Junio C Hamano gits...@pobox.com
Sent: Tuesday, July 23, 2013 7:26 PM

Jakub Narebski jna...@gmail.com writes:


Junio C Hamano gitster at pobox.com writes:



This is mostly unchanged since the previous round, except that

 * The option is spelled --force-with-lease=ref:expect.
   Nobody liked cas as it was too technical, many disliked
   lockref because lock sounded as if push by others were
   excluded by it while in fact this is to fail us.


Perhaps --force-gently ? :-)


Or --force-carefully to better indicate the safety / care that is 
being applied?




Hmph.  But we usually use gently to mean do not give the end user
an error message--the caller handles the error itself.

While the option lets you break the usual must fast-forward rule,
it is more precise in that the remote ref must be pointing at not
just any ancestor of what you are pushing, but has to be at the
exact commit you specify.

E.g. if you have built one commit on top of the shared branch, and
try to push it with push --cas=pu:HEAD^ HEAD:pu (because you know
one commit before the tip is where you started from), your push will
be rejected if somebody else did an equivalent of reset HEAD~3 on
the receiving end (perhaps because the top commits recorded some
material inappropriate for the project).  Your new commit is still a
decendant of that rewound tip, and usual must fast-forward rule
would accept the push, but with push --cas=pu:HEAD^ HEAD:pu, you
will notice that somebody wanted to rewind the tip and pushing your
work that contains these dropped commit contradicts with that wish.

So I dunno.
--


--
To unsubscribe from this list: send the line 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] [SIGNED-OFF] remotes-hg: bugfix for fetching non local remotes

2013-07-23 Thread Joern Hees
6796d49 introduced a bug by making shared_path == .git/hg' which
will most likely exist already, causing a new remote never to be
cloned and subsequently causing hg.share to fail with error msg:
mercurial.error.RepoError: repository .git/hg not found

Changing gitdir to dirname causes shared_path ==
.git/hg/remote_name/hg. The call to hg.share with local_path ==
.git/hg/remote_name/clone works again.

Signed-off-by: Joern Hees d...@joernhees.de
---
 contrib/remote-helpers/git-remote-hg | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/contrib/remote-helpers/git-remote-hg 
b/contrib/remote-helpers/git-remote-hg
index 0194c67..89dd4cc 100755
--- a/contrib/remote-helpers/git-remote-hg
+++ b/contrib/remote-helpers/git-remote-hg
@@ -390,7 +390,7 @@ def get_repo(url, alias):
 if not os.path.exists(dirname):
 os.makedirs(dirname)
 else:
-shared_path = os.path.join(gitdir, 'hg')
+shared_path = os.path.join(dirname, 'hg')
 if not os.path.exists(shared_path):
 try:
 hg.clone(myui, {}, url, shared_path, update=False, pull=True)
-- 
1.8.3.3

--
To unsubscribe from this list: send the line 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] web--browse: support /usr/bin/cygstart on Cygwin

2013-07-23 Thread Yaakov (Cygwin/X)

On 2013-06-21 11:06, Junio C Hamano wrote:

From: Yaakov Selkowitz yselkow...@users.sourceforge.net

While both GUI and console Cygwin browsers do exist, anecdotal evidence
suggests most users rely on their native Windows browser.  cygstart,
which is a long-standing part of the base Cygwin installation, will
cause the page to be opened in the default Windows browser (the one
registered to open .html files).

Signed-off-by: Yaakov Selkowitz yselkow...@users.sourceforge.net


Will queue and wait for somebody from Cygwin land to comment.


Ping?  Is there someone in particular whose input you are looking for?


Yaakov

--
To unsubscribe from this list: send the line 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 00/16] First class shallow clone

2013-07-23 Thread Philip Oakley

From: Duy Nguyen pclo...@gmail.com
Sent: Tuesday, July 23, 2013 2:20 AM
On Tue, Jul 23, 2013 at 6:41 AM, Philip Oakley philipoak...@iee.org 
wrote:

From: Nguyễn Thái Ngọc Duy pclo...@gmail.com
Subject: [PATCH v2 00/16] First class shallow clone

It's nice to see that shallow can be a first class clone.

Thinking outside the box, does this infrastructure offer the 
opportunity to

maybe add a date based depth option that would establish the shallow
watermark based on date rather than count. (e.g. the deepen SP 
depth could


I've been carefully avoiding the deepen issues because, as you see,
it's complicated. But no, this series does not enable or disable new
deeepen mechanisms. They can always be added as protocol extensions.
Still thinking if it's worth exposing a (restricted form of) rev-list
to the protocol..


Interesting idea.


have an alternate with a leading 'T' to indicate a time limit ratherv 
than
revision count - I'm expecting such a format would be an error for 
existing

servers).

My other thought was this style of cut limit list may also allow a 
big file
limit to do a similar process of listing objects (e.g. blobs) that 
are
size-shallow in the repo, though it maybe a long list on some repos, 
or with

a small size limit.


This one, on the other hand, changes the shape of the repo (now with
holes) and might need to go through the same process we do with this
series. Maybe we should prepare for it now. Do you have a use case for
size-based filtering? What can we do with a repo with some arbitrary
blobs missing? Another form of this is narrow clone, where we cut by
paths, not by blob size. Narrow clone sounds more useful to me because
it's easier to control what we leave out.


In some sense a project with a sub-module is a narrow clone, split at a 
'commit' object. There have been comments on the git-user list about the 
problem of accidental adding of large files which then make the repo's 
foot print pretty large as one use case [Git is consuming very much 
RAM]. The bigFileThreshold being one way of spotting such files as 
separate objects, and 'trimming' them.


It doesn't feel right to 'track files and directories` as paths for 
doing a narrow clone - it'd probably fall into the same trap as tracking 
file renames. However if one tracks trees and blobs (as a list of sha1 
values, possibly with their source path) then it should it should be 
possible to allow work on the repo with those empty directories/files in 
the same manner as is used for sub-modules, possibly with some form of 
git-link file as an alternate marker.


The thought process is to map sub-module working onto the other object 
types (blobs and trees). The user would be unable to edit the trimmed 
files/directories anyway, so its sha1 value can't change, allowing it to 
be included in the next commit in the branch series.


Philip


--
Duy
--


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


[PATCH] Documentation/git-clean: fix description for range

2013-07-23 Thread Jiang Xin
The descriptions of select by numbers section for interactive
git-clean are borrowed from git-add, and one sentence should be
replaced.

Signed-off-by: Jiang Xin worldhello@gmail.com
---
 Documentation/git-clean.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Documentation/git-clean.txt b/Documentation/git-clean.txt
index 75fb543..8997922 100644
--- a/Documentation/git-clean.txt
+++ b/Documentation/git-clean.txt
@@ -111,7 +111,7 @@ select by numbers::
'' like this, you can make more than one selection, concatenated
with whitespace or comma.  Also you can say ranges.  E.g. 2-5 7,9
to choose 2,3,4,5,7,9 from the list.  If the second number in a
-   range is omitted, all remaining patches are taken.  E.g. 7- to
+   range is omitted, all remaining items are selected.  E.g. 7- to
choose 7,8,9 from the list.  You can say '*' to choose everything.
Also when you are satisfied with the filtered result, press ENTER
(empty) back to the main menu.
-- 
1.8.3.2.1052.g3a6d627

--
To unsubscribe from this list: send the line 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] http: Add http.savecookies option to write out HTTP cookies

2013-07-23 Thread dborowitz
From: Dave Borowitz dborow...@google.com

HTTP servers may send Set-Cookie headers in a response and expect them
to be set on subsequent requests. By default, libcurl behavior is to
store such cookies in memory and reuse them across requests within a
single session. However, it may also make sense, depending on the
server and the cookies, to store them across sessions. Provide users
an option to enable this behavior, writing cookies out to the same
file specified in http.cookiefile.

Signed-off-by: Dave Borowitz dborow...@google.com
---
 Documentation/config.txt |  6 +-
 http.c   |  7 +++
 t/lib-httpd/apache.conf  |  8 
 t/t5551-http-fetch.sh| 18 ++
 4 files changed, 38 insertions(+), 1 deletion(-)

diff --git a/Documentation/config.txt b/Documentation/config.txt
index e0b923f..e935447 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -1456,7 +1456,11 @@ http.cookiefile::
of the file to read cookies from should be plain HTTP headers or
the Netscape/Mozilla cookie file format (see linkgit:curl[1]).
NOTE that the file specified with http.cookiefile is only used as
-   input. No cookies will be stored in the file.
+   input unless http.saveCookies is set.
+
+http.savecookies::
+   If set, store cookies received during requests to the file specified by
+   http.cookiefile. Has no effect if http.cookiefile is unset.
 
 http.sslVerify::
Whether to verify the SSL certificate when fetching or pushing
diff --git a/http.c b/http.c
index 2d086ae..2fbf986 100644
--- a/http.c
+++ b/http.c
@@ -45,6 +45,7 @@ static long curl_low_speed_time = -1;
 static int curl_ftp_no_epsv;
 static const char *curl_http_proxy;
 static const char *curl_cookie_file;
+static int curl_save_cookies;
 static struct credential http_auth = CREDENTIAL_INIT;
 static int http_proactive_auth;
 static const char *user_agent;
@@ -200,6 +201,10 @@ static int http_options(const char *var, const char 
*value, void *cb)
 
if (!strcmp(http.cookiefile, var))
return git_config_string(curl_cookie_file, var, value);
+   if (!strcmp(http.savecookies, var)) {
+   curl_save_cookies = git_config_bool(var, value);
+   return 0;
+   }
 
if (!strcmp(http.postbuffer, var)) {
http_post_buffer = git_config_int(var, value);
@@ -513,6 +518,8 @@ struct active_request_slot *get_active_slot(void)
slot-callback_data = NULL;
slot-callback_func = NULL;
curl_easy_setopt(slot-curl, CURLOPT_COOKIEFILE, curl_cookie_file);
+   if (curl_save_cookies)
+   curl_easy_setopt(slot-curl, CURLOPT_COOKIEJAR, 
curl_cookie_file);
curl_easy_setopt(slot-curl, CURLOPT_HTTPHEADER, pragma_header);
curl_easy_setopt(slot-curl, CURLOPT_ERRORBUFFER, curl_errorstr);
curl_easy_setopt(slot-curl, CURLOPT_CUSTOMREQUEST, NULL);
diff --git a/t/lib-httpd/apache.conf b/t/lib-httpd/apache.conf
index dd17e3a..397c480 100644
--- a/t/lib-httpd/apache.conf
+++ b/t/lib-httpd/apache.conf
@@ -22,6 +22,9 @@ ErrorLog error.log
 IfModule !mod_version.c
LoadModule version_module modules/mod_version.so
 /IfModule
+IfModule !mod_headers.c
+   LoadModule headers_module modules/mod_headers.so
+/IfModule
 
 IfVersion  2.4
 LockFile accept.lock
@@ -87,6 +90,11 @@ Alias /auth/dumb/ www/auth/dumb/
SetEnv GIT_HTTP_EXPORT_ALL
SetEnv GIT_NAMESPACE ns
 /LocationMatch
+LocationMatch /smart_cookies/
+   SetEnv GIT_EXEC_PATH ${GIT_EXEC_PATH}
+   SetEnv GIT_HTTP_EXPORT_ALL
+   Header set Set-Cookie name=value
+/LocationMatch
 ScriptAliasMatch /smart_*[^/]*/(.*) ${GIT_EXEC_PATH}/git-http-backend/$1
 ScriptAlias /broken_smart/ broken-smart-http.sh/
 Directory ${GIT_EXEC_PATH}
diff --git a/t/t5551-http-fetch.sh b/t/t5551-http-fetch.sh
index 55a866a..287d22b 100755
--- a/t/t5551-http-fetch.sh
+++ b/t/t5551-http-fetch.sh
@@ -187,6 +187,24 @@ test_expect_success 'dumb clone via http-backend respects 
namespace' '
test_cmp expect actual
 '
 
+cat cookies.txt EOF
+127.0.0.1  FALSE   /smart_cookies/ FALSE   0   othername   
othervalue
+EOF
+cat expect_cookies.txt EOF
+# Netscape HTTP Cookie File
+# http://curl.haxx.se/docs/http-cookies.html
+# This file was generated by libcurl! Edit at your own risk.
+
+127.0.0.1  FALSE   /smart_cookies/ FALSE   0   othername   
othervalue
+127.0.0.1  FALSE   /smart_cookies/repo.git/info/   FALSE   0   name
value
+EOF
+test_expect_success 'cookies stored in http.cookiefile when http.savecookies 
set' '
+   git config http.cookiefile cookies.txt 
+   git config http.savecookies true 
+   git ls-remote $HTTPD_URL/smart_cookies/repo.git master 
+   test_cmp expect_cookies.txt cookies.txt
+'
+
 test -n $GIT_TEST_LONG  test_set_prereq EXPENSIVE
 
 test_expect_success EXPENSIVE 'create 50,000 tags in the repo' '
-- 
1.8.3.2

--
To unsubscribe from this list: 

Re: [PATCH] http: Add http.savecookies option to write out HTTP cookies

2013-07-23 Thread Junio C Hamano
dborow...@google.com writes:

 From: Dave Borowitz dborow...@google.com

 HTTP servers may send Set-Cookie headers in a response and expect them
 to be set on subsequent requests. By default, libcurl behavior is to
 store such cookies in memory and reuse them across requests within a
 single session. However, it may also make sense, depending on the
 server and the cookies, to store them across sessions. Provide users
 an option to enable this behavior, writing cookies out to the same
 file specified in http.cookiefile.
 ---

Makes sense.

I briefly wondered if users want to be able to selectively store
cookies only from certain sites but not from others.  But if we are
going to build this on top of Kyle J. McKay's Per URL http.url.* 
configuration series, that will fall out as a natural consequence,
I think.

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


Re: [PATCH 2/5] t4211: demonstrate empty -L range crash

2013-07-23 Thread Eric Sunshine
On Tue, Jul 23, 2013 at 3:03 PM, Junio C Hamano gits...@pobox.com wrote:
 SZEDER Gábor sze...@ira.uka.de writes:
 You could avoid the 'cat' here and patch in 4/5 by doing $(wc -l b.c).
 Correct.

Thanks, I like that better.

Unfortunately, what actually got queued on 'next', after applying this
fix-up and re-ordering the patch series, is slightly bogus.  The diff
for f8395edc (range-set: satisfy non-empty ranges invariant) looks
like this:

@@ -67,7 +67,8 @@ test_bad_opts -L :foo:b.c no match
 # There is a separate bug when an empty -L range is the first -L encountered,
 # thus to demonstrate this particular bug, the empty -L range must follow a
 # non-empty -L range.
-test_expect_failure '-L {empty-range} (any -L)' '
+test_expect_success '-L {empty-range} (any -L)' '
+ n=$(expr $(cat b.c | wc -l) + 1) 
  n=$(expr $(wc -l b.c) + 1) 
  git log -L1,1:b.c -L$n:b.c
 '

which incorrectly adds back the $(cat b.c | wc -l) line just above the
fixed $(wc -l b.c) line.
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v3 0/6]

2013-07-23 Thread Eric Sunshine
On Tue, Jul 23, 2013 at 5:26 PM, Philip Oakley philipoak...@iee.org wrote:
 From: Junio C Hamano gits...@pobox.com
 Sent: Tuesday, July 23, 2013 7:26 PM
 Jakub Narebski jna...@gmail.com writes:
 Junio C Hamano gitster at pobox.com writes:
 This is mostly unchanged since the previous round, except that

  * The option is spelled --force-with-lease=ref:expect.
Nobody liked cas as it was too technical, many disliked
lockref because lock sounded as if push by others were
excluded by it while in fact this is to fail us.

 Perhaps --force-gently ? :-)

 Or --force-carefully to better indicate the safety / care that is being
 applied?

[bike-shedding: on]

--force-if-safe

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


Incompatible '+=' syntax in git-completion.bash

2013-07-23 Thread Matthew Wang
Hi there,

I noticed a change in commit 734b2f0 on
contrib/completion/git-completion.bash which reverted a syntax fix for
'+=' syntax [1], the syntax does not work for bash  3.1.  As far as I
know, bash 3.0.x is still widely used on some old servers, could
someone add the fix back again?

Thanks,
Matt

[1] 
https://github.com/git/git/commit/734b2f0532d847a9f566183982f83ddea8d8d197#commitcomment-3664571
--
To unsubscribe from this list: send the line 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 00/16] First class shallow clone

2013-07-23 Thread Duy Nguyen
On Wed, Jul 24, 2013 at 5:33 AM, Philip Oakley philipoak...@iee.org wrote:
 In some sense a project with a sub-module is a narrow clone, split at a
 'commit' object.

Yes, except narrow clone is more flexible. You have to decide the
split boundary at commit time for sub-module, while you decide the
same at clone time for narrow clone.

 There have been comments on the git-user list about the
 problem of accidental adding of large files which then make the repo's foot
 print pretty large as one use case [Git is consuming very much RAM]. The
 bigFileThreshold being one way of spotting such files as separate objects,
 and 'trimming' them.

I think rewriting history to remove those accidents is better than
working around it (the same for accidentally committing password). We
might be able to spot problems early, maybe warn user at commit time
that they have added an exceptionally large blob, maybe before push
time..

The Git is consuming very much RAM part is not right. We try to keep
memory usage under a limit regardless of the size of a blob. There may
be some cases we haven't fixed yet. Reports are welcome.
-- 
Duy
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] git-clean: implement partial matching for selection

2013-07-23 Thread Jiang Xin
Document for interactive git-clean says: You also could say `c` or
`clean` above as long as the choice is unique. But it's not true,
because only hotkey `c` and full match (`clean`) could work.

Implement partial matching via find_unique function to make the
document right.

Signed-off-by: Jiang Xin worldhello@gmail.com
---
 builtin/clean.c  | 80 
 t/t7301-clean-interactive.sh | 41 +--
 2 files changed, 91 insertions(+), 30 deletions(-)

diff --git a/builtin/clean.c b/builtin/clean.c
index dba8387..3c85e15 100644
--- a/builtin/clean.c
+++ b/builtin/clean.c
@@ -365,6 +365,56 @@ static void print_highlight_menu_stuff(struct menu_stuff 
*stuff, int **chosen)
string_list_clear(menu_list, 0);
 }
 
+static int find_unique(const char *choice, struct menu_stuff *menu_stuff)
+{
+   struct menu_item *menu_item;
+   struct string_list_item *string_list_item;
+   int i, len, found = 0;
+
+   len = strlen(choice);
+   switch (menu_stuff-type) {
+   default:
+   die(Bad type of menu_stuff when parse choice);
+   case MENU_STUFF_TYPE_MENU_ITEM:
+
+   menu_item = (struct menu_item *)menu_stuff-stuff;
+   for (i = 0; i  menu_stuff-nr; i++, menu_item++) {
+   if (len == 1  *choice == menu_item-hotkey) {
+   found = i + 1;
+   break;
+   }
+   if (!strncasecmp(choice, menu_item-title, len)) {
+   if (found) {
+   if (len == 1) {
+   /* continue for hotkey matching 
*/
+   found = -1;
+   } else {
+   found = 0;
+   break;
+   }
+   } else {
+   found = i + 1;
+   }
+   }
+   }
+   break;
+   case MENU_STUFF_TYPE_STRING_LIST:
+   string_list_item = ((struct string_list 
*)menu_stuff-stuff)-items;
+   for (i = 0; i  menu_stuff-nr; i++, string_list_item++) {
+   if (!strncasecmp(choice, string_list_item-string, 
len)) {
+   if (found) {
+   found = 0;
+   break;
+   }
+   found = i + 1;
+   }
+   }
+   break;
+   }
+   return found;
+}
+
+
 /*
  * Parse user input, and return choice(s) for menu (menu_stuff).
  *
@@ -392,8 +442,6 @@ static int parse_choice(struct menu_stuff *menu_stuff,
int **chosen)
 {
struct strbuf **choice_list, **ptr;
-   struct menu_item *menu_item;
-   struct string_list_item *string_list_item;
int nr = 0;
int i;
 
@@ -457,32 +505,8 @@ static int parse_choice(struct menu_stuff *menu_stuff,
bottom = 1;
top = menu_stuff-nr;
} else {
-   switch (menu_stuff-type) {
-   default:
-   die(Bad type of menu_stuff when parse choice);
-   case MENU_STUFF_TYPE_MENU_ITEM:
-   menu_item = (struct menu_item 
*)menu_stuff-stuff;
-   for (i = 0; i  menu_stuff-nr; i++, 
menu_item++) {
-   if (((*ptr)-len == 1 
-*(*ptr)-buf == menu_item-hotkey) 
||
-   !strcasecmp((*ptr)-buf, 
menu_item-title)) {
-   bottom = i + 1;
-   top = bottom;
-   break;
-   }
-   }
-   break;
-   case MENU_STUFF_TYPE_STRING_LIST:
-   string_list_item = ((struct string_list 
*)menu_stuff-stuff)-items;
-   for (i = 0; i  menu_stuff-nr; i++, 
string_list_item++) {
-   if (!strcasecmp((*ptr)-buf, 
string_list_item-string)) {
-   bottom = i + 1;
-   top = bottom;
-   break;
-   }
-   }
-   break;
-   }
+   bottom = 

[PATCH v2] git-clean: implement partial matching for selection

2013-07-23 Thread Jiang Xin
In the 1st version of this patch, I forgot to remove a shell command for
debug in t7301:

find .  /tmp/x 

Remove the above command in this version. Sorry about this.

Jiang Xin (1):
  git-clean: implement partial matching for selection

 builtin/clean.c  | 80 
 t/t7301-clean-interactive.sh | 40 --
 2 files changed, 90 insertions(+), 30 deletions(-)

-- 
1.8.3.4.842.g8e6673c

--
To unsubscribe from this list: send the line 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] git-clean: implement partial matching for selection

2013-07-23 Thread Jiang Xin
Document for interactive git-clean says: You also could say `c` or
`clean` above as long as the choice is unique. But it's not true,
because only hotkey `c` and full match (`clean`) could work.

Implement partial matching via find_unique function to make the
document right.

Signed-off-by: Jiang Xin worldhello@gmail.com
---
 builtin/clean.c  | 80 
 t/t7301-clean-interactive.sh | 40 --
 2 files changed, 90 insertions(+), 30 deletions(-)

diff --git a/builtin/clean.c b/builtin/clean.c
index dba8387..3c85e15 100644
--- a/builtin/clean.c
+++ b/builtin/clean.c
@@ -365,6 +365,56 @@ static void print_highlight_menu_stuff(struct menu_stuff 
*stuff, int **chosen)
string_list_clear(menu_list, 0);
 }
 
+static int find_unique(const char *choice, struct menu_stuff *menu_stuff)
+{
+   struct menu_item *menu_item;
+   struct string_list_item *string_list_item;
+   int i, len, found = 0;
+
+   len = strlen(choice);
+   switch (menu_stuff-type) {
+   default:
+   die(Bad type of menu_stuff when parse choice);
+   case MENU_STUFF_TYPE_MENU_ITEM:
+
+   menu_item = (struct menu_item *)menu_stuff-stuff;
+   for (i = 0; i  menu_stuff-nr; i++, menu_item++) {
+   if (len == 1  *choice == menu_item-hotkey) {
+   found = i + 1;
+   break;
+   }
+   if (!strncasecmp(choice, menu_item-title, len)) {
+   if (found) {
+   if (len == 1) {
+   /* continue for hotkey matching 
*/
+   found = -1;
+   } else {
+   found = 0;
+   break;
+   }
+   } else {
+   found = i + 1;
+   }
+   }
+   }
+   break;
+   case MENU_STUFF_TYPE_STRING_LIST:
+   string_list_item = ((struct string_list 
*)menu_stuff-stuff)-items;
+   for (i = 0; i  menu_stuff-nr; i++, string_list_item++) {
+   if (!strncasecmp(choice, string_list_item-string, 
len)) {
+   if (found) {
+   found = 0;
+   break;
+   }
+   found = i + 1;
+   }
+   }
+   break;
+   }
+   return found;
+}
+
+
 /*
  * Parse user input, and return choice(s) for menu (menu_stuff).
  *
@@ -392,8 +442,6 @@ static int parse_choice(struct menu_stuff *menu_stuff,
int **chosen)
 {
struct strbuf **choice_list, **ptr;
-   struct menu_item *menu_item;
-   struct string_list_item *string_list_item;
int nr = 0;
int i;
 
@@ -457,32 +505,8 @@ static int parse_choice(struct menu_stuff *menu_stuff,
bottom = 1;
top = menu_stuff-nr;
} else {
-   switch (menu_stuff-type) {
-   default:
-   die(Bad type of menu_stuff when parse choice);
-   case MENU_STUFF_TYPE_MENU_ITEM:
-   menu_item = (struct menu_item 
*)menu_stuff-stuff;
-   for (i = 0; i  menu_stuff-nr; i++, 
menu_item++) {
-   if (((*ptr)-len == 1 
-*(*ptr)-buf == menu_item-hotkey) 
||
-   !strcasecmp((*ptr)-buf, 
menu_item-title)) {
-   bottom = i + 1;
-   top = bottom;
-   break;
-   }
-   }
-   break;
-   case MENU_STUFF_TYPE_STRING_LIST:
-   string_list_item = ((struct string_list 
*)menu_stuff-stuff)-items;
-   for (i = 0; i  menu_stuff-nr; i++, 
string_list_item++) {
-   if (!strcasecmp((*ptr)-buf, 
string_list_item-string)) {
-   bottom = i + 1;
-   top = bottom;
-   break;
-   }
-   }
-   break;
-   }
+   bottom =