[PATCH] dir: remove dead code

2013-09-08 Thread Ramkumar Ramachandra
Remove dead code around remove_dir_recursively().

Signed-off-by: Ramkumar Ramachandra artag...@gmail.com
---
 dir.c | 21 -
 1 file changed, 4 insertions(+), 17 deletions(-)

diff --git a/dir.c b/dir.c
index 910bfcd..2b31241 100644
--- a/dir.c
+++ b/dir.c
@@ -1464,11 +1464,11 @@ int is_empty_dir(const char *path)
return ret;
 }
 
-static int remove_dir_recurse(struct strbuf *path, int flag, int *kept_up)
+int remove_dir_recursively(struct strbuf *path, int flag)
 {
DIR *dir;
struct dirent *e;
-   int ret = 0, original_len = path-len, len, kept_down = 0;
+   int ret = 0, original_len = path-len, len;
int only_empty = (flag  REMOVE_DIR_EMPTY_ONLY);
int keep_toplevel = (flag  REMOVE_DIR_KEEP_TOPLEVEL);
unsigned char submodule_head[20];
@@ -1476,8 +1476,6 @@ static int remove_dir_recurse(struct strbuf *path, int 
flag, int *kept_up)
if ((flag  REMOVE_DIR_KEEP_NESTED_GIT) 
!resolve_gitlink_ref(path-buf, HEAD, submodule_head)) {
/* Do not descend and nuke a nested git work tree. */
-   if (kept_up)
-   *kept_up = 1;
return 0;
}
 
@@ -1504,7 +1502,7 @@ static int remove_dir_recurse(struct strbuf *path, int 
flag, int *kept_up)
if (lstat(path-buf, st))
; /* fall thru */
else if (S_ISDIR(st.st_mode)) {
-   if (!remove_dir_recurse(path, flag, kept_down))
+   if (!remove_dir_recursively(path, flag))
continue; /* happy */
} else if (!only_empty  !unlink(path-buf))
continue; /* happy, too */
@@ -1516,22 +1514,11 @@ static int remove_dir_recurse(struct strbuf *path, int 
flag, int *kept_up)
closedir(dir);
 
strbuf_setlen(path, original_len);
-   if (!ret  !keep_toplevel  !kept_down)
+   if (!ret  !keep_toplevel)
ret = rmdir(path-buf);
-   else if (kept_up)
-   /*
-* report the uplevel that it is not an error that we
-* did not rmdir() our directory.
-*/
-   *kept_up = !ret;
return ret;
 }
 
-int remove_dir_recursively(struct strbuf *path, int flag)
-{
-   return remove_dir_recurse(path, flag, NULL);
-}
-
 void setup_standard_excludes(struct dir_struct *dir)
 {
const char *path;
-- 
1.8.4.100.gde18f6d.dirty

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


Re: [PATCH 0/3] Reject non-ff pulls by default

2013-09-08 Thread Felipe Contreras
On Sun, Sep 8, 2013 at 12:21 AM, Jeff King p...@peff.net wrote:
 On Sun, Sep 08, 2013 at 12:09:34AM -0500, Felipe Contreras wrote:

  It's not if you understand the difference between merge-then-commit and
  commit-then-merge. But for a clueless user who has been told replace
  svn commit with git commit  git push and replace svn update with
  git pull, it is quite similar.

 Well, yeah, but if they are so clueless they have to be told what to
 do, they can be told to do 'git pull --merge' instead, no?

 I think it's fine to tell them to do git pull --merge. What I'd worry
 more about is somebody who is suddenly presented with the choice between
 --rebase and --merge and doesn't know which to choose. We've created a
 cognitive load on the user, and even more load if they choose --rebase
 and don't quite understand what it means.

If that happens they will go back to the guy that told them to run
those commands.

Fortunately there probably are very few of these users.

 The current warning message in jc/pull-training-wheel is quite neutral
 between the two options. Perhaps we should lean more towards merging?

I don't like that message. I would like this for the deprecation period:

The pull was not fast-forward, in the future you would have to choose
a merge or a rebase, merging automatically for now. Read 'man git
pull' for more help.

Then when obsolete:

The pull was not fast-forward, please either merge or rebase.

Any more babysitting with essay long messages is counter-productive
to the vast majority of Git users.

 I guess that works against John's case, though, which is clueless people
 working on a project that _does_ care about the shape of history. At
 least they would have to stop and think for a moment, though, which
 might help (and maybe convince them to ask more clueful project
 members). I don't know.

Or google 'git pull' 'git merge' 'git rebase' or 'git non-fast-forward'.

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


Re: [PATCH 0/3] Reject non-ff pulls by default

2013-09-08 Thread Richard Hansen
On 2013-09-07 22:41, Felipe Contreras wrote:
 On Wed, Sep 4, 2013 at 5:59 PM, Junio C Hamano gits...@pobox.com wrote:
 
 Which can be solved by adding the above fail option, and then
 renaming them to pull.integrate and branch.name.integrate to
 clarify what these variables are about (it is no longer do you
 rebase or not---if you choose not to rebase, by definition you are
 going to merge, as there is a third choice to fail), while
 retaining pull.rebase and branch.name.rebase as a deprecated
 synonym.
 
 All these names are completely unintuitive. First of all, why
 integrate? Integrate what to what? And then, why fail? Fail on
 what circumstances? Always?
 
 My proposal that does:
 
   pull.mode = merge/rebase/merge-ff-only
 
 Is way more intuitive.

+1

What about something like:

pull.mergeoptions (defaults to --ff-only)
pull.rebaseoptions (defaults to empty?  --preserve-merges?)
branch.name.pull.mergeoptions (defaults to pull.mergeoptions)
branch.name.pull.rebaseoptions (defaults to pull.rebaseoptions)

-Richard
--
To unsubscribe from this list: send the line 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] diffcore-break: fix typo in comment

2013-09-08 Thread Ramkumar Ramachandra
The parameter is called break_score, not minimum_edit.

Signed-off-by: Ramkumar Ramachandra artag...@gmail.com
---
 diffcore-break.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/diffcore-break.c b/diffcore-break.c
index 1d9e530..34dd1e0 100644
--- a/diffcore-break.c
+++ b/diffcore-break.c
@@ -37,7 +37,7 @@ static int should_break(struct diff_filespec *src,
 * back together.  The break operation itself happens
 * according to the former definition.
 *
-* The minimum_edit parameter tells us when to break (the
+* The break_score parameter tells us when to break (the
 * amount of edit required for us to consider breaking the
 * pair).  We leave the amount of deletion in *merge_score_p
 * when we return.
-- 
1.8.4.100.gde18f6d.dirty

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


Re: [PATCH v2 1/3] index-pack: add --unpack-limit to unpack objects

2013-09-08 Thread Duy Nguyen
On Sun, Sep 8, 2013 at 11:44 AM, Jeff King p...@peff.net wrote:
 On Fri, Sep 06, 2013 at 07:46:01AM +0700, Nguyen Thai Ngoc Duy wrote:

 ---
  I had something that could unpack without writing to temp pack file
  but I scraped it and chose this way because it follows closely how
  index-pack works. It's a good thing imo because .pack v4 is coming
  and I don't know how v4 may impact this unpack code path. Once things
  are settled, we can revisit and open a separate code path if it's
  still a good idea.

 From a cursory read, this seems fine. If it were done in complete
 isolation, I'd say it was a slight regression, just because we are doing
 more I/O for the unpack case, and it is not really saving us any code
 (it is not like we can throw away unpack-objects, as I think we would
 want to keep it as a last resort for getting data out of malformed or
 otherwise non-indexable packs).

I can see unpack-objects is more tolerable on corrupt/incomplete
packs. If index-pack finds something wrong, it aborts the whole
process. I think we can make index-pack stop at the first bad object,
adjust nr_objects, and try to recover as much as possible out of the
good part. Any other reasons to keep unpack-objects (because I still
want to kill it)?

 But I can also see it making pack v4 handling easier. So it would make
 sense to me to put it at the start of a series adding pack v4 indexing.
 By the end of the series you would be able to see the benefits of the
 reduced code complexity. Until then, it is a probably this will help
 later change.

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


Re: [PATCH v2 1/3] index-pack: add --unpack-limit to unpack objects

2013-09-08 Thread Jeff King
On Sun, Sep 08, 2013 at 01:28:47PM +0700, Nguyen Thai Ngoc Duy wrote:

  From a cursory read, this seems fine. If it were done in complete
  isolation, I'd say it was a slight regression, just because we are doing
  more I/O for the unpack case, and it is not really saving us any code
  (it is not like we can throw away unpack-objects, as I think we would
  want to keep it as a last resort for getting data out of malformed or
  otherwise non-indexable packs).
 
 I can see unpack-objects is more tolerable on corrupt/incomplete
 packs. If index-pack finds something wrong, it aborts the whole
 process. I think we can make index-pack stop at the first bad object,
 adjust nr_objects, and try to recover as much as possible out of the
 good part. Any other reasons to keep unpack-objects (because I still
 want to kill it)?

No, I don't think there is another reason. The command name may hang
around for historical reasons, but we can always make it an alias for
index-pack --unpack-limit=0 or whatever.

I do not think index-pack even needs to be particularly clever about
trying to recover. It is mainly that we may do some extra sanity checks
when writing the index (e.g., the recent discussion on avoiding
duplicates in the index), that do not even come up when simply exploding
the pack in a linear fashion. But I don't think there is any fundamental
reason why index-pack could not learn to be as robust when operating in
unpack mode.

As an aside, you cannot just drop the nr_objects that index-pack's
generated index says it contains. Packfile readers double-check that the
.idx and .pack agree on the number of objects (I tried it as a method
for working around duplicate entries :) ).

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


Re: [PATCH 0/3] Reject non-ff pulls by default

2013-09-08 Thread Jeff King
On Sun, Sep 08, 2013 at 01:17:42AM -0500, Felipe Contreras wrote:

  I think it's fine to tell them to do git pull --merge. What I'd worry
  more about is somebody who is suddenly presented with the choice between
  --rebase and --merge and doesn't know which to choose. We've created a
  cognitive load on the user, and even more load if they choose --rebase
  and don't quite understand what it means.
 
 If that happens they will go back to the guy that told them to run
 those commands.

I think the guy may be git itself. For example, here is a possible
session with jc/pull-training-wheel:

  $ git push
  To ...
   ! [rejected]master - master (non-fast-forward)
  error: failed to push some refs to '...'
  hint: Updates were rejected because the tip of your current branch is behind
  hint: its remote counterpart. Integrate the remote changes (e.g.
  hint: 'git pull ...') before pushing again.
  hint: See the 'Note about fast-forwards' in 'git push --help' for details.

  $ git pull
  The pull does not fast-forward; please specify
  if you want to merge or rebase.

  Use either

  git pull --rebase
  git pull --merge

  You can also use 'git config pull.rebase true' (if you want --rebase) or
  'git config pull.rebase false' (if you want --merge) to set this once for
  this project and forget about it.

The user is pointed at pull from push, and then gets presented with
the merge or rebase choice. It may be that the advice you can find by
googling merge vs rebase is enough to then help the person along
(and/or we may need to improve the manpages in that respect).

I am genuinely curious what people in favor of this feature would want
to say in the documentation to a user encountering this choice for the
first time. In my experience, rebasing introduces more complications,
specifically:

  1. the merge is backwards with respect to ours/theirs

  2. you may end up with difficult conflict resolution due to repeated
 changes over the same section of code. E.g., you write some buggy
 code and then fix it, but upstream has changed the same area.
 Rebasing involves first resolving your buggy version with the
 upstream code, and then resolving the fix on top of the previous
 resolution.

  3. rewriting of commits found in other branches, which then need
 rebased on top of the branch you just rebased

  4. a previously bug-free commit can show a bug after the rebase if
 other parts of the project changed (whereas with a merge, the bug
 would be attributable to the merge)

I know those are all balanced by some advantages of rebasing, but I also
think they are things that can be troublesome for a user who does not
fully grok the rebase process. I'm just wondering if we should mention
both, but steer people towards merging as the safer alternative (you
might have ugly history, but you are less likely to create a mess with
duplicate commits or badly-resolved conflicts).

 Fortunately there probably are very few of these users.

Maybe. I am not sure how one would measure.

If you are interested, I can ask the opinion of some of the GitHub
trainers. They see a lot of new users and have a sense of what kinds of
confusion come up most frequently, what kinds of workflows they tend to
see, etc. Their experience may be biased towards corporate-ish users,
though, because those are the people who pay for training.

  The current warning message in jc/pull-training-wheel is quite neutral
  between the two options. Perhaps we should lean more towards merging?
 
 I don't like that message. I would like this for the deprecation period:
 
 The pull was not fast-forward, in the future you would have to choose
 a merge or a rebase, merging automatically for now. Read 'man git
 pull' for more help.
 
 Then when obsolete:
 
 The pull was not fast-forward, please either merge or rebase.

A deprecation message helps people who are making the transition from an
older behavior to a newer one. It cannot help new users who start with a
git version after the deprecation period.

 Any more babysitting with essay long messages is counter-productive
 to the vast majority of Git users.

I think that is what we have advice.* for.

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


Re: [PATCH 1/3] upload-pack: send the HEAD information

2013-09-08 Thread Jeff King
On Fri, Sep 06, 2013 at 10:46:24AM -0700, Junio C Hamano wrote:

 I think it is perfectly fine to expose _only_ HEAD now, and wait
 until we find a good reason that we should send this information for
 other symbolic refs in the repository.

Yeah, I agree with that.

 However, because we already anticipate that we may find such a good
 reason later, on-the-wire format should be prepared to support such
 later enhancement.  I think sending
 
   symref=HEAD:refs/heads/master
 
 is probably one good way to do so, as Peff suggested in that old
 thread ($gmane/102070; note that back then this wasn't suggested as
 a proper capability so the exact format he suggests in the message
 is different).  Then we could later add advertisements for other
 symbolic refs if we find it necessary to do so, e.g.
 
   symref=HEAD:refs/heads/master
 symref=refs/remotes/origin/HEAD:refs/remotes/origin/master
 
 (all on one line together with other capabilities separated with a
 SP in between).

It somehow feels a little weird to me that we would output the
information about refs/foo on the HEAD line. A few possible issues (and
I am playing devil's advocate to some degree here):

  1. What if we have a large number of symrefs? Would we run afoul of
 pkt-line length limits?

  2. What's the impact of having to display all symrefs on the first
 line, before we output other refs? Right now we can just stream out
 refs as we read them, but we would have to make two passes (and/or
 cache them all) to find all of the symrefs before we start
 outputting. Will the extra latency ever matter?

What do you think about teaching git to read extra data after \0 for
_every_ ref line? And then ref advertisement might look something like:

  sha1 HEAD\0multi_ack thin-pack ... symref=refs/heads/master\n
  sha1 refs/heads/master\n
  sha1 refs/heads/my-alias\0symref=refs/heads/master

That would leave us future room for more ref annotations if we should
want them, and I think (but haven't tested) that existing receivers
should ignore everything after the NUL.

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


Re: [PATCH 0/3] Reject non-ff pulls by default

2013-09-08 Thread Felipe Contreras
On Sun, Sep 8, 2013 at 1:54 AM, Jeff King p...@peff.net wrote:
 On Sun, Sep 08, 2013 at 01:17:42AM -0500, Felipe Contreras wrote:

  I think it's fine to tell them to do git pull --merge. What I'd worry
  more about is somebody who is suddenly presented with the choice between
  --rebase and --merge and doesn't know which to choose. We've created a
  cognitive load on the user, and even more load if they choose --rebase
  and don't quite understand what it means.

 If that happens they will go back to the guy that told them to run
 those commands.

 I think the guy may be git itself. For example, here is a possible
 session with jc/pull-training-wheel:

   $ git push

Who told him to use 'git push'? Certainly not git.

   To ...
! [rejected]master - master (non-fast-forward)
   error: failed to push some refs to '...'
   hint: Updates were rejected because the tip of your current branch is behind
   hint: its remote counterpart. Integrate the remote changes (e.g.
   hint: 'git pull ...') before pushing again.
   hint: See the 'Note about fast-forwards' in 'git push --help' for details.

   $ git pull

   The pull does not fast-forward; please specify
   if you want to merge or rebase.

   Use either

   git pull --rebase
   git pull --merge

   You can also use 'git config pull.rebase true' (if you want --rebase) or
   'git config pull.rebase false' (if you want --merge) to set this once for
   this project and forget about it.

Why stop there? Post the whole man page already.

Moreover, it's overly verbose on all the wrong and irrelevant
information. If you are going to waste precious screen state, explain
wth a non fast-forward is; people can figure out what a merge is,
and maybe a rebase, but a non fast-forward definitely not.

 The user is pointed at pull from push, and then gets presented with
 the merge or rebase choice. It may be that the advice you can find by
 googling merge vs rebase is enough to then help the person along
 (and/or we may need to improve the manpages in that respect).

Yes, but that's not the use-case we are talking about. You mentioned
specifically a svn-like worfklow where the guy was told by somebody
else to replace the svn commands with git ones.

If we are talking about a guy that is learning git, that's and
entirely different case.

 I am genuinely curious what people in favor of this feature would want
 to say in the documentation to a user encountering this choice for the
 first time. In my experience, rebasing introduces more complications,
 specifically:

Yes, but it's what the user might want.

 I know those are all balanced by some advantages of rebasing, but I also
 think they are things that can be troublesome for a user who does not
 fully grok the rebase process. I'm just wondering if we should mention
 both, but steer people towards merging as the safer alternative (you
 might have ugly history, but you are less likely to create a mess with
 duplicate commits or badly-resolved conflicts).

The purpose of this change in the code is not to change the user
behavior. The choice of merge vs. rebase is entirely up to the user,
and we are not changing that.

The purpose of this change is to avoid doing a merge when the user
wanted a rebase, or maybe something more complicated. So a rebase
being complicated is not an issue, because we know that's what the
user wants, that's the whole reason we are trying to avoid the
automated merge.

 Fortunately there probably are very few of these users.

 Maybe. I am not sure how one would measure.

 If you are interested, I can ask the opinion of some of the GitHub
 trainers. They see a lot of new users and have a sense of what kinds of
 confusion come up most frequently, what kinds of workflows they tend to
 see, etc. Their experience may be biased towards corporate-ish users,
 though, because those are the people who pay for training.

Ask. I'm sure they will tell you doing merges by mistake with 'git
pull' is an issue.

  The current warning message in jc/pull-training-wheel is quite neutral
  between the two options. Perhaps we should lean more towards merging?

 I don't like that message. I would like this for the deprecation period:

 The pull was not fast-forward, in the future you would have to choose
 a merge or a rebase, merging automatically for now. Read 'man git
 pull' for more help.

 Then when obsolete:

 The pull was not fast-forward, please either merge or rebase.

 A deprecation message helps people who are making the transition from an
 older behavior to a newer one. It cannot help new users who start with a
 git version after the deprecation period.

The new users are told to either merge or rebase, if they don't know
what that means, they will go on look it up, just like they looked up
the 'git pull' command in the first place.

 Any more babysitting with essay long messages is counter-productive
 to the vast majority of Git users.

 I think that is what we have advice.* for.

I don't 

[PATCH v2 00/14] pack v4 support in index-pack

2013-09-08 Thread Nguyễn Thái Ngọc Duy
Mostly cleanups after Nico's comments. The diff against v2 is

diff --git a/builtin/index-pack.c b/builtin/index-pack.c
index 4a24bc3..88340b5 100644
--- a/builtin/index-pack.c
+++ b/builtin/index-pack.c
@@ -22,8 +22,8 @@ struct object_entry {
struct pack_idx_entry idx;
unsigned long size;
unsigned int hdr_size;
-   enum object_type type;
-   enum object_type real_type;
+   enum object_type type;  /* type as written in pack */
+   enum object_type real_type; /* type after delta resolving */
unsigned delta_depth;
int base_object_no;
int nr_bases;   /* only valid for v4 trees */
@@ -194,8 +194,10 @@ static int mark_link(struct object *obj, int type, void 
*data)
return 0;
 }
 
-/* The content of each linked object must have been checked
-   or it must be already present in the object database */
+/*
+ * The content of each linked object must have been checked or it must
+ * be already present in the object database
+ */
 static unsigned check_object(struct object *obj)
 {
if (!obj)
@@ -289,6 +291,19 @@ static inline void *fill_and_use(int bytes)
return p;
 }
 
+static void check_against_sha1table(const unsigned char *sha1)
+{
+   const unsigned char *found;
+   if (!packv4)
+   return;
+
+   found = bsearch(sha1, sha1_table, nr_objects, 20,
+   (int (*)(const void *, const void *))hashcmp);
+   if (!found)
+   die(_(object %s not found in SHA-1 table),
+   sha1_to_hex(sha1));
+}
+
 static NORETURN void bad_object(unsigned long offset, const char *format,
   ...) __attribute__((format (printf, 2, 3)));
 
@@ -325,15 +340,8 @@ static const unsigned char *read_sha1ref(void)
 static const unsigned char *read_sha1table_ref(void)
 {
const unsigned char *sha1 = read_sha1ref();
-   if (sha1  sha1_table || sha1 = sha1_table + nr_objects * 20) {
-   unsigned char *found;
-   found = bsearch(sha1, sha1_table, nr_objects, 20,
-   (int (*)(const void *, const void *))hashcmp);
-   if (!found)
-   bad_object(consumed_bytes,
-  _(SHA-1 %s not found in SHA-1 table),
-  sha1_to_hex(sha1));
-   }
+   if (sha1  sha1_table || sha1 = sha1_table + nr_objects * 20)
+   check_against_sha1table(sha1);
return sha1;
 }
 
@@ -346,21 +354,6 @@ static const unsigned char *read_dictref(struct 
packv4_dict *dict)
return  dict-data + dict-offsets[index];
 }
 
-static void *read_data(int size)
-{
-   const int max = sizeof(input_buffer);
-   void *buf;
-   char *p;
-   p = buf = xmalloc(size);
-   while (size) {
-   int to_fill = size  max ? max : size;
-   memcpy(p, fill_and_use(to_fill), to_fill);
-   p += to_fill;
-   size -= to_fill;
-   }
-   return buf;
-}
-
 static const char *open_pack_file(const char *pack_name)
 {
if (from_stdin) {
@@ -532,8 +525,7 @@ static void read_and_inflate(unsigned long offset,
git_SHA1_Final(sha1, ctx);
 }
 
-static void *unpack_commit_v4(unsigned int offset,
- unsigned long size,
+static void *unpack_commit_v4(unsigned int offset, unsigned long size,
  unsigned char *sha1)
 {
unsigned int nb_parents;
@@ -622,7 +614,8 @@ static void add_tree_delta_base(struct object_entry *obj,
  * v4 trees are actually kind of deltas and we don't do delta in the
  * first pass. This function only walks through a tree object to find
  * the end offset, register object dependencies and performs limited
- * validation.
+ * validation. For v4 trees that have no dependencies, we do
+ * uncompress and calculate their SHA-1.
  */
 static void *unpack_tree_v4(struct object_entry *obj,
unsigned int offset, unsigned long size,
@@ -641,9 +634,9 @@ static void *unpack_tree_v4(struct object_entry *obj,
add_tree_delta_base(obj, last_base, 
delta_start);
} else if (!last_base)
bad_object(offset,
-  _(bad copy count index in 
unpack_tree_v4));
+  _(missing delta base 
unpack_tree_v4));
copy_count = 1;
-   if (!copy_count)
+   if (!copy_count || copy_count  nr)
bad_object(offset,
   _(bad copy count index in 
unpack_tree_v4));
nr -= copy_count;
@@ -657,6 +650,13 @@ static void *unpack_tree_v4(struct object_entry *obj,
entry_sha1 = read_sha1ref();
nr--;
 
+   /*
+ 

[PATCH v2 04/14] index-pack: split out varint decoding code

2013-09-08 Thread Nguyễn Thái Ngọc Duy
---
 builtin/index-pack.c | 82 
 1 file changed, 45 insertions(+), 37 deletions(-)

diff --git a/builtin/index-pack.c b/builtin/index-pack.c
index 1dbabe0..5fbd517 100644
--- a/builtin/index-pack.c
+++ b/builtin/index-pack.c
@@ -277,6 +277,31 @@ static void use(int bytes)
consumed_bytes += bytes;
 }
 
+static inline void *fill_and_use(int bytes)
+{
+   void *p = fill(bytes);
+   use(bytes);
+   return p;
+}
+
+static NORETURN void bad_object(unsigned long offset, const char *format,
+  ...) __attribute__((format (printf, 2, 3)));
+
+static uintmax_t read_varint(void)
+{
+   unsigned char c = *(char*)fill_and_use(1);
+   uintmax_t val = c  127;
+   while (c  128) {
+   val += 1;
+   if (!val || MSB(val, 7))
+   bad_object(consumed_bytes,
+  _(offset overflow in read_varint));
+   c = *(char*)fill_and_use(1);
+   val = (val  7) + (c  127);
+   }
+   return val;
+}
+
 static const char *open_pack_file(const char *pack_name)
 {
if (from_stdin) {
@@ -317,9 +342,6 @@ static void parse_pack_header(void)
use(sizeof(struct pack_header));
 }
 
-static NORETURN void bad_object(unsigned long offset, const char *format,
-  ...) __attribute__((format (printf, 2, 3)));
-
 static NORETURN void bad_object(unsigned long offset, const char *format, ...)
 {
va_list params;
@@ -462,55 +484,41 @@ static void *unpack_entry_data(unsigned long offset, 
unsigned long size,
return buf == fixed_buf ? NULL : buf;
 }
 
+static void read_typesize_v2(struct object_entry *obj)
+{
+   unsigned char c = *(char*)fill_and_use(1);
+   unsigned shift;
+
+   obj-type = (c  4)  7;
+   obj-size = (c  15);
+   shift = 4;
+   while (c  128) {
+   c = *(char*)fill_and_use(1);
+   obj-size += (c  0x7f)  shift;
+   shift += 7;
+   }
+}
+
 static void *unpack_raw_entry(struct object_entry *obj,
  union delta_base *delta_base,
  unsigned char *sha1)
 {
-   unsigned char *p;
-   unsigned long size, c;
-   off_t base_offset;
-   unsigned shift;
void *data;
+   uintmax_t val;
 
obj-idx.offset = consumed_bytes;
input_crc32 = crc32(0, NULL, 0);
 
-   p = fill(1);
-   c = *p;
-   use(1);
-   obj-type = (c  4)  7;
-   size = (c  15);
-   shift = 4;
-   while (c  0x80) {
-   p = fill(1);
-   c = *p;
-   use(1);
-   size += (c  0x7f)  shift;
-   shift += 7;
-   }
-   obj-size = size;
+   read_typesize_v2(obj);
 
switch (obj-type) {
case OBJ_REF_DELTA:
-   hashcpy(delta_base-sha1, fill(20));
-   use(20);
+   hashcpy(delta_base-sha1, fill_and_use(20));
break;
case OBJ_OFS_DELTA:
memset(delta_base, 0, sizeof(*delta_base));
-   p = fill(1);
-   c = *p;
-   use(1);
-   base_offset = c  127;
-   while (c  128) {
-   base_offset += 1;
-   if (!base_offset || MSB(base_offset, 7))
-   bad_object(obj-idx.offset, _(offset value 
overflow for delta base object));
-   p = fill(1);
-   c = *p;
-   use(1);
-   base_offset = (base_offset  7) + (c  127);
-   }
-   delta_base-offset = obj-idx.offset - base_offset;
+   val = read_varint();
+   delta_base-offset = obj-idx.offset - val;
if (delta_base-offset = 0 || delta_base-offset = 
obj-idx.offset)
bad_object(obj-idx.offset, _(delta base offset is out 
of bound));
break;
-- 
1.8.2.83.gc99314b

--
To unsubscribe from this list: send the line 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 02/14] pack v4: add pv4_free_dict()

2013-09-08 Thread Nguyễn Thái Ngọc Duy
---
 packv4-parse.c | 8 
 packv4-parse.h | 1 +
 sha1_file.c| 2 ++
 3 files changed, 11 insertions(+)

diff --git a/packv4-parse.c b/packv4-parse.c
index 82661ba..d515bb9 100644
--- a/packv4-parse.c
+++ b/packv4-parse.c
@@ -63,6 +63,14 @@ struct packv4_dict *pv4_create_dict(const unsigned char 
*data, int dict_size)
return dict;
 }
 
+void pv4_free_dict(struct packv4_dict *dict)
+{
+   if (dict) {
+   free((void*)dict-data);
+   free(dict);
+   }
+}
+
 static struct packv4_dict *load_dict(struct packed_git *p, off_t *offset)
 {
struct pack_window *w_curs = NULL;
diff --git a/packv4-parse.h b/packv4-parse.h
index 0b2405a..e6719f6 100644
--- a/packv4-parse.h
+++ b/packv4-parse.h
@@ -8,6 +8,7 @@ struct packv4_dict {
 };
 
 struct packv4_dict *pv4_create_dict(const unsigned char *data, int dict_size);
+void pv4_free_dict(struct packv4_dict *dict);
 
 void *pv4_get_commit(struct packed_git *p, struct pack_window **w_curs,
 off_t offset, unsigned long size);
diff --git a/sha1_file.c b/sha1_file.c
index c7bf677..1528e28 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -763,6 +763,8 @@ void free_pack_by_name(const char *pack_name)
}
close_pack_index(p);
free(p-bad_object_sha1);
+   pv4_free_dict(p-ident_dict);
+   pv4_free_dict(p-path_dict);
*pp = p-next;
if (last_found_pack == p)
last_found_pack = NULL;
-- 
1.8.2.83.gc99314b

--
To unsubscribe from this list: send the line 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 07/14] index-pack: parse v4 header and dictionaries

2013-09-08 Thread Nguyễn Thái Ngọc Duy
---
 builtin/index-pack.c | 49 -
 1 file changed, 48 insertions(+), 1 deletion(-)

diff --git a/builtin/index-pack.c b/builtin/index-pack.c
index 3389262..83e6e79 100644
--- a/builtin/index-pack.c
+++ b/builtin/index-pack.c
@@ -11,6 +11,7 @@
 #include exec_cmd.h
 #include streaming.h
 #include thread-utils.h
+#include packv4-parse.h
 
 static const char index_pack_usage[] =
 git index-pack [-v] [-o index-file] [--keep | --keep=msg] [--verify] 
[--strict] (pack-file | --stdin [--fix-thin] [pack-file]);
@@ -70,6 +71,8 @@ struct delta_entry {
 static struct object_entry *objects;
 static struct delta_entry *deltas;
 static struct thread_local nothread_data;
+static unsigned char *sha1_table;
+static struct packv4_dict *name_dict, *path_dict;
 static int nr_objects;
 static int nr_deltas;
 static int nr_resolved_deltas;
@@ -81,6 +84,7 @@ static int do_fsck_object;
 static int verbose;
 static int show_stat;
 static int check_self_contained_and_connected;
+static int packv4;
 
 static struct progress *progress;
 
@@ -334,7 +338,9 @@ static void parse_pack_header(void)
/* Header consistency check */
if (hdr-hdr_signature != htonl(PACK_SIGNATURE))
die(_(pack signature mismatch));
-   if (!pack_version_ok(hdr-hdr_version))
+   if (hdr-hdr_version == htonl(4))
+   packv4 = 1;
+   else if (!pack_version_ok(hdr-hdr_version))
die(_(pack version %PRIu32 unsupported),
ntohl(hdr-hdr_version));
 
@@ -1035,6 +1041,40 @@ static void *threaded_second_pass(void *data)
 }
 #endif
 
+static struct packv4_dict *read_dict(void)
+{
+   unsigned long size;
+   unsigned char *data;
+   struct packv4_dict *dict;
+
+   size = read_varint();
+   data = xmallocz(size);
+   read_and_inflate(consumed_bytes, data, size, 0, NULL, NULL);
+   dict = pv4_create_dict(data, size);
+   if (!dict)
+   die(unable to parse dictionary);
+   return dict;
+}
+
+static void parse_dictionaries(void)
+{
+   int i;
+   if (!packv4)
+   return;
+
+   sha1_table = xmalloc(20 * nr_objects);
+   hashcpy(sha1_table, fill_and_use(20));
+   for (i = 1; i  nr_objects; i++) {
+   unsigned char *p = sha1_table + i * 20;
+   hashcpy(p, fill_and_use(20));
+   if (hashcmp(p - 20, p) = 0)
+   die(_(wrong order in SHA-1 table at entry %d), i);
+   }
+
+   name_dict = read_dict();
+   path_dict = read_dict();
+}
+
 /*
  * First pass:
  * - find locations of all objects;
@@ -1673,6 +1713,7 @@ int cmd_index_pack(int argc, const char **argv, const 
char *prefix)
parse_pack_header();
objects = xcalloc(nr_objects + 1, sizeof(struct object_entry));
deltas = xcalloc(nr_objects, sizeof(struct delta_entry));
+   parse_dictionaries();
parse_pack_objects(pack_sha1);
resolve_deltas();
conclude_pack(fix_thin_pack, curr_pack, pack_sha1);
@@ -1683,6 +1724,9 @@ int cmd_index_pack(int argc, const char **argv, const 
char *prefix)
if (show_stat)
show_pack_info(stat_only);
 
+   if (packv4)
+   die(we're not there yet);
+
idx_objects = xmalloc((nr_objects) * sizeof(struct pack_idx_entry *));
for (i = 0; i  nr_objects; i++)
idx_objects[i] = objects[i].idx;
@@ -1699,6 +1743,9 @@ int cmd_index_pack(int argc, const char **argv, const 
char *prefix)
free(objects);
free(index_name_buf);
free(keep_name_buf);
+   free(sha1_table);
+   pv4_free_dict(name_dict);
+   pv4_free_dict(path_dict);
if (pack_name == NULL)
free((void *) curr_pack);
if (index_name == NULL)
-- 
1.8.2.83.gc99314b

--
To unsubscribe from this list: send the line 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 06/14] index-pack: split inflate/digest code out of unpack_entry_data

2013-09-08 Thread Nguyễn Thái Ngọc Duy
---
 builtin/index-pack.c | 62 +++-
 1 file changed, 37 insertions(+), 25 deletions(-)

diff --git a/builtin/index-pack.c b/builtin/index-pack.c
index 78554d0..3389262 100644
--- a/builtin/index-pack.c
+++ b/builtin/index-pack.c
@@ -431,6 +431,40 @@ static int is_delta_type(enum object_type type)
return (type == OBJ_REF_DELTA || type == OBJ_OFS_DELTA);
 }
 
+static void read_and_inflate(unsigned long offset,
+void *buf, unsigned long size,
+unsigned long wraparound,
+git_SHA_CTX *ctx,
+unsigned char *sha1)
+{
+   git_zstream stream;
+   int status;
+
+   memset(stream, 0, sizeof(stream));
+   git_inflate_init(stream);
+   stream.next_out = buf;
+   stream.avail_out = wraparound ? wraparound : size;
+
+   do {
+   unsigned char *last_out = stream.next_out;
+   stream.next_in = fill(1);
+   stream.avail_in = input_len;
+   status = git_inflate(stream, 0);
+   use(input_len - stream.avail_in);
+   if (sha1)
+   git_SHA1_Update(ctx, last_out, stream.next_out - 
last_out);
+   if (wraparound) {
+   stream.next_out = buf;
+   stream.avail_out = wraparound;
+   }
+   } while (status == Z_OK);
+   if (stream.total_out != size || status != Z_STREAM_END)
+   bad_object(offset, _(inflate returned %d), status);
+   git_inflate_end(stream);
+   if (sha1)
+   git_SHA1_Final(sha1, ctx);
+}
+
 /*
  * Unpack an entry data in the streamed pack, calculate the object
  * SHA-1 if it's not a large blob. Otherwise just try to inflate the
@@ -440,8 +474,6 @@ static void *unpack_entry_data(unsigned long offset, 
unsigned long size,
   enum object_type type, unsigned char *sha1)
 {
static char fixed_buf[8192];
-   int status;
-   git_zstream stream;
void *buf;
git_SHA_CTX c;
char hdr[32];
@@ -459,29 +491,9 @@ static void *unpack_entry_data(unsigned long offset, 
unsigned long size,
else
buf = xmalloc(size);
 
-   memset(stream, 0, sizeof(stream));
-   git_inflate_init(stream);
-   stream.next_out = buf;
-   stream.avail_out = buf == fixed_buf ? sizeof(fixed_buf) : size;
-
-   do {
-   unsigned char *last_out = stream.next_out;
-   stream.next_in = fill(1);
-   stream.avail_in = input_len;
-   status = git_inflate(stream, 0);
-   use(input_len - stream.avail_in);
-   if (sha1)
-   git_SHA1_Update(c, last_out, stream.next_out - 
last_out);
-   if (buf == fixed_buf) {
-   stream.next_out = buf;
-   stream.avail_out = sizeof(fixed_buf);
-   }
-   } while (status == Z_OK);
-   if (stream.total_out != size || status != Z_STREAM_END)
-   bad_object(offset, _(inflate returned %d), status);
-   git_inflate_end(stream);
-   if (sha1)
-   git_SHA1_Final(sha1, c);
+   read_and_inflate(offset, buf, size,
+buf == fixed_buf ? sizeof(fixed_buf) : 0,
+c, sha1);
return buf == fixed_buf ? NULL : buf;
 }
 
-- 
1.8.2.83.gc99314b

--
To unsubscribe from this list: send the line 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 03/14] index-pack: add more comments on some big functions

2013-09-08 Thread Nguyễn Thái Ngọc Duy
---
 builtin/index-pack.c | 30 ++
 1 file changed, 26 insertions(+), 4 deletions(-)

diff --git a/builtin/index-pack.c b/builtin/index-pack.c
index 9c1cfac..1dbabe0 100644
--- a/builtin/index-pack.c
+++ b/builtin/index-pack.c
@@ -19,8 +19,8 @@ struct object_entry {
struct pack_idx_entry idx;
unsigned long size;
unsigned int hdr_size;
-   enum object_type type;
-   enum object_type real_type;
+   enum object_type type;  /* type as written in pack */
+   enum object_type real_type; /* type after delta resolving */
unsigned delta_depth;
int base_object_no;
 };
@@ -187,8 +187,10 @@ static int mark_link(struct object *obj, int type, void 
*data)
return 0;
 }
 
-/* The content of each linked object must have been checked
-   or it must be already present in the object database */
+/*
+ * The content of each linked object must have been checked or it must
+ * be already present in the object database
+ */
 static unsigned check_object(struct object *obj)
 {
if (!obj)
@@ -407,6 +409,11 @@ static int is_delta_type(enum object_type type)
return (type == OBJ_REF_DELTA || type == OBJ_OFS_DELTA);
 }
 
+/*
+ * Unpack an entry data in the streamed pack, calculate the object
+ * SHA-1 if it's not a large blob. Otherwise just try to inflate the
+ * object to /dev/null to determine the end of the entry in the pack.
+ */
 static void *unpack_entry_data(unsigned long offset, unsigned long size,
   enum object_type type, unsigned char *sha1)
 {
@@ -522,6 +529,11 @@ static void *unpack_raw_entry(struct object_entry *obj,
return data;
 }
 
+/*
+ * Unpack entry data in the second pass when the pack is already
+ * stored on disk. consume call back is used for large-blob case. Must
+ * be thread safe.
+ */
 static void *unpack_data(struct object_entry *obj,
 int (*consume)(const unsigned char *, unsigned long, 
void *),
 void *cb_data)
@@ -875,6 +887,11 @@ static void resolve_delta(struct object_entry *delta_obj,
counter_unlock();
 }
 
+/*
+ * Given a base object, search for all objects depending on the base,
+ * try to unpack one of those object. The function will be called
+ * repeatedly until all objects are unpacked.
+ */
 static struct base_data *find_unresolved_deltas_1(struct base_data *base,
  struct base_data *prev_base)
 {
@@ -958,6 +975,10 @@ static int compare_delta_entry(const void *a, const void 
*b)
   objects[delta_b-obj_no].type);
 }
 
+/*
+ * Unpack all objects depending directly or indirectly on the given
+ * object
+ */
 static void resolve_base(struct object_entry *obj)
 {
struct base_data *base_obj = alloc_base_data();
@@ -967,6 +988,7 @@ static void resolve_base(struct object_entry *obj)
 }
 
 #ifndef NO_PTHREADS
+/* Call resolve_base() in multiple threads */
 static void *threaded_second_pass(void *data)
 {
set_thread_data(data);
-- 
1.8.2.83.gc99314b

--
To unsubscribe from this list: send the line 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 01/14] pack v4: split pv4_create_dict() out of load_dict()

2013-09-08 Thread Nguyễn Thái Ngọc Duy
---
 packv4-parse.c | 63 --
 packv4-parse.h |  8 
 2 files changed, 43 insertions(+), 28 deletions(-)

diff --git a/packv4-parse.c b/packv4-parse.c
index 63bba03..82661ba 100644
--- a/packv4-parse.c
+++ b/packv4-parse.c
@@ -30,11 +30,38 @@ const unsigned char *get_sha1ref(struct packed_git *p,
return sha1;
 }
 
-struct packv4_dict {
-   const unsigned char *data;
-   unsigned int nb_entries;
-   unsigned int offsets[FLEX_ARRAY];
-};
+struct packv4_dict *pv4_create_dict(const unsigned char *data, int dict_size)
+{
+   struct packv4_dict *dict;
+   int i;
+
+   /* count number of entries */
+   int nb_entries = 0;
+   const unsigned char *cp = data;
+   while (cp  data + dict_size - 3) {
+   cp += 2;  /* prefix bytes */
+   cp += strlen((const char *)cp);  /* entry string */
+   cp += 1;  /* terminating NUL */
+   nb_entries++;
+   }
+   if (cp - data != dict_size) {
+   error(dict size mismatch);
+   return NULL;
+   }
+
+   dict = xmalloc(sizeof(*dict) + nb_entries * sizeof(dict-offsets[0]));
+   dict-data = data;
+   dict-nb_entries = nb_entries;
+
+   cp = data;
+   for (i = 0; i  nb_entries; i++) {
+   dict-offsets[i] = cp - data;
+   cp += 2;
+   cp += strlen((const char *)cp) + 1;
+   }
+
+   return dict;
+}
 
 static struct packv4_dict *load_dict(struct packed_git *p, off_t *offset)
 {
@@ -45,7 +72,7 @@ static struct packv4_dict *load_dict(struct packed_git *p, 
off_t *offset)
const unsigned char *cp;
git_zstream stream;
struct packv4_dict *dict;
-   int nb_entries, i, st;
+   int st;
 
/* get uncompressed dictionary data size */
src = use_pack(p, w_curs, curpos, avail);
@@ -77,32 +104,12 @@ static struct packv4_dict *load_dict(struct packed_git *p, 
off_t *offset)
return NULL;
}
 
-   /* count number of entries */
-   nb_entries = 0;
-   cp = data;
-   while (cp  data + dict_size - 3) {
-   cp += 2;  /* prefix bytes */
-   cp += strlen((const char *)cp);  /* entry string */
-   cp += 1;  /* terminating NUL */
-   nb_entries++;
-   }
-   if (cp - data != dict_size) {
-   error(dict size mismatch);
+   dict = pv4_create_dict(data, dict_size);
+   if (!dict) {
free(data);
return NULL;
}
 
-   dict = xmalloc(sizeof(*dict) + nb_entries * sizeof(dict-offsets[0]));
-   dict-data = data;
-   dict-nb_entries = nb_entries;
-
-   cp = data;
-   for (i = 0; i  nb_entries; i++) {
-   dict-offsets[i] = cp - data;
-   cp += 2;
-   cp += strlen((const char *)cp) + 1;
-   }
-
*offset = curpos;
return dict;
 }
diff --git a/packv4-parse.h b/packv4-parse.h
index 5f9d809..0b2405a 100644
--- a/packv4-parse.h
+++ b/packv4-parse.h
@@ -1,6 +1,14 @@
 #ifndef PACKV4_PARSE_H
 #define PACKV4_PARSE_H
 
+struct packv4_dict {
+   const unsigned char *data;
+   unsigned int nb_entries;
+   unsigned int offsets[FLEX_ARRAY];
+};
+
+struct packv4_dict *pv4_create_dict(const unsigned char *data, int dict_size);
+
 void *pv4_get_commit(struct packed_git *p, struct pack_window **w_curs,
 off_t offset, unsigned long size);
 void *pv4_get_tree(struct packed_git *p, struct pack_window **w_curs,
-- 
1.8.2.83.gc99314b

--
To unsubscribe from this list: send the line 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 13/14] index-pack: skip looking for ofs-deltas in v4 as they are not allowed

2013-09-08 Thread Nguyễn Thái Ngọc Duy
---
 builtin/index-pack.c | 11 +++
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/builtin/index-pack.c b/builtin/index-pack.c
index e903a49..ce06473 100644
--- a/builtin/index-pack.c
+++ b/builtin/index-pack.c
@@ -1173,10 +1173,13 @@ static struct base_data 
*find_unresolved_deltas_1(struct base_data *base,
find_delta_children(base_spec,
base-ref_first, base-ref_last, 
OBJ_REF_DELTA);
 
-   memset(base_spec, 0, sizeof(base_spec));
-   base_spec.offset = base-obj-idx.offset;
-   find_delta_children(base_spec,
-   base-ofs_first, base-ofs_last, 
OBJ_OFS_DELTA);
+   if (!packv4) {
+   memset(base_spec, 0, sizeof(base_spec));
+   base_spec.offset = base-obj-idx.offset;
+   find_delta_children(base_spec,
+   base-ofs_first, base-ofs_last,
+   OBJ_OFS_DELTA);
+   }
 
if (base-ref_last == -1  base-ofs_last == -1) {
free(base-data);
-- 
1.8.2.83.gc99314b

--
To unsubscribe from this list: send the line 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 11/14] index-pack: move delta base queuing code to unpack_raw_entry

2013-09-08 Thread Nguyễn Thái Ngọc Duy
For v2, ofs-delta and ref-delta can only have queue one delta base at
a time. A v4 tree can have more than one delta base. Move the queuing
code up to unpack_raw_entry() and give unpack_tree_v4() more
flexibility to add its bases.
---
 builtin/index-pack.c | 46 ++
 1 file changed, 30 insertions(+), 16 deletions(-)

diff --git a/builtin/index-pack.c b/builtin/index-pack.c
index dcb6409..8f2d929 100644
--- a/builtin/index-pack.c
+++ b/builtin/index-pack.c
@@ -568,6 +568,25 @@ static void *unpack_commit_v4(unsigned int offset, 
unsigned long size,
return dst.buf;
 }
 
+static void add_sha1_delta(struct object_entry *obj,
+  const unsigned char *sha1)
+{
+   struct delta_entry *delta = deltas + nr_deltas;
+   delta-obj_no = obj - objects;
+   hashcpy(delta-base.sha1, sha1);
+   nr_deltas++;
+}
+
+static void add_ofs_delta(struct object_entry *obj,
+ off_t offset)
+{
+   struct delta_entry *delta = deltas + nr_deltas;
+   delta-obj_no = obj - objects;
+   memset(delta-base, 0, sizeof(delta-base));
+   delta-base.offset = offset;
+   nr_deltas++;
+}
+
 /*
  * v4 trees are actually kind of deltas and we don't do delta in the
  * first pass. This function only walks through a tree object to find
@@ -703,17 +722,16 @@ static void read_typesize_v2(struct object_entry *obj)
 }
 
 static void *unpack_raw_entry(struct object_entry *obj,
- union delta_base *delta_base,
  unsigned char *sha1)
 {
void *data;
-   uintmax_t val;
+   off_t offset;
 
obj-idx.offset = consumed_bytes;
input_crc32 = crc32(0, NULL, 0);
 
if (packv4) {
-   val = read_varint();
+   uintmax_t val = read_varint();
obj-type = val  15;
obj-size = val  4;
} else
@@ -722,14 +740,14 @@ static void *unpack_raw_entry(struct object_entry *obj,
 
switch (obj-type) {
case OBJ_REF_DELTA:
-   hashcpy(delta_base-sha1, fill_and_use(20));
+   add_sha1_delta(obj, fill_and_use(20));
break;
case OBJ_OFS_DELTA:
-   memset(delta_base, 0, sizeof(*delta_base));
-   val = read_varint();
-   delta_base-offset = obj-idx.offset - val;
-   if (delta_base-offset = 0 || delta_base-offset = 
obj-idx.offset)
-   bad_object(obj-idx.offset, _(delta base offset is out 
of bound));
+   offset = obj-idx.offset - read_varint();
+   if (offset = 0 || offset = obj-idx.offset)
+   bad_object(obj-idx.offset,
+  _(delta base offset is out of bound));
+   add_ofs_delta(obj, offset);
break;
case OBJ_COMMIT:
case OBJ_TREE:
@@ -1282,7 +1300,6 @@ static void parse_dictionaries(void)
 static void parse_pack_objects(unsigned char *sha1)
 {
int i, nr_delays = 0;
-   struct delta_entry *delta = deltas;
struct stat st;
 
if (verbose)
@@ -1291,12 +1308,9 @@ static void parse_pack_objects(unsigned char *sha1)
nr_objects);
for (i = 0; i  nr_objects; i++) {
struct object_entry *obj = objects[i];
-   void *data = unpack_raw_entry(obj, delta-base, obj-idx.sha1);
-   if (is_delta_type(obj-type)) {
-   nr_deltas++;
-   delta-obj_no = i;
-   delta++;
-   } else if (!data  obj-type == OBJ_PV4_TREE) {
+   void *data = unpack_raw_entry(obj, obj-idx.sha1);
+   if (is_delta_type(obj-type) ||
+   (!data  obj-type == OBJ_PV4_TREE)) {
/* delay sha1_object() until second pass */
} else if (!data) {
/* large blobs, check later */
-- 
1.8.2.83.gc99314b

--
To unsubscribe from this list: send the line 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 09/14] index-pack: parse v4 commit format

2013-09-08 Thread Nguyễn Thái Ngọc Duy
---
 builtin/index-pack.c | 94 ++--
 1 file changed, 91 insertions(+), 3 deletions(-)

diff --git a/builtin/index-pack.c b/builtin/index-pack.c
index efb969a..473514a 100644
--- a/builtin/index-pack.c
+++ b/builtin/index-pack.c
@@ -319,6 +319,30 @@ static uintmax_t read_varint(void)
return val;
 }
 
+static const unsigned char *read_sha1ref(void)
+{
+   unsigned int index = read_varint();
+   if (!index) {
+   static unsigned char sha1[20];
+   hashcpy(sha1, fill_and_use(20));
+   return sha1;
+   }
+   index--;
+   if (index = nr_objects)
+   bad_object(consumed_bytes,
+  _(bad index in read_sha1ref));
+   return sha1_table + index * 20;
+}
+
+static const unsigned char *read_dictref(struct packv4_dict *dict)
+{
+   unsigned int index = read_varint();
+   if (index = dict-nb_entries)
+   bad_object(consumed_bytes,
+  _(bad index in read_dictref));
+   return  dict-data + dict-offsets[index];
+}
+
 static const char *open_pack_file(const char *pack_name)
 {
if (from_stdin) {
@@ -484,6 +508,58 @@ static void read_and_inflate(unsigned long offset,
git_SHA1_Final(sha1, ctx);
 }
 
+static void *unpack_commit_v4(unsigned int offset, unsigned long size,
+ unsigned char *sha1)
+{
+   unsigned int nb_parents;
+   const unsigned char *committer, *author, *ident;
+   unsigned long author_time, committer_time;
+   git_SHA_CTX ctx;
+   char hdr[32];
+   int hdrlen;
+   int16_t committer_tz, author_tz;
+   struct strbuf dst;
+
+   strbuf_init(dst, size);
+
+   strbuf_addf(dst, tree %s\n, sha1_to_hex(read_sha1ref()));
+   nb_parents = read_varint();
+   while (nb_parents--)
+   strbuf_addf(dst, parent %s\n, sha1_to_hex(read_sha1ref()));
+
+   committer_time = read_varint();
+   ident = read_dictref(name_dict);
+   committer_tz = (ident[0]  8) | ident[1];
+   committer = ident + 2;
+
+   author_time = read_varint();
+   ident = read_dictref(name_dict);
+   author_tz = (ident[0]  8) | ident[1];
+   author = ident + 2;
+
+   if (author_time  1)
+   author_time = committer_time + (author_time  1);
+   else
+   author_time = committer_time - (author_time  1);
+
+   strbuf_addf(dst,
+   author %s %lu %+05d\n
+   committer %s %lu %+05d\n,
+   author, author_time, author_tz,
+   committer, committer_time, committer_tz);
+
+   if (dst.len  size)
+   bad_object(offset, _(bad commit));
+
+   hdrlen = sprintf(hdr, commit %lu, size) + 1;
+   git_SHA1_Init(ctx);
+   git_SHA1_Update(ctx, hdr, hdrlen);
+   git_SHA1_Update(ctx, dst.buf, dst.len);
+   read_and_inflate(offset, dst.buf + dst.len, size - dst.len,
+0, ctx, sha1);
+   return dst.buf;
+}
+
 /*
  * Unpack an entry data in the streamed pack, calculate the object
  * SHA-1 if it's not a large blob. Otherwise just try to inflate the
@@ -498,6 +574,9 @@ static void *unpack_entry_data(unsigned long offset, 
unsigned long size,
char hdr[32];
int hdrlen;
 
+   if (type == OBJ_PV4_COMMIT)
+   return unpack_commit_v4(offset, size, sha1);
+
if (!is_delta_type(type)) {
hdrlen = sprintf(hdr, %s %lu, typename(type), size) + 1;
git_SHA1_Init(c);
@@ -541,7 +620,13 @@ static void *unpack_raw_entry(struct object_entry *obj,
obj-idx.offset = consumed_bytes;
input_crc32 = crc32(0, NULL, 0);
 
-   read_typesize_v2(obj);
+   if (packv4) {
+   val = read_varint();
+   obj-type = val  15;
+   obj-size = val  4;
+   } else
+   read_typesize_v2(obj);
+   obj-real_type = obj-type;
 
switch (obj-type) {
case OBJ_REF_DELTA:
@@ -559,6 +644,10 @@ static void *unpack_raw_entry(struct object_entry *obj,
case OBJ_BLOB:
case OBJ_TAG:
break;
+
+   case OBJ_PV4_COMMIT:
+   obj-real_type = OBJ_COMMIT;
+   break;
default:
bad_object(obj-idx.offset, _(unknown object type %d), 
obj-type);
}
@@ -1108,7 +1197,6 @@ static void parse_pack_objects(unsigned char *sha1)
for (i = 0; i  nr_objects; i++) {
struct object_entry *obj = objects[i];
void *data = unpack_raw_entry(obj, delta-base, obj-idx.sha1);
-   obj-real_type = obj-type;
if (is_delta_type(obj-type)) {
nr_deltas++;
delta-obj_no = i;
@@ -1120,7 +1208,7 @@ static void parse_pack_objects(unsigned char *sha1)
check_against_sha1table(obj-idx.sha1);
} else {
 

[PATCH v2 08/14] index-pack: make sure all objects are registered in v4's SHA-1 table

2013-09-08 Thread Nguyễn Thái Ngọc Duy
---
 builtin/index-pack.c | 22 --
 1 file changed, 20 insertions(+), 2 deletions(-)

diff --git a/builtin/index-pack.c b/builtin/index-pack.c
index 83e6e79..efb969a 100644
--- a/builtin/index-pack.c
+++ b/builtin/index-pack.c
@@ -288,6 +288,19 @@ static inline void *fill_and_use(int bytes)
return p;
 }
 
+static void check_against_sha1table(const unsigned char *sha1)
+{
+   const unsigned char *found;
+   if (!packv4)
+   return;
+
+   found = bsearch(sha1, sha1_table, nr_objects, 20,
+   (int (*)(const void *, const void *))hashcmp);
+   if (!found)
+   die(_(object %s not found in SHA-1 table),
+   sha1_to_hex(sha1));
+}
+
 static NORETURN void bad_object(unsigned long offset, const char *format,
   ...) __attribute__((format (printf, 2, 3)));
 
@@ -907,6 +920,7 @@ static void resolve_delta(struct object_entry *delta_obj,
bad_object(delta_obj-idx.offset, _(failed to apply delta));
hash_sha1_file(result-data, result-size,
   typename(delta_obj-real_type), delta_obj-idx.sha1);
+   check_against_sha1table(delta_obj-idx.sha1);
sha1_object(result-data, NULL, result-size, delta_obj-real_type,
delta_obj-idx.sha1);
counter_lock();
@@ -1103,8 +1117,12 @@ static void parse_pack_objects(unsigned char *sha1)
/* large blobs, check later */
obj-real_type = OBJ_BAD;
nr_delays++;
-   } else
-   sha1_object(data, NULL, obj-size, obj-type, 
obj-idx.sha1);
+   check_against_sha1table(obj-idx.sha1);
+   } else {
+   check_against_sha1table(obj-idx.sha1);
+   sha1_object(data, NULL, obj-size, obj-type,
+   obj-idx.sha1);
+   }
free(data);
display_progress(progress, i+1);
}
-- 
1.8.2.83.gc99314b

--
To unsubscribe from this list: send the line 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 12/14] index-pack: record all delta bases in v4 (tree and ref-delta)

2013-09-08 Thread Nguyễn Thái Ngọc Duy
---
 builtin/index-pack.c | 33 ++---
 1 file changed, 30 insertions(+), 3 deletions(-)

diff --git a/builtin/index-pack.c b/builtin/index-pack.c
index 8f2d929..e903a49 100644
--- a/builtin/index-pack.c
+++ b/builtin/index-pack.c
@@ -24,6 +24,7 @@ struct object_entry {
enum object_type real_type; /* type after delta resolving */
unsigned delta_depth;
int base_object_no;
+   int nr_bases;   /* only valid for v4 trees */
 };
 
 union delta_base {
@@ -482,6 +483,11 @@ static int is_delta_type(enum object_type type)
return (type == OBJ_REF_DELTA || type == OBJ_OFS_DELTA);
 }
 
+static int is_delta_tree(const struct object_entry *obj)
+{
+   return obj-type == OBJ_PV4_TREE  obj-nr_bases  0;
+}
+
 static void read_and_inflate(unsigned long offset,
 void *buf, unsigned long size,
 unsigned long wraparound,
@@ -587,6 +593,20 @@ static void add_ofs_delta(struct object_entry *obj,
nr_deltas++;
 }
 
+static void add_tree_delta_base(struct object_entry *obj,
+   const unsigned char *base,
+   int delta_start)
+{
+   int i;
+
+   for (i = delta_start; i  nr_deltas; i++)
+   if (!hashcmp(base, deltas[i].base.sha1))
+   return;
+
+   add_sha1_delta(obj, base);
+   obj-nr_bases++;
+}
+
 /*
  * v4 trees are actually kind of deltas and we don't do delta in the
  * first pass. This function only walks through a tree object to find
@@ -601,12 +621,14 @@ static void *unpack_tree_v4(struct object_entry *obj,
unsigned int nr = read_varint();
const unsigned char *last_base = NULL;
struct strbuf sb = STRBUF_INIT;
+   int delta_start = nr_deltas;
while (nr) {
unsigned int copy_start_or_path = read_varint();
if (copy_start_or_path  1) { /* copy_start */
unsigned int copy_count = read_varint();
if (copy_count  1) { /* first delta */
last_base = read_sha1table_ref();
+   add_tree_delta_base(obj, last_base, 
delta_start);
} else if (!last_base)
bad_object(offset,
   _(missing delta base 
unpack_tree_v4));
@@ -740,9 +762,15 @@ static void *unpack_raw_entry(struct object_entry *obj,
 
switch (obj-type) {
case OBJ_REF_DELTA:
-   add_sha1_delta(obj, fill_and_use(20));
+   if (packv4)
+   add_sha1_delta(obj, read_sha1table_ref());
+   else
+   add_sha1_delta(obj, fill_and_use(20));
break;
case OBJ_OFS_DELTA:
+   if (packv4)
+   die(_(pack version 4 does not support ofs-delta type 
(offset %lu)),
+   obj-idx.offset);
offset = obj-idx.offset - read_varint();
if (offset = 0 || offset = obj-idx.offset)
bad_object(obj-idx.offset,
@@ -1309,8 +1337,7 @@ static void parse_pack_objects(unsigned char *sha1)
for (i = 0; i  nr_objects; i++) {
struct object_entry *obj = objects[i];
void *data = unpack_raw_entry(obj, obj-idx.sha1);
-   if (is_delta_type(obj-type) ||
-   (!data  obj-type == OBJ_PV4_TREE)) {
+   if (is_delta_type(obj-type) || is_delta_tree(obj)) {
/* delay sha1_object() until second pass */
} else if (!data) {
/* large blobs, check later */
-- 
1.8.2.83.gc99314b

--
To unsubscribe from this list: send the line 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 14/14] index-pack: resolve v4 one-base trees

2013-09-08 Thread Nguyễn Thái Ngọc Duy
This is the most common case for delta trees. In fact it's the only
kind that's produced by packv4-create. It fits well in the way
index-pack resolves deltas and benefits from threading (the set of
objects depending on this base does not overlap with the set of
objects depending on another base)

Multi-base trees will be probably processed differently.
---
 builtin/index-pack.c | 195 ++-
 1 file changed, 179 insertions(+), 16 deletions(-)

diff --git a/builtin/index-pack.c b/builtin/index-pack.c
index ce06473..88340b5 100644
--- a/builtin/index-pack.c
+++ b/builtin/index-pack.c
@@ -12,6 +12,8 @@
 #include streaming.h
 #include thread-utils.h
 #include packv4-parse.h
+#include varint.h
+#include tree-walk.h
 
 static const char index_pack_usage[] =
 git index-pack [-v] [-o index-file] [--keep | --keep=msg] [--verify] 
[--strict] (pack-file | --stdin [--fix-thin] [pack-file]);
@@ -38,8 +40,8 @@ struct base_data {
struct object_entry *obj;
void *data;
unsigned long size;
-   int ref_first, ref_last;
-   int ofs_first, ofs_last;
+   int ref_first, ref_last, tree_first;
+   int ofs_first, ofs_last, tree_last;
 };
 
 #if !defined(NO_PTHREADS)  defined(NO_THREAD_SAFE_PREAD)
@@ -430,6 +432,7 @@ static struct base_data *alloc_base_data(void)
memset(base, 0, sizeof(*base));
base-ref_last = -1;
base-ofs_last = -1;
+   base-tree_last = -1;
return base;
 }
 
@@ -670,6 +673,8 @@ static void *unpack_tree_v4(struct object_entry *obj,
}
 
if (last_base) {
+   if (nr_deltas - delta_start  1)
+   die(sorry guys, multi-base trees are not supported 
yet);
strbuf_release(sb);
return NULL;
} else {
@@ -800,6 +805,84 @@ static void *unpack_raw_entry(struct object_entry *obj,
 }
 
 /*
+ * Some checks are skipped because they are already done by
+ * unpack_tree_v4() in the first pass.
+ */
+static void *patch_one_base_tree(const struct object_entry *src,
+const unsigned char *src_buf,
+const unsigned char *delta_buf,
+unsigned long delta_size,
+unsigned long *dst_size)
+{
+   int nr;
+   const unsigned char *last_base = NULL;
+   struct strbuf sb = STRBUF_INIT;
+   const unsigned char *p = delta_buf;
+
+   nr = decode_varint(p);
+   while (nr  0  p  delta_buf + delta_size) {
+   unsigned int copy_start_or_path = decode_varint(p);
+   if (copy_start_or_path  1) { /* copy_start */
+   struct tree_desc desc;
+   struct name_entry entry;
+   unsigned int copy_count = decode_varint(p);
+   unsigned int copy_start = copy_start_or_path  1;
+   if (!src)
+   die(we are not supposed to copy from another 
tree!);
+   if (copy_count  1) { /* first delta */
+   unsigned int id = decode_varint(p);
+   if (!id) {
+   last_base = p;
+   p += 20;
+   } else
+   last_base = sha1_table + (id - 1) * 20;
+   if (hashcmp(last_base, src-idx.sha1))
+   die(_(bad tree base in 
patch_one_base_tree));
+   }
+
+   copy_count = 1;
+   nr -= copy_count;
+
+   init_tree_desc(desc, src_buf, src-size);
+   while (tree_entry(desc, entry)) {
+   if (copy_start)
+   copy_start--;
+   else if (copy_count) {
+   strbuf_addf(sb, %o %s%c,
+   entry.mode, entry.path, 
'\0');
+   strbuf_add(sb, entry.sha1, 20);
+   copy_count--;
+   } else
+   break;
+   }
+   } else {/* path */
+   unsigned int path_idx = copy_start_or_path  1;
+   const unsigned char *path;
+   unsigned mode;
+   unsigned int id;
+   const unsigned char *entry_sha1;
+
+   id = decode_varint(p);
+   if (!id) {
+   entry_sha1 = p;
+   p += 20;
+   } else
+   entry_sha1 = sha1_table + (id - 1) * 20;
+   nr--;
+
+   

[PATCH v2 10/14] index-pack: parse v4 tree format

2013-09-08 Thread Nguyễn Thái Ngọc Duy
---
 builtin/index-pack.c | 105 +--
 1 file changed, 101 insertions(+), 4 deletions(-)

diff --git a/builtin/index-pack.c b/builtin/index-pack.c
index 473514a..dcb6409 100644
--- a/builtin/index-pack.c
+++ b/builtin/index-pack.c
@@ -334,6 +334,14 @@ static const unsigned char *read_sha1ref(void)
return sha1_table + index * 20;
 }
 
+static const unsigned char *read_sha1table_ref(void)
+{
+   const unsigned char *sha1 = read_sha1ref();
+   if (sha1  sha1_table || sha1 = sha1_table + nr_objects * 20)
+   check_against_sha1table(sha1);
+   return sha1;
+}
+
 static const unsigned char *read_dictref(struct packv4_dict *dict)
 {
unsigned int index = read_varint();
@@ -561,21 +569,105 @@ static void *unpack_commit_v4(unsigned int offset, 
unsigned long size,
 }
 
 /*
+ * v4 trees are actually kind of deltas and we don't do delta in the
+ * first pass. This function only walks through a tree object to find
+ * the end offset, register object dependencies and performs limited
+ * validation. For v4 trees that have no dependencies, we do
+ * uncompress and calculate their SHA-1.
+ */
+static void *unpack_tree_v4(struct object_entry *obj,
+   unsigned int offset, unsigned long size,
+   unsigned char *sha1)
+{
+   unsigned int nr = read_varint();
+   const unsigned char *last_base = NULL;
+   struct strbuf sb = STRBUF_INIT;
+   while (nr) {
+   unsigned int copy_start_or_path = read_varint();
+   if (copy_start_or_path  1) { /* copy_start */
+   unsigned int copy_count = read_varint();
+   if (copy_count  1) { /* first delta */
+   last_base = read_sha1table_ref();
+   } else if (!last_base)
+   bad_object(offset,
+  _(missing delta base 
unpack_tree_v4));
+   copy_count = 1;
+   if (!copy_count || copy_count  nr)
+   bad_object(offset,
+  _(bad copy count index in 
unpack_tree_v4));
+   nr -= copy_count;
+   } else {/* path */
+   unsigned int path_idx = copy_start_or_path  1;
+   const unsigned char *entry_sha1;
+
+   if (path_idx = path_dict-nb_entries)
+   bad_object(offset,
+  _(bad path index in 
unpack_tree_v4));
+   entry_sha1 = read_sha1ref();
+   nr--;
+
+   /*
+* Attempt to rebuild a canonical (base) tree.
+* If last_base is set, this tree depends on
+* another tree, which we have no access at this
+* stage, so reconstruction must be delayed until
+* the second pass.
+*/
+   if (!last_base) {
+   const unsigned char *path;
+   unsigned mode;
+
+   path = path_dict-data + 
path_dict-offsets[path_idx];
+   mode = (path[0]  8) | path[1];
+   strbuf_addf(sb, %o %s%c, mode, path+2, '\0');
+   strbuf_add(sb, entry_sha1, 20);
+   if (sb.len  size)
+   bad_object(offset,
+  _(tree larger than 
expected));
+   }
+   }
+   }
+
+   if (last_base) {
+   strbuf_release(sb);
+   return NULL;
+   } else {
+   git_SHA_CTX ctx;
+   char hdr[32];
+   int hdrlen;
+
+   if (sb.len != size)
+   bad_object(offset, _(tree size mismatch));
+
+   hdrlen = sprintf(hdr, tree %lu, size) + 1;
+   git_SHA1_Init(ctx);
+   git_SHA1_Update(ctx, hdr, hdrlen);
+   git_SHA1_Update(ctx, sb.buf, size);
+   git_SHA1_Final(sha1, ctx);
+   return strbuf_detach(sb, NULL);
+   }
+}
+
+/*
  * Unpack an entry data in the streamed pack, calculate the object
  * SHA-1 if it's not a large blob. Otherwise just try to inflate the
  * object to /dev/null to determine the end of the entry in the pack.
  */
-static void *unpack_entry_data(unsigned long offset, unsigned long size,
-  enum object_type type, unsigned char *sha1)
+static void *unpack_entry_data(struct object_entry *obj, unsigned char *sha1)
 {
static char fixed_buf[8192];
void *buf;
git_SHA_CTX c;
char hdr[32];
int hdrlen;
+ 

Re: [PATCH 1/3] upload-pack: send the HEAD information

2013-09-08 Thread Jeff King
On Sun, Sep 08, 2013 at 03:13:59AM -0400, Jeff King wrote:

 What do you think about teaching git to read extra data after \0 for
 _every_ ref line? And then ref advertisement might look something like:
 
   sha1 HEAD\0multi_ack thin-pack ... symref=refs/heads/master\n
   sha1 refs/heads/master\n
   sha1 refs/heads/my-alias\0symref=refs/heads/master
 
 That would leave us future room for more ref annotations if we should
 want them, and I think (but haven't tested) that existing receivers
 should ignore everything after the NUL.

Meh, elsewhere you said:

  The capability list _could_ be sent more than once, and the
  receiving end is prepared to accept such a stream.  Everything
  learned from an older capability list needs to be forgot and only
  the last one is honored, I think.

and I think you are right. We simply keep a copy of the string the
server sent, and when we see a new one, we free the old and replace it.
So each subsequent ref would have to re-send the whole capability string
(only if it is a symref, but still, it is somewhat ugly).

-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: Officially start moving to the term 'staging area'

2013-09-08 Thread Philip Oakley

From: Felipe Contreras felipe.contre...@gmail.com
Sent: Sunday, September 08, 2013 2:33 AM
[snip...]

The snapshot concept is totally orthogonal from the staging area
concept. Git works in snapshots, which are frozen images of how the
content tree was at a certain point in time; IOW; a commit.


(I feel that) In most peoples minds the need for a staging area, and the 
use of snapshots, are related. Part of that relationship, often not 
noticed by those folks, is that they are 'orthogonal' to *each other*. 
Thus orthogonality means both un-related, and related at the same time 
(aren't we humans peculiar!). They are cleaved to each other.


When trying to explain staging/index I tend to use the analogy of an old 
style office (I am almost that old) where one has an In tray and an Out 
tray on one's desk (and one parked WIP for lunch time desk tidy), and 
the staging area is the basket at the end marked 'For Filing'. When the 
'For Filing' basket is ready, one called the filing clerk to dictate the 
cover note and away it went, commited to some remote filing repository. 
Oh how things have changed ;-)




_How_ that snapshot is created is an entirely different topic, and the
staging area is a tool to create the desired snapshots. The user might
decide to never use that tool (i.e. always run git commit -a), but the
concept of snapshots remain. So, clearly, one concept has absolutely
nothing to do with the other.



The point would be that we allow a particular snapshot to be selected, 
and that the git commit -a is but one (common) method. Commit -a is like 
jumping in the car for a quick trip to the shops, while the selective 
staging of content is like packing for a holiday.


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


Re: [PATCH 0/3] Reject non-ff pulls by default

2013-09-08 Thread Jeff King
On Sun, Sep 08, 2013 at 02:15:17AM -0500, Felipe Contreras wrote:

  I think the guy may be git itself. For example, here is a possible
  session with jc/pull-training-wheel:
 
$ git push
 
 Who told him to use 'git push'? Certainly not git.

Any of the hundreds of existing tutorials that teach basic git commands
like push?

To ...
 ! [rejected]master - master (non-fast-forward)
error: failed to push some refs to '...'
hint: Updates were rejected because the tip of your current branch is 
  behind
hint: its remote counterpart. Integrate the remote changes (e.g.
hint: 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
 [...]
 
 Why stop there? Post the whole man page already.
 
 Moreover, it's overly verbose on all the wrong and irrelevant
 information. If you are going to waste precious screen state, explain
 wth a non fast-forward is; people can figure out what a merge is,
 and maybe a rebase, but a non fast-forward definitely not.

Note that I was not trying to defend any of the messages, but only
showing a plausible mechanism by which a user with basic knowledge that
he wants to push may arrive at the question what is the difference
between merge and rebase?.

If you want to suggest revisions for the push message, go ahead. The
push advice _is_ an attempt to define non-fast-forwards in plain
language without taking up too much space, but perhaps you can do
better. You could even suggest omitting it entirely, but I'm not sure if
that is a good idea. It was not added in a vacuum; we lacked that advice
for many years, and people complained about it quite a bit until it was
added.

  The user is pointed at pull from push, and then gets presented with
  the merge or rebase choice. It may be that the advice you can find by
  googling merge vs rebase is enough to then help the person along
  (and/or we may need to improve the manpages in that respect).
 
 Yes, but that's not the use-case we are talking about. You mentioned
 specifically a svn-like worfklow where the guy was told by somebody
 else to replace the svn commands with git ones.

No, I mentioned an svn-like workflow. I didn't say anything about how
they were told. They might have been told by a co-worker, or read a
brief tutorial on git, or read something like Git-SVN Crash Course.

 If we are talking about a guy that is learning git, that's and
 entirely different case.

That is certainly what I meant to be talking about.

 The purpose of this change in the code is not to change the user
 behavior. The choice of merge vs. rebase is entirely up to the user,
 and we are not changing that.

Right, but by not doing anything by default, you are forcing the user to
make a decision. Right now, we strongly encourage merging by making it
the default, and you have to learn about rebasing separately. But a
message that mentions them both as equals is going to lead to extra work
for the user; they have to figure out which one is most appropriate. My
concern is that this is non-trivial for new users, and that they may end
up arbitrarily picking rebase, which is probably not doing them any
favors if they do not understand it.

For clueful users, choosing between the two is not hard. But some people
seem to have trouble understanding the DAG. I don't know how large a
group that is, and how any pain caused by this change might compare to
the times it will help.

  If you are interested, I can ask the opinion of some of the GitHub
  trainers. They see a lot of new users and have a sense of what kinds of
  confusion come up most frequently, what kinds of workflows they tend to
  see, etc. Their experience may be biased towards corporate-ish users,
  though, because those are the people who pay for training.
 
 Ask. I'm sure they will tell you doing merges by mistake with 'git
 pull' is an issue.

I've sent an email. I'll post the response when I get it.

  Any more babysitting with essay long messages is counter-productive
  to the vast majority of Git users.
 
  I think that is what we have advice.* for.
 
 I don't understand what that means.

It means that some time ago, after many people complained that git did
not give enough hints, we added many hints. Some people who did not need
these hints would want to disable them, and we have the advice.*
config options to do so. So we can have a longer message for new users,
and a shorter one for people who do not want to be bothered with the
long advice.

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


Re: [PATCH 0/3] Reject non-ff pulls by default

2013-09-08 Thread Philip Oakley

From: Felipe Contreras felipe.contre...@gmail.com
Sent: Sunday, September 08, 2013 3:34 AM
On Thu, Sep 5, 2013 at 3:06 AM, John Keeping j...@keeping.me.uk 
wrote:

On Wed, Sep 04, 2013 at 03:59:18PM -0700, Junio C Hamano wrote:

Are there cases where you do not want to either rebase nor merge?
If so what do you want to do after git pull fetches from the other
side?  Nothing?


One other thing that I can see being useful occasionally is:

git rebase @{u}@{1} --onto @{u}

which allows local commits to be replayed onto a rewritten upstream
branch.

Although I agree with your side note below that people doing this may 
be
better off fetching and then updating their local branch, 
particularly

if @{1} is not the correct reflog entry for the upstream when they
created the branch.


That's why after recognizing the fact the you can't find the branch
point of a branch in Git, I decided to write patches to support the
@{tail} shorthand, which is basically the point where the branch was
created, or rebased to:

https://github.com/felipec/git/commits/fc/base

And if 'git rebase' was fixed to ignore the commits already in the
rebased onto branch, almost always what you would want to do is 'git
rebase @{tail} --onto @{upstream}'.

The use case that trips me up (i.e. doesn't fit the above) is when I 
have a branch that may need rebasing on (onto) pu, or may need rebasing 
on master, or next, depending on what others have been doing.


As a Distributed VCS (i.e. others doing work independently), a rebase 
always has the possibility that the world has moved on and one has to 
adapt to the new world order by moving location (--onto somewhere new), 
not just fixing up the house (patch conflicts). When the update order is 
unknown there is no guaranteed solution (IIUC).


You are right that mostly what one wants to do is stick with ones 
current location and patch up conflicts, it's just that one din't want 
any conflicts in the first place (i.e. the fast forward check). 


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


Re: Git tag output order is incorrect (IMHO)

2013-09-08 Thread Jeff King
On Tue, Aug 20, 2013 at 05:12:47PM +0200, Antoine Pelisse wrote:

 On Sat, Jul 20, 2013 at 2:22 AM, Jeff King p...@peff.net wrote:
  I do plan to finish it eventually, but if anyone else feels like picking
  it up, I'd be glad to review patches and/or share my work-in-progress as
  a starting point.
 
 I have some free time to come, and would like to work on that feature.
 Does the offer still hold ?
 If it does, I would be interested in your patches.

I'm sorry I have taken so long to get back to you on this. I was hoping
to revisit the topic and make sure the patches were in a sensible state
for showing to somebody. But it took me some time to get around to it,
and now that I have, they're really not looking very good.

My general strategy was to factor out all of the which refs to select
code from git-tag (which knows --contains and --points-at) and
git-branch (which knows --merged, --no-merged, and --contains), and then
make them all available in a library-ish way to both commands, as well
as for-each-ref (which also knows name matching, which all 3 should
know, too). You can see my messy in-progress commit (that does not even
compile) at:

  git://github.com/peff/git.git jk/contains-wip

Part of the complication is that the filters have to happen at different
times (you can efficiently ask --contains for each ref as you see it,
but asking --merged must happen after you have collected each one).

I do not recall at this point what other issues led me to stop working
on it (it may simply have been time for dinner, and I never came back to
it). So the patches there may or may not actually be helpful to you.

Sorry I can't be more helpful. I'd be happy to discuss or review if you
want to work on it.

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


Re: [PATCH 0/4] Re: [PATCH 3/4] t: rev-parse-parents: avoid yoda conditions

2013-09-08 Thread Philip Oakley

From: Jeff King p...@peff.net
Sent: Sunday, September 08, 2013 5:06 AM

Was there some objective argument made that I missed?


Here's more; human semantics:



Isn't this one of those pick any two from three tasks:
'human', 'objective', 'argument'.

Only 1/6 of the time is an 'objective' answer the result. 


Philip
Between thee and me there's nowt so queer as fowk,
and I ain't so sure about thee. old Yorkshire saying.


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


Re: [PATCH 0/3] Reject non-ff pulls by default

2013-09-08 Thread Felipe Contreras
On Sun, Sep 8, 2013 at 3:01 AM, Philip Oakley philipoak...@iee.org wrote:
 From: Felipe Contreras felipe.contre...@gmail.com
 Sent: Sunday, September 08, 2013 3:34 AM

 On Thu, Sep 5, 2013 at 3:06 AM, John Keeping j...@keeping.me.uk wrote:

 On Wed, Sep 04, 2013 at 03:59:18PM -0700, Junio C Hamano wrote:

 Are there cases where you do not want to either rebase nor merge?
 If so what do you want to do after git pull fetches from the other
 side?  Nothing?


 One other thing that I can see being useful occasionally is:

 git rebase @{u}@{1} --onto @{u}

 which allows local commits to be replayed onto a rewritten upstream
 branch.

 Although I agree with your side note below that people doing this may be
 better off fetching and then updating their local branch, particularly
 if @{1} is not the correct reflog entry for the upstream when they
 created the branch.


 That's why after recognizing the fact the you can't find the branch
 point of a branch in Git, I decided to write patches to support the
 @{tail} shorthand, which is basically the point where the branch was
 created, or rebased to:

 https://github.com/felipec/git/commits/fc/base

 And if 'git rebase' was fixed to ignore the commits already in the
 rebased onto branch, almost always what you would want to do is 'git
 rebase @{tail} --onto @{upstream}'.

 The use case that trips me up (i.e. doesn't fit the above) is when I have a
 branch that may need rebasing on (onto) pu, or may need rebasing on master,
 or next, depending on what others have been doing.

Yes, so you would do:

% git rebase --onto pu

Which would be translated to:

% git rebase @{tail} --onto pu

What's the problem?

 As a Distributed VCS (i.e. others doing work independently), a rebase always
 has the possibility that the world has moved on and one has to adapt to the
 new world order by moving location (--onto somewhere new), not just fixing
 up the house (patch conflicts). When the update order is unknown there is no
 guaranteed solution (IIUC).

Yeah, but almost always you want to rebase onto @{upstream}.

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


[PATCHv2 0/5] git-config and large integers

2013-09-08 Thread Jeff King
Here's a re-roll (and re-design) of my series to help with git config
and large integers. It takes the different approach we discussed of
simply removing (well, increasing) the range limits for git config
--int.

I also improved the error messages for bogus config (patches 3-4).

  [1/5]: config: factor out integer parsing from range checks
  [2/5]: config: properly range-check integer values
  [3/5]: config: set errno in numeric git_parse_* functions
  [4/5]: config: make numeric parsing errors more clear
  [5/5]: git-config: always treat --int as 64-bit internally

-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


[PATCH 2/5] config: properly range-check integer values

2013-09-08 Thread Jeff King
When we look at a config value as an integer using the
git_config_int function, we carefully range-check the value
we get and complain if it is out of our range. But the range
we compare to is that of a long, which we then cast to an
int in the function's return value. This means that on
systems where int and long have different sizes (e.g.,
LP64 systems), we may pass the range check, but then return
nonsense by truncating the value as we cast it to an int.

We can solve this by converting git_parse_long into
git_parse_int, and range-checking the int range. Nobody
actually cared that we used a long internally, since the
result was truncated anyway. And the only other caller of
git_parse_long is git_config_maybe_bool, which should be
fine to just use int (though we will now forbid out-of-range
nonsense like setting merge.ff to 10g to mean true,
which is probably a good thing).

Signed-off-by: Jeff King p...@peff.net
---

I tested this with:

diff --git a/t/t6500-gc.sh b/t/t6500-gc.sh
index b1a6365..5444952 100755
--- a/t/t6500-gc.sh
+++ b/t/t6500-gc.sh
@@ -25,4 +25,8 @@ test_expect_success 'gc -h with invalid 
configuration' '
test_i18ngrep [Uu]sage broken/usage
 '
 
+test_expect_success 'gc complains about out-of-range integers' '
+   test_must_fail git -c gc.auto=3g gc --auto
+'
+
 test_done

but that test is horrible for a few reasons:

  1. It depends on knowing that gc.auto uses git_config_int internally.

  2. It passes without the patch on 32-bit platforms.

  3. It won't pass with the patch on ILP64 systems.

We can't use git config --int to test it, because it's going to stop
using git_config_int later in the series. So I think we should just go
without a test.

 config.c | 12 ++--
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/config.c b/config.c
index ee7c1f8..0a65ac2 100644
--- a/config.c
+++ b/config.c
@@ -515,10 +515,10 @@ static int git_parse_long(const char *value, long *ret)
return 0;
 }
 
-static int git_parse_long(const char *value, long *ret)
+static int git_parse_int(const char *value, int *ret)
 {
intmax_t tmp;
-   if (!git_parse_signed(value, tmp, maximum_signed_value_of_type(long)))
+   if (!git_parse_signed(value, tmp, maximum_signed_value_of_type(int)))
return 0;
*ret = tmp;
return 1;
@@ -542,8 +542,8 @@ int git_config_int(const char *name, const char *value)
 
 int git_config_int(const char *name, const char *value)
 {
-   long ret = 0;
-   if (!git_parse_long(value, ret))
+   int ret;
+   if (!git_parse_int(value, ret))
die_bad_config(name);
return ret;
 }
@@ -575,10 +575,10 @@ int git_config_maybe_bool(const char *name, const char 
*value)
 
 int git_config_maybe_bool(const char *name, const char *value)
 {
-   long v = git_config_maybe_bool_text(name, value);
+   int v = git_config_maybe_bool_text(name, value);
if (0 = v)
return v;
-   if (git_parse_long(value, v))
+   if (git_parse_int(value, v))
return !!v;
return -1;
 }
-- 
1.8.4.2.g87d4a77

--
To unsubscribe from this list: send the line 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] config: set errno in numeric git_parse_* functions

2013-09-08 Thread Jeff King
When we are parsing an integer or unsigned long, we use
the strto*max functions, which properly set errno to ERANGE
if we get a large value. However, we also do further range
checks after applying our multiplication factor, but do not
set ERANGE. This means that a caller cannot tell if an error
was caused by ERANGE or if the input was simply not a valid
number.

This patch teaches git_parse_signed and git_parse_unsigned
reliably set ERANGE for range errors, and EINVAL for other
errors.

Signed-off-by: Jeff King p...@peff.net
---
I'm a little iffy on using errno like this. The normal way in git
would be to return an enum like:

  enum config_parse_error {
CONFIG_PARSE_SUCCESS = 0,
CONFIG_PARSE_RANGE = -1,
CONFIG_PARSE_INVALID_UNIT = -2
  };

But that would be changing the return semantics of git_parse_ulong
(which currently is 0 for fail, 1 for success) without changing its
signature. I figured this was the path of least resistance since we
already get ERANGE out of strtoimax, but I'm happy to switch it, too.

 config.c | 18 ++
 1 file changed, 14 insertions(+), 4 deletions(-)

diff --git a/config.c b/config.c
index 0a65ac2..7332b06 100644
--- a/config.c
+++ b/config.c
@@ -480,16 +480,21 @@ static int git_parse_signed(const char *value, intmax_t 
*ret, intmax_t max)
val = strtoimax(value, end, 0);
if (errno == ERANGE)
return 0;
-   if (!parse_unit_factor(end, factor))
+   if (!parse_unit_factor(end, factor)) {
+   errno = EINVAL;
return 0;
+   }
uval = abs(val);
uval *= factor;
-   if (uval  max || abs(val)  uval)
+   if (uval  max || abs(val)  uval) {
+   errno = ERANGE;
return 0;
+   }
val *= factor;
*ret = val;
return 1;
}
+   errno = EINVAL;
return 0;
 }
 
@@ -505,13 +510,18 @@ int git_parse_unsigned(const char *value, uintmax_t *ret, 
uintmax_t max)
if (errno == ERANGE)
return 0;
oldval = val;
-   if (!parse_unit_factor(end, val))
+   if (!parse_unit_factor(end, val)) {
+   errno = EINVAL;
return 0;
-   if (val  max || oldval  val)
+   }
+   if (val  max || oldval  val) {
+   errno = ERANGE;
return 0;
+   }
*ret = val;
return 1;
}
+   errno = EINVAL;
return 0;
 }
 
-- 
1.8.4.2.g87d4a77

--
To unsubscribe from this list: send the line 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] config: make numeric parsing errors more clear

2013-09-08 Thread Jeff King
If we try to parse an integer config argument and get a
number outside of the representable range, we die with the
cryptic message: bad config value for '%s'.

We can improve two things:

  1. Show the value that produced the error (e.g., bad
 config value '3g' for 'foo.bar').

  2. Mention the reason the value was rejected (e.g.,
 invalid unit versus out of range).

A few tests need to be updated with the new output, but that
should not be representative of real-world breakage, as
scripts should not be depending on the exact text of our
stderr output, which is subject to i18n anyway.

Signed-off-by: Jeff King p...@peff.net
---
I was tempted to clean up the tortured string construction in
die_bad_number(), but my understanding is that translators prefer to see
the string in as whole a piece as we can get it, rather than building it
piecemeal from ifs. And though this isn't marked for translation, it
probably should be.

 config.c| 17 -
 t/t1300-repo-config.sh  |  6 +++---
 t/t4055-diff-context.sh |  2 +-
 3 files changed, 16 insertions(+), 9 deletions(-)

diff --git a/config.c b/config.c
index 7332b06..87f87ba 100644
--- a/config.c
+++ b/config.c
@@ -543,18 +543,25 @@ int git_config_int(const char *name, const char *value)
return 1;
 }
 
-static void die_bad_config(const char *name)
+static void die_bad_number(const char *name, const char *value)
 {
+   const char *reason = errno == ERANGE ?
+out of range :
+invalid unit;
+   if (!value)
+   value = ;
+
if (cf  cf-name)
-   die(bad config value for '%s' in %s, name, cf-name);
-   die(bad config value for '%s', name);
+   die(bad numeric config value '%s' for '%s' in %s: %s,
+   value, name, cf-name, reason);
+   die(bad numeric config value '%s' for '%s': %s, value, name, reason);
 }
 
 int git_config_int(const char *name, const char *value)
 {
int ret;
if (!git_parse_int(value, ret))
-   die_bad_config(name);
+   die_bad_number(name, value);
return ret;
 }
 
@@ -562,7 +569,7 @@ unsigned long git_config_ulong(const char *name, const char 
*value)
 {
unsigned long ret;
if (!git_parse_ulong(value, ret))
-   die_bad_config(name);
+   die_bad_number(name, value);
return ret;
 }
 
diff --git a/t/t1300-repo-config.sh b/t/t1300-repo-config.sh
index c4a7d84..20aee6e 100755
--- a/t/t1300-repo-config.sh
+++ b/t/t1300-repo-config.sh
@@ -657,11 +657,11 @@ test_expect_success 'invalid unit' '
echo 1auto expect 
git config aninvalid.unit actual 
test_cmp expect actual 
-   cat  expect -\EOF
-   fatal: bad config value for '\''aninvalid.unit'\'' in .git/config
+   cat expect -\EOF
+   fatal: bad numeric config value '\''1auto'\'' for 
'\''aninvalid.unit'\'' in .git/config: invalid unit
EOF
test_must_fail git config --int --get aninvalid.unit 2actual 
-   test_cmp actual expect
+   test_i18ncmp expect actual
 '
 
 cat  expect  EOF
diff --git a/t/t4055-diff-context.sh b/t/t4055-diff-context.sh
index 97172b4..cd04543 100755
--- a/t/t4055-diff-context.sh
+++ b/t/t4055-diff-context.sh
@@ -73,7 +73,7 @@ test_expect_success 'non-integer config parsing' '
 test_expect_success 'non-integer config parsing' '
git config diff.context no 
test_must_fail git diff 2output 
-   test_i18ngrep bad config value output
+   test_i18ngrep bad numeric config value output
 '
 
 test_expect_success 'negative integer config parsing' '
-- 
1.8.4.2.g87d4a77

--
To unsubscribe from this list: send the line 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] git-config: always treat --int as 64-bit internally

2013-09-08 Thread Jeff King
When you run git config --int, the maximum size of integer
you get depends on how git was compiled, and what it
considers to be an int.

This is almost useful, because your scripts calling git
config will behave similarly to git internally. But relying
on this is dubious; you have to actually know how git treats
each value internally (e.g., int versus unsigned long),
which is not documented and is subject to change. And even
if you know it is unsigned long, we do not have a
git-config option to match that behavior.

Furthermore, you may simply be asking git to store a value
on your behalf (e.g., configuration for a hook). In that
case, the relevant range check has nothing at all to do with
git, but rather with whatever scripting tools you are using
(and git has no way of knowing what the appropriate range is
there).

Not only is the range check useless, but it is actively
harmful, as there is no way at all for scripts to look
at config variables with large values. For instance, one
cannot reliably get the value of pack.packSizeLimit via
git-config. On an LP64 system, git happily uses a 64-bit
unsigned long internally to represent the value, but the
script cannot read any value over 2G.

Ideally, the --int option would simply represent an
arbitrarily large integer. For practical purposes, however,
a 64-bit integer is large enough, and is much easier to
implement (and if somebody overflows it, we will still
notice the problem, and not simply return garbage).

Signed-off-by: Jeff King p...@peff.net
---
I kind of picked 64-bit as big enough. But I suppose we could also go
with intmax_t. The only thing we can't do is an unsigned value.

Also, this is the first use of PRId64. I notice we have compatibility
macros for PRIu*, but I'm not sure what to put in one for PRId64.

 builtin/config.c   |  7 ---
 cache.h|  1 +
 config.c   | 17 +
 t/t1300-repo-config.sh |  7 +++
 4 files changed, 29 insertions(+), 3 deletions(-)

diff --git a/builtin/config.c b/builtin/config.c
index 4010c43..8b182d2 100644
--- a/builtin/config.c
+++ b/builtin/config.c
@@ -128,7 +128,8 @@ static int collect_config(const char *key_, const char 
*value_, void *cb)
must_print_delim = 1;
}
if (types == TYPE_INT)
-   sprintf(value, %d, git_config_int(key_, value_?value_:));
+   sprintf(value, %PRId64,
+   git_config_int64(key_, value_ ? value_ : ));
else if (types == TYPE_BOOL)
vptr = git_config_bool(key_, value_) ? true : false;
else if (types == TYPE_BOOL_OR_INT) {
@@ -265,8 +266,8 @@ static char *normalize_value(const char *key, const char 
*value)
else {
normalized = xmalloc(64);
if (types == TYPE_INT) {
-   int v = git_config_int(key, value);
-   sprintf(normalized, %d, v);
+   int64_t v = git_config_int64(key, value);
+   sprintf(normalized, %PRId64, v);
}
else if (types == TYPE_BOOL)
sprintf(normalized, %s,
diff --git a/cache.h b/cache.h
index 85b544f..ac4525a 100644
--- a/cache.h
+++ b/cache.h
@@ -1190,6 +1190,7 @@ extern int git_config_int(const char *, const char *);
 extern int git_config_early(config_fn_t fn, void *, const char *repo_config);
 extern int git_parse_ulong(const char *, unsigned long *);
 extern int git_config_int(const char *, const char *);
+extern int64_t git_config_int64(const char *, const char *);
 extern unsigned long git_config_ulong(const char *, const char *);
 extern int git_config_bool_or_int(const char *, const char *, int *);
 extern int git_config_bool(const char *, const char *);
diff --git a/config.c b/config.c
index 87f87ba..6588cf5 100644
--- a/config.c
+++ b/config.c
@@ -534,6 +534,15 @@ static int git_parse_int(const char *value, int *ret)
return 1;
 }
 
+static int git_parse_int64(const char *value, int64_t *ret)
+{
+   intmax_t tmp;
+   if (!git_parse_signed(value, tmp, 
maximum_signed_value_of_type(int64_t)))
+   return 0;
+   *ret = tmp;
+   return 1;
+}
+
 int git_parse_ulong(const char *value, unsigned long *ret)
 {
uintmax_t tmp;
@@ -565,6 +574,14 @@ int git_config_int(const char *name, const char *value)
return ret;
 }
 
+int64_t git_config_int64(const char *name, const char *value)
+{
+   int64_t ret;
+   if (!git_parse_int64(value, ret))
+   die_bad_number(name, value);
+   return ret;
+}
+
 unsigned long git_config_ulong(const char *name, const char *value)
 {
unsigned long ret;
diff --git a/t/t1300-repo-config.sh b/t/t1300-repo-config.sh
index 20aee6e..b66c632 100755
--- a/t/t1300-repo-config.sh
+++ b/t/t1300-repo-config.sh
@@ -652,6 +652,13 @@ test_expect_success numbers '
test_cmp expect actual
 '
 
+test_expect_success '--int is at least 64 bits' '
+   git 

Re: [PATCH 0/3] Reject non-ff pulls by default

2013-09-08 Thread Philip Oakley

From: Felipe Contreras felipe.contre...@gmail.com
To: Philip Oakley philipoak...@iee.org
Cc: John Keeping j...@keeping.me.uk; Junio C Hamano 
gits...@pobox.com; git@vger.kernel.org; Andreas Krey 
a.k...@gmx.de

Sent: Sunday, September 08, 2013 9:16 AM
Subject: Re: [PATCH 0/3] Reject non-ff pulls by default


On Sun, Sep 8, 2013 at 3:01 AM, Philip Oakley philipoak...@iee.org 
wrote:

From: Felipe Contreras felipe.contre...@gmail.com
Sent: Sunday, September 08, 2013 3:34 AM

On Thu, Sep 5, 2013 at 3:06 AM, John Keeping j...@keeping.me.uk 
wrote:


On Wed, Sep 04, 2013 at 03:59:18PM -0700, Junio C Hamano wrote:


Are there cases where you do not want to either rebase nor merge?
If so what do you want to do after git pull fetches from the 
other

side?  Nothing?



One other thing that I can see being useful occasionally is:

git rebase @{u}@{1} --onto @{u}

which allows local commits to be replayed onto a rewritten upstream
branch.

Although I agree with your side note below that people doing this 
may be
better off fetching and then updating their local branch, 
particularly

if @{1} is not the correct reflog entry for the upstream when they
created the branch.



That's why after recognizing the fact the you can't find the branch
point of a branch in Git, I decided to write patches to support the
@{tail} shorthand, which is basically the point where the branch was
created, or rebased to:

https://github.com/felipec/git/commits/fc/base

And if 'git rebase' was fixed to ignore the commits already in the
rebased onto branch, almost always what you would want to do is 'git
rebase @{tail} --onto @{upstream}'.

The use case that trips me up (i.e. doesn't fit the above) is when I 
have a
branch that may need rebasing on (onto) pu, or may need rebasing on 
master,

or next, depending on what others have been doing.


Yes, so you would do:

% git rebase --onto pu

Which would be translated to:

% git rebase @{tail} --onto pu

What's the problem?

The 'problem' is (would be) that I don't yet know that I would need 
the --onto pu until I discover (how?) that the default rebase would 
result in conflicts.


As a Distributed VCS (i.e. others doing work independently), a rebase 
always
has the possibility that the world has moved on and one has to adapt 
to the
new world order by moving location (--onto somewhere new), not just 
fixing
up the house (patch conflicts). When the update order is unknown 
there is no

guaranteed solution (IIUC).


Yeah, but almost always you want to rebase onto @{upstream}.


Yeah, but almost always you want to check first *before* starting. 
That is, 'git rebase --abort' should not be required from the (user's 
selected /git's) default invocation.


--
Philip Oakley 


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


Re: [PATCH 0/3] Reject non-ff pulls by default

2013-09-08 Thread Felipe Contreras
On Sun, Sep 8, 2013 at 2:50 AM, Jeff King p...@peff.net wrote:
 On Sun, Sep 08, 2013 at 02:15:17AM -0500, Felipe Contreras wrote:

  I think the guy may be git itself. For example, here is a possible
  session with jc/pull-training-wheel:
 
$ git push

 Who told him to use 'git push'? Certainly not git.

 Any of the hundreds of existing tutorials that teach basic git commands
 like push?

You can't use a tutorial out there that just tells you to replace svn
commands with git alternatives, go to work and mess up the repository
history.

I'm trying to take the point of view of your hypothetical user working
on a repository where history is not important, but it seems more and
more than this person is just not real. If it's OK to push crappy
merges, somebody must have told him that was OK and provided him with
the commands.

If it's just some random person that read some random tutorial from
'svn' - 'git' working on a random repository that happens to accept
merges all over the place. Well I think that's a very very exceptional
situation.

And this person still wouldn't have a problem finding another tutorial
explaining what a merge is.

To ...
 ! [rejected]master - master (non-fast-forward)
error: failed to push some refs to '...'
hint: Updates were rejected because the tip of your current branch is 
  behind
hint: its remote counterpart. Integrate the remote changes (e.g.
hint: 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for 
  details.
 [...]

 Why stop there? Post the whole man page already.

 Moreover, it's overly verbose on all the wrong and irrelevant
 information. If you are going to waste precious screen state, explain
 wth a non fast-forward is; people can figure out what a merge is,
 and maybe a rebase, but a non fast-forward definitely not.

 Note that I was not trying to defend any of the messages, but only
 showing a plausible mechanism by which a user with basic knowledge that
 he wants to push may arrive at the question what is the difference
 between merge and rebase?.

Yes, and this person would have to read it online, like everything
else, because clearly Git documentation would do a bad job at it.
That's why the online documentation was needed in the first place.

The first hits of 'git merge vs rebase' are rather useful:
http://mislav.uniqpath.com/2013/02/merge-vs-rebase/
http://stackoverflow.com/questions/16336014/git-merge-vs-rebase
http://www.derekgourlay.com/archives/428
http://blog.sourcetreeapp.com/2012/08/21/merge-or-rebase/
http://git-scm.com/book/en/Git-Branching-Rebasing

Notice how none of the results point to official documentation,
precisely because it's not really useful.

 If you want to suggest revisions for the push message, go ahead. The
 push advice _is_ an attempt to define non-fast-forwards in plain
 language without taking up too much space, but perhaps you can do
 better.

I definitely can, but you would disagree.

But anyway, you are relying on the user having pushed first, what if
he is pulling first, or what if he doesn't have write access and is
only pulling?

 You could even suggest omitting it entirely, but I'm not sure if
 that is a good idea. It was not added in a vacuum; we lacked that advice
 for many years, and people complained about it quite a bit until it was
 added.

I would have to see the evidence, as I have never seen any complaints
about that. The complains are about the UI, and they still remain.

  The user is pointed at pull from push, and then gets presented with
  the merge or rebase choice. It may be that the advice you can find by
  googling merge vs rebase is enough to then help the person along
  (and/or we may need to improve the manpages in that respect).

 Yes, but that's not the use-case we are talking about. You mentioned
 specifically a svn-like worfklow where the guy was told by somebody
 else to replace the svn commands with git ones.

 No, I mentioned an svn-like workflow. I didn't say anything about how
 they were told. They might have been told by a co-worker, or read a
 brief tutorial on git, or read something like Git-SVN Crash Course.

Once again, this doesn't make any sense. People can't just push crap
merges to any repository.

 If we are talking about a guy that is learning git, that's and
 entirely different case.

 That is certainly what I meant to be talking about.

If he is learning Git, then he will be looking for the meaning of a
merge and a rebase. The fact that the repository accepts crappy merges
wouldn't be relevant.

 The purpose of this change in the code is not to change the user
 behavior. The choice of merge vs. rebase is entirely up to the user,
 and we are not changing that.

 Right, but by not doing anything by default, you are forcing the user to
 make a decision.

No, it would be a warning first, he wouldn't be *forced* to make a
decision, only after the deprecation period is over.

Then yes, if by then he 

Re: [PATCH 0/3] Reject non-ff pulls by default

2013-09-08 Thread Felipe Contreras
On Sun, Sep 8, 2013 at 3:42 AM, Philip Oakley philipoak...@iee.org wrote:

 The 'problem' is (would be) that I don't yet know that I would need the
 --onto pu until I discover (how?) that the default rebase would result in
 conflicts.

I don't see what that has to do with an invocation of 'git rebase'
without arguments, and @{tail}. There's absolutely no way Git can
figure out for you which is the appropriate place for you to rebase
onto.

However, it shouldn't be too difficult to write a tool that checks
multiple commits and tells you on top of which ones a rebase could
work, but I don't think 'git rebase' is the right place.

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


[PATCH 0/2] upload-pack keepalive

2013-09-08 Thread Jeff King
I've gotten complaints that cloning from github.com with -q will
sometimes abort before sending any data. The problem is that during a
quiet clone, upload-pack may be silent for a long time while preparing
the pack (i.e., the counting objects and compressing phases).

We have load balancers and reverse proxies sitting in front of the git
machines, and these machines may sometimes think the connection has hung
and drop it, even though if they had waited a few more seconds, the pack
would have started coming.

We mitigated it somewhat by bumping the timeouts on our side, but that's
only one piece of the puzzle. Clients may be going through http proxies
or stateful firewalls on their end, and neither we nor they have any
control.

This series teaches upload-pack to periodically send an empty sideband
data packet when pack-objects is being quiet. That keeps a small amount
of data flowing, and should be backwards compatible. I hand-tested it
against JGit, dulwich (via the mercurial git plugin), libgit2, and old
versions of git, and all worked fine.  It has also been running on
github.com for about a week and a half, and nobody has reported any
problems.

  [1/2]: upload-pack: send keepalive packets during pack computation
  [2/2]: upload-pack: bump keepalive default to 5 seconds

-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


[PATCH 2/2] upload-pack: bump keepalive default to 5 seconds

2013-09-08 Thread Jeff King
From: Jeff King p...@peff.net

There is no reason not to turn on keepalives by default.
They take very little bandwidth, and significantly less than
the progress reporting they are replacing. And in the case
that progress reporting is on, we should never need to send
a keepalive anyway, as we will constantly be showing
progress and resetting the keepalive timer.

We do not necessarily know what the client's idea of a
reasonable timeout is, so let's keep this on the low side of
5 seconds. That is high enough that we will always prefer
our normal 1-second progress reports to sending a keepalive
packet, but low enough that no sane client should consider
the connection hung.

Signed-off-by: Jeff King p...@peff.net
---
 Documentation/config.txt | 2 +-
 upload-pack.c| 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/Documentation/config.txt b/Documentation/config.txt
index 5d748f7..6b35578 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -2225,7 +2225,7 @@ uploadpack.keepalive::
the server to be hung and give up. Setting this option instructs
`upload-pack` to send an empty keepalive packet every
`uploadpack.keepalive` seconds. Setting this option to 0
-   disables keepalive packets entirely. The default is 0.
+   disables keepalive packets entirely. The default is 5 seconds.
 
 url.base.insteadOf::
Any URL that starts with this value will be rewritten to
diff --git a/upload-pack.c b/upload-pack.c
index c3e4a20..04a8707 100644
--- a/upload-pack.c
+++ b/upload-pack.c
@@ -40,7 +40,7 @@ static unsigned int timeout;
 static struct object_array want_obj;
 static struct object_array extra_edge_obj;
 static unsigned int timeout;
-static int keepalive = -1;
+static int keepalive = 5;
 /* 0 for no sideband,
  * otherwise maximum packet size (up to 65520 bytes).
  */
-- 
1.8.4.2.g87d4a77
--
To unsubscribe from this list: send the line 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/2] upload-pack: send keepalive packets during pack computation

2013-09-08 Thread Jeff King
Whenn upload-pack has started pack-objects, there may be a
quiet period while pack-objects prepares the pack (i.e.,
counting objects and delta compression).  Normally we would
see (and send to the client) progress information, but if
--quiet is in effect, pack-objects will produce nothing at
all until the pack data is ready. On a large repository,
this can take tens of seconds (or even minutes if the system
is loaded or the repository is badly packed). Clients or
intermediate proxies can sometimes give up in this
situation, assuming that the server or connection has hung.

This patch introduces a keepalive option; if upload-pack
sees no data from pack-objects for a certain number of
seconds, it will send an empty sideband data packet to let
the other side know that we are still working on it.

Signed-off-by: Jeff King p...@peff.net
---
 Documentation/config.txt | 11 +++
 upload-pack.c| 25 -
 2 files changed, 35 insertions(+), 1 deletion(-)

diff --git a/Documentation/config.txt b/Documentation/config.txt
index ec57a15..5d748f7 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -2216,6 +2216,17 @@ uploadpack.allowtipsha1inwant::
of a hidden ref (by default, such a request is rejected).
see also `uploadpack.hiderefs`.
 
+uploadpack.keepalive::
+   When `upload-pack` has started `pack-objects`, there may be a
+   quiet period while `pack-objects` prepares the pack. Normally
+   it would output progress information, but if `--quiet` was used
+   for the fetch, `pack-objects` will output nothing at all until
+   the pack data begins. Some clients and networks may consider
+   the server to be hung and give up. Setting this option instructs
+   `upload-pack` to send an empty keepalive packet every
+   `uploadpack.keepalive` seconds. Setting this option to 0
+   disables keepalive packets entirely. The default is 0.
+
 url.base.insteadOf::
Any URL that starts with this value will be rewritten to
start, instead, with base. In cases where some site serves a
diff --git a/upload-pack.c b/upload-pack.c
index 127e59a..c3e4a20 100644
--- a/upload-pack.c
+++ b/upload-pack.c
@@ -40,6 +40,7 @@ static unsigned int timeout;
 static struct object_array want_obj;
 static struct object_array extra_edge_obj;
 static unsigned int timeout;
+static int keepalive = -1;
 /* 0 for no sideband,
  * otherwise maximum packet size (up to 65520 bytes).
  */
@@ -200,6 +201,7 @@ static void create_pack_file(void)
while (1) {
struct pollfd pfd[2];
int pe, pu, pollsize;
+   int ret;
 
reset_timeout();
 
@@ -222,7 +224,8 @@ static void create_pack_file(void)
if (!pollsize)
break;
 
-   if (poll(pfd, pollsize, -1)  0) {
+   ret = poll(pfd, pollsize, 1000 * keepalive);
+   if (ret  0) {
if (errno != EINTR) {
error(poll failed, resuming: %s,
  strerror(errno));
@@ -284,6 +287,21 @@ static void create_pack_file(void)
if (sz  0)
goto fail;
}
+
+   /*
+* We hit the keepalive timeout without saying anything; send
+* an empty message on the data sideband just to let the other
+* side know we're still working on it, but don't have any data
+* yet.
+*
+* If we don't have a sideband channel, there's no room in the
+* protocol to say anything, so those clients are just out of
+* luck.
+*/
+   if (!ret  use_sideband) {
+   static const char buf[] = 0005\1;
+   write_or_die(1, buf, 5);
+   }
}
 
if (finish_command(pack_objects)) {
@@ -785,6 +803,11 @@ static int upload_pack_config(const char *var, const char 
*value, void *unused)
 {
if (!strcmp(uploadpack.allowtipsha1inwant, var))
allow_tip_sha1_in_want = git_config_bool(var, value);
+   else if (!strcmp(uploadpack.keepalive, var)) {
+   keepalive = git_config_int(var, value);
+   if (!keepalive)
+   keepalive = -1;
+   }
return parse_hide_refs_config(var, value, uploadpack);
 }
 
-- 
1.8.4.2.g87d4a77

--
To unsubscribe from this list: send the line 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: Officially start moving to the term 'staging area'

2013-09-08 Thread Felipe Contreras
On Sun, Sep 8, 2013 at 2:49 AM, Philip Oakley philipoak...@iee.org wrote:
 From: Felipe Contreras felipe.contre...@gmail.com
 Sent: Sunday, September 08, 2013 2:33 AM
 [snip...]

 The snapshot concept is totally orthogonal from the staging area
 concept. Git works in snapshots, which are frozen images of how the
 content tree was at a certain point in time; IOW; a commit.


 (I feel that) In most peoples minds the need for a staging area, and the use
 of snapshots, are related. Part of that relationship, often not noticed by
 those folks, is that they are 'orthogonal' to *each other*. Thus
 orthogonality means both un-related, and related at the same time (aren't we
 humans peculiar!). They are cleaved to each other.

Not really. You can argue that a movie is a sequence of snapshots, 24
of them per second, but most people don't think of it that way. You
can also argue that every change you do on a file is a snapshot, but
again, people don't think of it that way. Yes, you can argue that the
index is a snapshot, but it doesn't help to think of it that way. And
if you try to argue that way, then every waking moment is a snapshot,
what is NOT a snapshot?

The useful concept of snapshot is a moment in time stored for
posterity, in that sense a photo is a snapshot, a backup is a
snapshot, and a commit is a snapshot, but the staging area is not,
because it will be gone.

In fact, I just thought of another concept; a draft.

 When trying to explain staging/index I tend to use the analogy of an old
 style office (I am almost that old) where one has an In tray and an Out tray
 on one's desk (and one parked WIP for lunch time desk tidy), and the staging
 area is the basket at the end marked 'For Filing'. When the 'For Filing'
 basket is ready, one called the filing clerk to dictate the cover note and
 away it went, commited to some remote filing repository. Oh how things have
 changed ;-)

But that doesn't work well. You didn't add and remove things for the
'For Filing' as you worked, did you? Even if it did work, I don't
think it would be particularly useful to most people today.

I think a much more fitting analogy is a mail draft; you add and
remove things, change them, review, you can take as much time as you
want, and at the end of the day you can discard the whole thing.
Nothing gets done until you press 'send', which is analogous to
'commit'.

 _How_ that snapshot is created is an entirely different topic, and the
 staging area is a tool to create the desired snapshots. The user might
 decide to never use that tool (i.e. always run git commit -a), but the
 concept of snapshots remain. So, clearly, one concept has absolutely
 nothing to do with the other.


 The point would be that we allow a particular snapshot to be selected, and
 that the git commit -a is but one (common) method. Commit -a is like jumping
 in the car for a quick trip to the shops, while the selective staging of
 content is like packing for a holiday.

I still don't see it. When you do 'git commit' you don't have an array
of snapshots to choose from, you just have one, and it's not
particularly static, as you can add and remove things from it, so it's
not really a snapshot of your working directory even, because you can
add things that where never there.

And then if the staging area is a snapshot, then what is a commit?
Another snapshot? Then what is the difference between the two? One is
permanent and the other temporary? Well, then saying snapshot
wouldn't be enough to describe the staging area, you would need to say
preliminary snapshot, which doesn't really make sense, as those are
called previews, not snapshots. But why bother with snapshot, we can
use preliminary commit. But again, it sounds weird using the word
commit to something that can and is meant to change, unlike git
commits, and incidentally, unlike snapshots.

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


Re: [PATCH 0/3] Reject non-ff pulls by default

2013-09-08 Thread Philip Oakley

From: Felipe Contreras felipe.contre...@gmail.com
Sent: Sunday, September 08, 2013 9:49 AM
On Sun, Sep 8, 2013 at 3:42 AM, Philip Oakley philipoak...@iee.org 
wrote:


The 'problem' is (would be) that I don't yet know that I would need 
the
--onto pu until I discover (how?) that the default rebase would 
result in

conflicts.


I don't see what that has to do with an invocation of 'git rebase'
without arguments, and @{tail}.



There's absolutely no way Git can
figure out for you which is the appropriate place for you to rebase
onto.

.. which was my point. I may not have explained it that well.

Given that Git can't figure it out, we should stop trying in such cases.



However, it shouldn't be too difficult to write a tool that checks
multiple commits and tells you on top of which ones a rebase could
work, but I don't think 'git rebase' is the right place.


That's an SOS approach (Success Oriented Script)[1] that presumes the 
user is already better than they are - The Kruger Dunning paper [2] 
offers some insight into capability misconceptions (at all levels).


--
regards

Philip
--
[1] in the original it was a Success Oriented Schedule - one of those 
plans that hopeful managers put together on late running projects that 
amount to wishful thinking that hopefully garners them enough time to 
make a little progress and update their 'success stories'.
[2] http://dx.doi.org/10.%2F1467-8721.01235 Why People Fail to 
Recognize Their Own Incompetence. Though the corollaries (People fail 
to recognise their own skills, and hence they/we mishandle our 
communications) are just as (IMHO more) important. 


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


Re: [PATCH 0/3] Reject non-ff pulls by default

2013-09-08 Thread John Keeping
On Sun, Sep 08, 2013 at 02:54:20AM -0400, Jeff King wrote:
 I am genuinely curious what people in favor of this feature would want
 to say in the documentation to a user encountering this choice for the
 first time. In my experience, rebasing introduces more complications,
 specifically:
 
   1. the merge is backwards with respect to ours/theirs
 
   2. you may end up with difficult conflict resolution due to repeated
  changes over the same section of code. E.g., you write some buggy
  code and then fix it, but upstream has changed the same area.
  Rebasing involves first resolving your buggy version with the
  upstream code, and then resolving the fix on top of the previous
  resolution.
 
   3. rewriting of commits found in other branches, which then need
  rebased on top of the branch you just rebased
 
   4. a previously bug-free commit can show a bug after the rebase if
  other parts of the project changed (whereas with a merge, the bug
  would be attributable to the merge)
 
 I know those are all balanced by some advantages of rebasing, but I also
 think they are things that can be troublesome for a user who does not
 fully grok the rebase process. I'm just wondering if we should mention
 both, but steer people towards merging as the safer alternative (you
 might have ugly history, but you are less likely to create a mess with
 duplicate commits or badly-resolved conflicts).

The really correct thing to do here is to encourage a feature branch
workflow, but in my experience people are happier to walk through a
rebase than to switch over to feature branches completely.

An alternative pull mode would be:

git reset --keep @{u} 
git merge @{-1}

which gets a sensible history shape without any of your disadvantages
above.  But that didn't go anywhere last time it came up [1] [2].

[1] http://article.gmane.org/gmane.comp.version-control.git/210246
[2] http://article.gmane.org/gmane.comp.version-control.git/210625

  Fortunately there probably are very few of these users.
 
 Maybe. I am not sure how one would measure.
 
 If you are interested, I can ask the opinion of some of the GitHub
 trainers. They see a lot of new users and have a sense of what kinds of
 confusion come up most frequently, what kinds of workflows they tend to
 see, etc. Their experience may be biased towards corporate-ish users,
 though, because those are the people who pay for training.

I expect corporate environments are the ones in which this is relevant.
Open source projects that care about the shape of history can have one
person able to write to the central repository who can enforce the
policy they want.  This tends to be more difficult in a corporate
environment, particularly one that was previously using a centralised
VCS.
--
To unsubscribe from this list: send the line 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] Teach git to change to a given directory using -C option

2013-09-08 Thread Eric Sunshine
On Wed, Sep 4, 2013 at 8:20 AM, Nazri Ramliy ayieh...@gmail.com wrote:
 Subject: git: run in a directory given with -C option

 This is similar in spirit to to make -C dir ... and tar -C dir 
 ---
 diff --git a/Documentation/git.txt b/Documentation/git.txt
 index 83edf30..ae049da 100644
 --- a/Documentation/git.txt
 +++ b/Documentation/git.txt
 @@ -395,6 +395,20 @@ displayed. See linkgit:git-help[1] for more information,
  because `git --help ...` is converted internally into `git
  help ...`.

 +-C path::
 +   Run as if git was started in path instead of the current working
 +   directory.  When multiple -C options are given, each subsequent
 +   non-absolute -C path is interpreted relative to the preceding -C
 +   path.

For consistency with existing formatting in git.txt, you may want to
squash in the following fixes (sans gmail whitespace damage):

--- 8 ---
diff --git a/Documentation/git.txt b/Documentation/git.txt
index ae049da..6622037 100644
--- a/Documentation/git.txt
+++ b/Documentation/git.txt
@@ -396,14 +396,14 @@ because `git --help ...` is converted internally into `git
 help ...`.

 -C path::
- Run as if git was started in path instead of the current working
- directory.  When multiple -C options are given, each subsequent
- non-absolute -C path is interpreted relative to the preceding -C
- path.
+ Run as if git was started in 'path' instead of the current working
+ directory.  When multiple '-C' options are given, each subsequent
+ non-absolute `-C path` is interpreted relative to the preceding `-C
+ path`.
 +
-This option affects options that expect path name like --git-dir and
---work-tree in that their interpretations of the path names would be
-made relative to the working directory caused by the -C option. For
+This option affects options that expect path name like '--git-dir' and
+'--work-tree' in that their interpretations of the path names would be
+made relative to the working directory caused by the '-C' option. For
 example the following invocations are equivalent:

 git --git-dir=a.git --work-tree=b -C c status
--- 8 ---

 +This option affects options that expect path name like --git-dir and
 +--work-tree in that their interpretations of the path names would be
 +made relative to the working directory caused by the -C option. For
 +example the following invocations are equivalent:
 +
 +git --git-dir=a.git --work-tree=b -C c status
 +git --git-dir=c/a.git --work-tree=c/b status

Is the interaction of -C with --work-tree and --git-dir desirable or
useful? (I'm genuinely curious.) Do you have use-cases in mind? Would
mentioning them in the commit message help to justify the interaction?
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 0/3] Reject non-ff pulls by default

2013-09-08 Thread Philip Oakley

From: Philip Oakley philipoak...@iee.org
[2] http://dx.doi.org/10.%2F1467-8721.01235 Why People Fail to 
Recognize Their Own Incompetence.


Oops, That's behind a paywall, and a more recent variant.

 Though the corollaries 
(People fail to recognise their own skills, and hence they/we 
mishandle our communications) are just as (IMHO more) important.


I believe this is the on-line version of the original 1999 paper
http://mastercodeprofessional.com/library_files/Kruger-Dunning---Unskilled_and_Unaware_of_It_(2009).pdf

The section 5.1. The Burden of Expertise discusses my point above.
they [Experts] fail to realize that their proficiency is not 
necessarily shared by their peers.


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


[PATCH] Doc: 'replace' merge and non-merge commits

2013-09-08 Thread Philip Oakley
Merges are often treated as special case objects so tell users that
they are not special here.

Signed-off-by: Philip Oakley philipoak...@iee.org
---

This updates my in-line patch given in [PATCH v3 07/11]
Documentation/replace: tell that -f option bypasses the type check
($gmane/233997 05 September 2013 23:20) and Junio's comments
($gmane/234001 06 September 2013 00:13) 

Applies on top of pu and Christian Couder's series.

Philip

---
 Documentation/git-replace.txt | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/git-replace.txt b/Documentation/git-replace.txt
index 414000e..f373ab4 100644
--- a/Documentation/git-replace.txt
+++ b/Documentation/git-replace.txt
@@ -26,6 +26,7 @@ This restriction can be bypassed using `-f`.
 Unless `-f` is given, the 'replace' reference must not yet exist.
 
 There is no other restriction on the replaced and replacement objects.
+Merge commits can be replaced by non-merge commits and vice versa.
 
 Replacement references will be used by default by all Git commands
 except those doing reachability traversal (prune, pack transfer and
-- 
1.8.1.msysgit.1

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


Bash completion doing full tree traversal?

2013-09-08 Thread Isaac Levy
I experienced a weird stall from git bash completion:
$ git add pTAB

I did some investigation and found this call trace:

+ __git_index_files '--others --modified' ''
   --- git ls-files --exclude-standard --others --modified

This bash function captures output of the git call and strips all but
the base directory or base filename.  The results are limited to
entries in the current directory.

Appears to be from fea16b47b603e and first released in v1.8.2 (I have 1.8.4).

Isaac
--
To unsubscribe from this list: send the line 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 04/11] pack v4: add version argument to write_pack_header

2013-09-08 Thread Nguyễn Thái Ngọc Duy

Signed-off-by: Nguyễn Thái Ngọc Duy pclo...@gmail.com
---
 builtin/pack-objects.c | 2 +-
 bulk-checkin.c | 2 +-
 pack-write.c   | 7 +--
 pack.h | 3 +--
 4 files changed, 8 insertions(+), 6 deletions(-)

diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c
index f069462..33faea8 100644
--- a/builtin/pack-objects.c
+++ b/builtin/pack-objects.c
@@ -735,7 +735,7 @@ static void write_pack_file(void)
else
f = create_tmp_packfile(pack_tmp_name);
 
-   offset = write_pack_header(f, nr_remaining);
+   offset = write_pack_header(f, 2, nr_remaining);
if (!offset)
die_errno(unable to write pack header);
nr_written = 0;
diff --git a/bulk-checkin.c b/bulk-checkin.c
index 6b0b6d4..9d8f0d0 100644
--- a/bulk-checkin.c
+++ b/bulk-checkin.c
@@ -176,7 +176,7 @@ static void prepare_to_stream(struct bulk_checkin_state 
*state,
reset_pack_idx_option(state-pack_idx_opts);
 
/* Pretend we are going to write only one object */
-   state-offset = write_pack_header(state-f, 1);
+   state-offset = write_pack_header(state-f, 2, 1);
if (!state-offset)
die_errno(unable to write pack header);
 }
diff --git a/pack-write.c b/pack-write.c
index 631007e..88e4788 100644
--- a/pack-write.c
+++ b/pack-write.c
@@ -186,12 +186,15 @@ const char *write_idx_file(const char *index_name, struct 
pack_idx_entry **objec
return index_name;
 }
 
-off_t write_pack_header(struct sha1file *f, uint32_t nr_entries)
+off_t write_pack_header(struct sha1file *f,
+   int version, uint32_t nr_entries)
 {
struct pack_header hdr;
 
hdr.hdr_signature = htonl(PACK_SIGNATURE);
-   hdr.hdr_version = htonl(PACK_VERSION);
+   hdr.hdr_version = htonl(version);
+   if (!pack_version_ok(hdr.hdr_version))
+   die(_(pack version %d is not supported), version);
hdr.hdr_entries = htonl(nr_entries);
if (sha1write(f, hdr, sizeof(hdr)))
return 0;
diff --git a/pack.h b/pack.h
index aa6ee7d..855f6c6 100644
--- a/pack.h
+++ b/pack.h
@@ -8,7 +8,6 @@
  * Packed object header
  */
 #define PACK_SIGNATURE 0x5041434b  /* PACK */
-#define PACK_VERSION 2
 #define pack_version_ok(v) ((v) == htonl(2) || (v) == htonl(3))
 struct pack_header {
uint32_t hdr_signature;
@@ -80,7 +79,7 @@ extern const char *write_idx_file(const char *index_name, 
struct pack_idx_entry
 extern int check_pack_crc(struct packed_git *p, struct pack_window **w_curs, 
off_t offset, off_t len, unsigned int nr);
 extern int verify_pack_index(struct packed_git *);
 extern int verify_pack(struct packed_git *, verify_fn fn, struct progress *, 
uint32_t);
-extern off_t write_pack_header(struct sha1file *f, uint32_t);
+extern off_t write_pack_header(struct sha1file *f, int, uint32_t);
 extern void fixup_pack_header_footer(int, unsigned char *, const char *, 
uint32_t, unsigned char *, off_t);
 extern char *index_pack_lockfile(int fd);
 extern int encode_in_pack_object_header(enum object_type, uintmax_t, unsigned 
char *);
-- 
1.8.2.83.gc99314b

--
To unsubscribe from this list: send the line 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 05/11] pack-write.c: add pv4_encode_in_pack_object_header

2013-09-08 Thread Nguyễn Thái Ngọc Duy

Signed-off-by: Nguyễn Thái Ngọc Duy pclo...@gmail.com
---
 pack-write.c | 29 +
 pack.h   |  1 +
 2 files changed, 30 insertions(+)

diff --git a/pack-write.c b/pack-write.c
index 88e4788..6f11104 100644
--- a/pack-write.c
+++ b/pack-write.c
@@ -1,6 +1,7 @@
 #include cache.h
 #include pack.h
 #include csum-file.h
+#include varint.h
 
 void reset_pack_idx_option(struct pack_idx_option *opts)
 {
@@ -340,6 +341,34 @@ int encode_in_pack_object_header(enum object_type type, 
uintmax_t size, unsigned
return n;
 }
 
+/*
+ * The per-object header is a pretty dense thing, which is
+ *  - first byte: low four bits are size, then three bits of type,
+ *and the high bit is size continues.
+ *  - each byte afterwards: low seven bits are size continuation,
+ *with the high bit being size continues
+ */
+int pv4_encode_in_pack_object_header(enum object_type type,
+uintmax_t size, unsigned char *hdr)
+{
+   uintmax_t val;
+   if (type  OBJ_COMMIT || type  OBJ_PV4_TREE || type == OBJ_OFS_DELTA)
+   die(bad type %d, type);
+
+   /*
+* We allocate 4 bits in the LSB for the object type which
+* should be good for quite a while, given that we effectively
+* encodes only 5 object types: commit, tree, blob, delta,
+* tag.
+*/
+   val = size;
+   if (MSB(val, 4))
+   die(fixme: the code doesn't currently cope with big sizes);
+   val = 4;
+   val |= type;
+   return encode_varint(val, hdr);
+}
+
 struct sha1file *create_tmp_packfile(char **pack_tmp_name)
 {
char tmpname[PATH_MAX];
diff --git a/pack.h b/pack.h
index 855f6c6..38f869d 100644
--- a/pack.h
+++ b/pack.h
@@ -83,6 +83,7 @@ extern off_t write_pack_header(struct sha1file *f, int, 
uint32_t);
 extern void fixup_pack_header_footer(int, unsigned char *, const char *, 
uint32_t, unsigned char *, off_t);
 extern char *index_pack_lockfile(int fd);
 extern int encode_in_pack_object_header(enum object_type, uintmax_t, unsigned 
char *);
+extern int pv4_encode_in_pack_object_header(enum object_type, uintmax_t, 
unsigned char *);
 
 #define PH_ERROR_EOF   (-1)
 #define PH_ERROR_PACK_SIGNATURE(-2)
-- 
1.8.2.83.gc99314b

--
To unsubscribe from this list: send the line 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 07/11] list-objects.c: add show_tree_entry callback to traverse_commit_list

2013-09-08 Thread Nguyễn Thái Ngọc Duy
This helps construct tree dictionary in pack v4.

Signed-off-by: Nguyễn Thái Ngọc Duy pclo...@gmail.com
---
 builtin/pack-objects.c | 2 +-
 builtin/rev-list.c | 4 ++--
 list-objects.c | 9 -
 list-objects.h | 3 ++-
 upload-pack.c  | 2 +-
 5 files changed, 14 insertions(+), 6 deletions(-)

diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c
index ef68fc5..b38d3dc 100644
--- a/builtin/pack-objects.c
+++ b/builtin/pack-objects.c
@@ -2380,7 +2380,7 @@ static void get_object_list(int ac, const char **av)
if (prepare_revision_walk(revs))
die(revision walk setup failed);
mark_edges_uninteresting(revs.commits, revs, show_edge);
-   traverse_commit_list(revs, show_commit, show_object, NULL);
+   traverse_commit_list(revs, show_commit, NULL, show_object, NULL);
 
if (keep_unreachable)
add_objects_in_unpacked_packs(revs);
diff --git a/builtin/rev-list.c b/builtin/rev-list.c
index a5ec30d..b25f896 100644
--- a/builtin/rev-list.c
+++ b/builtin/rev-list.c
@@ -243,7 +243,7 @@ static int show_bisect_vars(struct rev_list_info *info, int 
reaches, int all)
strcpy(hex, sha1_to_hex(revs-commits-item-object.sha1));
 
if (flags  BISECT_SHOW_ALL) {
-   traverse_commit_list(revs, show_commit, show_object, info);
+   traverse_commit_list(revs, show_commit, NULL, show_object, 
info);
printf(--\n);
}
 
@@ -348,7 +348,7 @@ int cmd_rev_list(int argc, const char **argv, const char 
*prefix)
return show_bisect_vars(info, reaches, all);
}
 
-   traverse_commit_list(revs, show_commit, show_object, info);
+   traverse_commit_list(revs, show_commit, NULL, show_object, info);
 
if (revs.count) {
if (revs.left_right  revs.cherry_mark)
diff --git a/list-objects.c b/list-objects.c
index 3dd4a96..6def897 100644
--- a/list-objects.c
+++ b/list-objects.c
@@ -61,6 +61,7 @@ static void process_gitlink(struct rev_info *revs,
 
 static void process_tree(struct rev_info *revs,
 struct tree *tree,
+show_tree_entry_fn show_tree_entry,
 show_object_fn show,
 struct name_path *path,
 struct strbuf *base,
@@ -107,9 +108,13 @@ static void process_tree(struct rev_info *revs,
continue;
}
 
+   if (show_tree_entry)
+   show_tree_entry(entry, cb_data);
+
if (S_ISDIR(entry.mode))
process_tree(revs,
 lookup_tree(entry.sha1),
+show_tree_entry,
 show, me, base, entry.path,
 cb_data);
else if (S_ISGITLINK(entry.mode))
@@ -167,6 +172,7 @@ static void add_pending_tree(struct rev_info *revs, struct 
tree *tree)
 
 void traverse_commit_list(struct rev_info *revs,
  show_commit_fn show_commit,
+ show_tree_entry_fn show_tree_entry,
  show_object_fn show_object,
  void *data)
 {
@@ -196,7 +202,8 @@ void traverse_commit_list(struct rev_info *revs,
continue;
}
if (obj-type == OBJ_TREE) {
-   process_tree(revs, (struct tree *)obj, show_object,
+   process_tree(revs, (struct tree *)obj,
+show_tree_entry, show_object,
 NULL, base, name, data);
continue;
}
diff --git a/list-objects.h b/list-objects.h
index 3db7bb6..297b2e0 100644
--- a/list-objects.h
+++ b/list-objects.h
@@ -2,8 +2,9 @@
 #define LIST_OBJECTS_H
 
 typedef void (*show_commit_fn)(struct commit *, void *);
+typedef void (*show_tree_entry_fn)(const struct name_entry *, void *);
 typedef void (*show_object_fn)(struct object *, const struct name_path *, 
const char *, void *);
-void traverse_commit_list(struct rev_info *, show_commit_fn, show_object_fn, 
void *);
+void traverse_commit_list(struct rev_info *, show_commit_fn, 
show_tree_entry_fn, show_object_fn, void *);
 
 typedef void (*show_edge_fn)(struct commit *);
 void mark_edges_uninteresting(struct commit_list *, struct rev_info *, 
show_edge_fn);
diff --git a/upload-pack.c b/upload-pack.c
index 127e59a..ccf76d9 100644
--- a/upload-pack.c
+++ b/upload-pack.c
@@ -125,7 +125,7 @@ static int do_rev_list(int in, int out, void *user_data)
for (i = 0; i  extra_edge_obj.nr; i++)
fprintf(pack_pipe, -%s\n, sha1_to_hex(
extra_edge_obj.objects[i].item-sha1));
-   traverse_commit_list(revs, show_commit, show_object, NULL);
+   traverse_commit_list(revs, 

[PATCH 00/11] pack v4 support in pack-objects

2013-09-08 Thread Nguyễn Thái Ngọc Duy
I can produce pack v4 on git.git with this and verify it with
index-pack. I'm not familiar with pack-objects code and not really
confident with my changes. Suggestions are welcome.

Also I chose to keep packv4-create.c in libgit.a and move test code
out to test-packv4.c. Not sure if it's good decision. The other option
is to copy necessary code to pack-objects.c, then delete
packv4-create.c in the end. Either way we have the same amount of code
move.

Thin pack support is not there yet, but it should be simple on
pack-objects' end. Like the compatibility layer you added to
sha1_file.c, this code does not take advantage of v4 as source packs
(performance regressions entail) A lot of rooms for improvements.

Nguyễn Thái Ngọc Duy (11):
  pack v4: allocate dicts from the beginning
  pack v4: stop using static/global variables in packv4-create.c
  pack v4: move packv4-create.c to libgit.a
  pack v4: add version argument to write_pack_header
  pack-write.c: add pv4_encode_in_pack_object_header
  pack-objects: add --version to specify written pack version
  list-objects.c: add show_tree_entry callback to traverse_commit_list
  pack-objects: create pack v4 tables
  pack-objects: do not cache delta for v4 trees
  pack-objects: exclude commits out of delta objects in v4
  pack-objects: support writing pack v4

 Makefile   |   4 +-
 builtin/pack-objects.c | 187 +++--
 builtin/rev-list.c |   4 +-
 bulk-checkin.c |   2 +-
 list-objects.c |   9 +-
 list-objects.h |   3 +-
 pack-write.c   |  36 +++-
 pack.h |   6 +-
 packv4-create.c| 534 -
 packv4-create.h (new)  |  50 +
 test-packv4.c (new)| 476 +++
 upload-pack.c  |   2 +-
 12 files changed, 789 insertions(+), 524 deletions(-)
 create mode 100644 packv4-create.h
 create mode 100644 test-packv4.c

-- 
1.8.2.83.gc99314b

--
To unsubscribe from this list: send the line 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 06/11] pack-objects: add --version to specify written pack version

2013-09-08 Thread Nguyễn Thái Ngọc Duy

Signed-off-by: Nguyễn Thái Ngọc Duy pclo...@gmail.com
---
 builtin/pack-objects.c | 6 +-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c
index 33faea8..ef68fc5 100644
--- a/builtin/pack-objects.c
+++ b/builtin/pack-objects.c
@@ -81,6 +81,7 @@ static int num_preferred_base;
 static struct progress *progress_state;
 static int pack_compression_level = Z_DEFAULT_COMPRESSION;
 static int pack_compression_seen;
+static int pack_version = 2;
 
 static unsigned long delta_cache_size = 0;
 static unsigned long max_delta_cache_size = 256 * 1024 * 1024;
@@ -735,7 +736,7 @@ static void write_pack_file(void)
else
f = create_tmp_packfile(pack_tmp_name);
 
-   offset = write_pack_header(f, 2, nr_remaining);
+   offset = write_pack_header(f, pack_version, nr_remaining);
if (!offset)
die_errno(unable to write pack header);
nr_written = 0;
@@ -2455,6 +2456,7 @@ int cmd_pack_objects(int argc, const char **argv, const 
char *prefix)
{ OPTION_CALLBACK, 0, index-version, NULL, 
N_(version[,offset]),
  N_(write the pack index file in the specified idx format 
version),
  0, option_parse_index_version },
+   OPT_INTEGER(0, version, pack_version, N_(pack version)),
OPT_ULONG(0, max-pack-size, pack_size_limit,
  N_(maximum size of each output pack file)),
OPT_BOOL(0, local, local,
@@ -2525,6 +2527,8 @@ int cmd_pack_objects(int argc, const char **argv, const 
char *prefix)
}
if (pack_to_stdout != !base_name || argc)
usage_with_options(pack_usage, pack_objects_options);
+   if (pack_version != 2)
+   die(_(pack version %d is not supported), pack_version);
 
rp_av[rp_ac++] = pack-objects;
if (thin) {
-- 
1.8.2.83.gc99314b

--
To unsubscribe from this list: send the line 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 01/11] pack v4: allocate dicts from the beginning

2013-09-08 Thread Nguyễn Thái Ngọc Duy
commit_ident_table and tree_path_table are local to packv4-create.c
and test-packv4.c. Move them out of add_*_dict_entries so
add_*_dict_entries can be exported to pack-objects.c

Signed-off-by: Nguyễn Thái Ngọc Duy pclo...@gmail.com
---
 packv4-create.c | 22 --
 1 file changed, 12 insertions(+), 10 deletions(-)

diff --git a/packv4-create.c b/packv4-create.c
index 38fa594..dbc2a03 100644
--- a/packv4-create.c
+++ b/packv4-create.c
@@ -181,14 +181,12 @@ static char *get_nameend_and_tz(char *from, int *tz_val)
return end;
 }
 
-static int add_commit_dict_entries(void *buf, unsigned long size)
+int add_commit_dict_entries(struct dict_table *commit_ident_table,
+   void *buf, unsigned long size)
 {
char *name, *end = NULL;
int tz_val;
 
-   if (!commit_ident_table)
-   commit_ident_table = create_dict_table();
-
/* parse and add author info */
name = strstr(buf, \nauthor );
if (name) {
@@ -212,14 +210,12 @@ static int add_commit_dict_entries(void *buf, unsigned 
long size)
return 0;
 }
 
-static int add_tree_dict_entries(void *buf, unsigned long size)
+static int add_tree_dict_entries(struct dict_table *tree_path_table,
+void *buf, unsigned long size)
 {
struct tree_desc desc;
struct name_entry name_entry;
 
-   if (!tree_path_table)
-   tree_path_table = create_dict_table();
-
init_tree_desc(desc, buf, size);
while (tree_entry(desc, name_entry)) {
int pathlen = tree_entry_len(name_entry);
@@ -659,6 +655,9 @@ static int create_pack_dictionaries(struct packed_git *p,
struct progress *progress_state;
unsigned int i;
 
+   commit_ident_table = create_dict_table();
+   tree_path_table = create_dict_table();
+
progress_state = start_progress(Scanning objects, p-num_objects);
for (i = 0; i  p-num_objects; i++) {
struct pack_idx_entry *obj = obj_list[i];
@@ -666,7 +665,8 @@ static int create_pack_dictionaries(struct packed_git *p,
enum object_type type;
unsigned long size;
struct object_info oi = {};
-   int (*add_dict_entries)(void *, unsigned long);
+   int (*add_dict_entries)(struct dict_table *, void *, unsigned 
long);
+   struct dict_table *dict;
 
display_progress(progress_state, i+1);
 
@@ -679,9 +679,11 @@ static int create_pack_dictionaries(struct packed_git *p,
switch (type) {
case OBJ_COMMIT:
add_dict_entries = add_commit_dict_entries;
+   dict = commit_ident_table;
break;
case OBJ_TREE:
add_dict_entries = add_tree_dict_entries;
+   dict = tree_path_table;
break;
default:
continue;
@@ -693,7 +695,7 @@ static int create_pack_dictionaries(struct packed_git *p,
if (check_sha1_signature(obj-sha1, data, size, typename(type)))
die(packed %s from %s is corrupt,
sha1_to_hex(obj-sha1), p-pack_name);
-   if (add_dict_entries(data, size)  0)
+   if (add_dict_entries(dict, data, size)  0)
die(can't process %s object %s,
typename(type), sha1_to_hex(obj-sha1));
free(data);
-- 
1.8.2.83.gc99314b

--
To unsubscribe from this list: send the line 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 03/11] pack v4: move packv4-create.c to libgit.a

2013-09-08 Thread Nguyễn Thái Ngọc Duy
git-packv4-create now becomes test-packv4. Code that will not be used
by pack-objects.c is moved to test-packv4.c. It may be removed when
the code transition to pack-objects completes.

Signed-off-by: Nguyễn Thái Ngọc Duy pclo...@gmail.com
---
 Makefile|   4 +-
 packv4-create.c | 491 +---
 packv4-create.h |  39 +
 test-packv4.c (new) | 476 ++
 4 files changed, 525 insertions(+), 485 deletions(-)
 create mode 100644 test-packv4.c

diff --git a/Makefile b/Makefile
index 22fc276..af2e3e3 100644
--- a/Makefile
+++ b/Makefile
@@ -550,7 +550,6 @@ PROGRAM_OBJS += shell.o
 PROGRAM_OBJS += show-index.o
 PROGRAM_OBJS += upload-pack.o
 PROGRAM_OBJS += remote-testsvn.o
-PROGRAM_OBJS += packv4-create.o
 
 # Binary suffix, set to .exe for Windows builds
 X =
@@ -568,6 +567,7 @@ TEST_PROGRAMS_NEED_X += test-line-buffer
 TEST_PROGRAMS_NEED_X += test-match-trees
 TEST_PROGRAMS_NEED_X += test-mergesort
 TEST_PROGRAMS_NEED_X += test-mktemp
+TEST_PROGRAMS_NEED_X += test-packv4
 TEST_PROGRAMS_NEED_X += test-parse-options
 TEST_PROGRAMS_NEED_X += test-path-utils
 TEST_PROGRAMS_NEED_X += test-prio-queue
@@ -702,6 +702,7 @@ LIB_H += notes.h
 LIB_H += object.h
 LIB_H += pack-revindex.h
 LIB_H += pack.h
+LIB_H += packv4-create.h
 LIB_H += packv4-parse.h
 LIB_H += parse-options.h
 LIB_H += patch-ids.h
@@ -839,6 +840,7 @@ LIB_OBJS += object.o
 LIB_OBJS += pack-check.o
 LIB_OBJS += pack-revindex.o
 LIB_OBJS += pack-write.o
+LIB_OBJS += packv4-create.o
 LIB_OBJS += packv4-parse.o
 LIB_OBJS += pager.o
 LIB_OBJS += parse-options.o
diff --git a/packv4-create.c b/packv4-create.c
index 920a0b4..cdf82c0 100644
--- a/packv4-create.c
+++ b/packv4-create.c
@@ -18,9 +18,9 @@
 #include packv4-create.h
 
 
-static int pack_compression_seen;
-static int pack_compression_level = Z_DEFAULT_COMPRESSION;
-static int min_tree_copy = 1;
+int pack_compression_seen;
+int pack_compression_level = Z_DEFAULT_COMPRESSION;
+int min_tree_copy = 1;
 
 struct data_entry {
unsigned offset;
@@ -28,17 +28,6 @@ struct data_entry {
unsigned hits;
 };
 
-struct dict_table {
-   unsigned char *data;
-   unsigned cur_offset;
-   unsigned size;
-   struct data_entry *entry;
-   unsigned nb_entries;
-   unsigned max_entries;
-   unsigned *hash;
-   unsigned hash_size;
-};
-
 struct dict_table *create_dict_table(void)
 {
return xcalloc(sizeof(struct dict_table), 1);
@@ -139,7 +128,7 @@ static int cmp_dict_entries(const void *a_, const void *b_)
return diff;
 }
 
-static void sort_dict_entries_by_hits(struct dict_table *t)
+void sort_dict_entries_by_hits(struct dict_table *t)
 {
qsort(t-entry, t-nb_entries, sizeof(*t-entry), cmp_dict_entries);
t-hash_size = (t-nb_entries * 4 / 3) / 2;
@@ -208,7 +197,7 @@ int add_commit_dict_entries(struct dict_table 
*commit_ident_table,
return 0;
 }
 
-static int add_tree_dict_entries(struct dict_table *tree_path_table,
+int add_tree_dict_entries(struct dict_table *tree_path_table,
 void *buf, unsigned long size)
 {
struct tree_desc desc;
@@ -224,7 +213,7 @@ static int add_tree_dict_entries(struct dict_table 
*tree_path_table,
return 0;
 }
 
-void dump_dict_table(struct dict_table *t)
+static void dump_dict_table(struct dict_table *t)
 {
int i;
 
@@ -241,7 +230,7 @@ void dump_dict_table(struct dict_table *t)
}
 }
 
-static void dict_dump(struct packv4_tables *v4)
+void dict_dump(struct packv4_tables *v4)
 {
dump_dict_table(v4-commit_ident_table);
dump_dict_table(v4-tree_path_table);
@@ -611,103 +600,6 @@ void *pv4_encode_tree(const struct packv4_tables *v4,
return buffer;
 }
 
-static struct pack_idx_entry *get_packed_object_list(struct packed_git *p)
-{
-   unsigned i, nr_objects = p-num_objects;
-   struct pack_idx_entry *objects;
-
-   objects = xmalloc((nr_objects + 1) * sizeof(*objects));
-   objects[nr_objects].offset = p-pack_size - 20;
-   for (i = 0; i  nr_objects; i++) {
-   hashcpy(objects[i].sha1, nth_packed_object_sha1(p, i));
-   objects[i].offset = nth_packed_object_offset(p, i);
-   }
-
-   return objects;
-}
-
-static int sort_by_offset(const void *e1, const void *e2)
-{
-   const struct pack_idx_entry * const *entry1 = e1;
-   const struct pack_idx_entry * const *entry2 = e2;
-   if ((*entry1)-offset  (*entry2)-offset)
-   return -1;
-   if ((*entry1)-offset  (*entry2)-offset)
-   return 1;
-   return 0;
-}
-
-static struct pack_idx_entry **sort_objs_by_offset(struct pack_idx_entry *list,
-   unsigned nr_objects)
-{
-   unsigned i;
-   struct pack_idx_entry **sorted;
-
-   sorted = xmalloc((nr_objects + 1) * sizeof(*sorted));
-   for (i = 0; i  nr_objects + 1; i++)
-  

[PATCH 02/11] pack v4: stop using static/global variables in packv4-create.c

2013-09-08 Thread Nguyễn Thái Ngọc Duy

Signed-off-by: Nguyễn Thái Ngọc Duy pclo...@gmail.com
---
 packv4-create.c   | 103 --
 packv4-create.h (new) |  11 ++
 2 files changed, 69 insertions(+), 45 deletions(-)
 create mode 100644 packv4-create.h

diff --git a/packv4-create.c b/packv4-create.c
index dbc2a03..920a0b4 100644
--- a/packv4-create.c
+++ b/packv4-create.c
@@ -15,6 +15,7 @@
 #include pack-revindex.h
 #include progress.h
 #include varint.h
+#include packv4-create.h
 
 
 static int pack_compression_seen;
@@ -145,9 +146,6 @@ static void sort_dict_entries_by_hits(struct dict_table *t)
rehash_entries(t);
 }
 
-static struct dict_table *commit_ident_table;
-static struct dict_table *tree_path_table;
-
 /*
  * Parse the author/committer line from a canonical commit object.
  * The 'from' argument points right after the author  or committer 
@@ -243,10 +241,10 @@ void dump_dict_table(struct dict_table *t)
}
 }
 
-static void dict_dump(void)
+static void dict_dump(struct packv4_tables *v4)
 {
-   dump_dict_table(commit_ident_table);
-   dump_dict_table(tree_path_table);
+   dump_dict_table(v4-commit_ident_table);
+   dump_dict_table(v4-tree_path_table);
 }
 
 /*
@@ -254,10 +252,12 @@ static void dict_dump(void)
  * pack SHA1 table incremented by 1, or the literal SHA1 value prefixed
  * with a zero byte if the needed SHA1 is not available in the table.
  */
-static struct pack_idx_entry *all_objs;
-static unsigned all_objs_nr;
-static int encode_sha1ref(const unsigned char *sha1, unsigned char *buf)
+
+int encode_sha1ref(const struct packv4_tables *v4,
+  const unsigned char *sha1, unsigned char *buf)
 {
+   unsigned all_objs_nr = v4-all_objs_nr;
+   struct pack_idx_entry *all_objs = v4-all_objs;
unsigned lo = 0, hi = all_objs_nr;
 
do {
@@ -284,7 +284,8 @@ static int encode_sha1ref(const unsigned char *sha1, 
unsigned char *buf)
  * strict so to ensure the canonical version may always be
  * regenerated and produce the same hash.
  */
-void *pv4_encode_commit(void *buffer, unsigned long *sizep)
+void *pv4_encode_commit(const struct packv4_tables *v4,
+   void *buffer, unsigned long *sizep)
 {
unsigned long size = *sizep;
char *in, *tail, *end;
@@ -310,7 +311,7 @@ void *pv4_encode_commit(void *buffer, unsigned long *sizep)
if (get_sha1_lowhex(in + 5, sha1)  0)
goto bad_data;
in += 46;
-   out += encode_sha1ref(sha1, out);
+   out += encode_sha1ref(v4, sha1, out);
 
/* count how many parent lines */
nb_parents = 0;
@@ -325,7 +326,7 @@ void *pv4_encode_commit(void *buffer, unsigned long *sizep)
while (nb_parents--) {
if (get_sha1_lowhex(in + 7, sha1))
goto bad_data;
-   out += encode_sha1ref(sha1, out);
+   out += encode_sha1ref(v4, sha1, out);
in += 48;
}
 
@@ -337,7 +338,7 @@ void *pv4_encode_commit(void *buffer, unsigned long *sizep)
end = get_nameend_and_tz(in, tz_val);
if (!end)
goto bad_data;
-   author_index = dict_add_entry(commit_ident_table, tz_val, in, end - in);
+   author_index = dict_add_entry(v4-commit_ident_table, tz_val, in, end - 
in);
if (author_index  0)
goto bad_dict;
author_time = strtoul(end, end, 10);
@@ -353,7 +354,7 @@ void *pv4_encode_commit(void *buffer, unsigned long *sizep)
end = get_nameend_and_tz(in, tz_val);
if (!end)
goto bad_data;
-   commit_index = dict_add_entry(commit_ident_table, tz_val, in, end - in);
+   commit_index = dict_add_entry(v4-commit_ident_table, tz_val, in, end - 
in);
if (commit_index  0)
goto bad_dict;
commit_time = strtoul(end, end, 10);
@@ -436,7 +437,8 @@ static int compare_tree_entries(struct name_entry *e1, 
struct name_entry *e2)
  * If a delta buffer is provided, we may encode multiple ranges of tree
  * entries against that buffer.
  */
-void *pv4_encode_tree(void *_buffer, unsigned long *sizep,
+void *pv4_encode_tree(const struct packv4_tables *v4,
+ void *_buffer, unsigned long *sizep,
  void *delta, unsigned long delta_size,
  const unsigned char *delta_sha1)
 {
@@ -551,7 +553,7 @@ void *pv4_encode_tree(void *_buffer, unsigned long *sizep,
cp += encode_varint(copy_start, cp);
cp += encode_varint(copy_count, cp);
if (first_delta)
-   cp += encode_sha1ref(delta_sha1, cp);
+   cp += encode_sha1ref(v4, delta_sha1, cp);
 
/*
 * Now let's make sure this is going to take less
@@ -577,7 +579,7 @@ void *pv4_encode_tree(void *_buffer, unsigned long *sizep,
}
 
pathlen = 

[PATCH 09/11] pack-objects: do not cache delta for v4 trees

2013-09-08 Thread Nguyễn Thái Ngọc Duy

Signed-off-by: Nguyễn Thái Ngọc Duy pclo...@gmail.com
---
 builtin/pack-objects.c | 6 +-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c
index 69a22c1..665853d 100644
--- a/builtin/pack-objects.c
+++ b/builtin/pack-objects.c
@@ -1759,8 +1759,12 @@ static void find_deltas(struct object_entry **list, 
unsigned *list_size,
 * and therefore it is best to go to the write phase ASAP
 * instead, as we can afford spending more time compressing
 * between writes at that moment.
+*
+* For v4 trees we'll need to delta differently anyway
+* so no cache. v4 commits simply do not delta.
 */
-   if (entry-delta_data  !pack_to_stdout) {
+   if (entry-delta_data  !pack_to_stdout 
+   (pack_version  4 || entry-type == OBJ_BLOB)) {
entry-z_delta_size = do_compress(entry-delta_data,
  entry-delta_size);
cache_lock();
-- 
1.8.2.83.gc99314b

--
To unsubscribe from this list: send the line 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 10/11] pack-objects: exclude commits out of delta objects in v4

2013-09-08 Thread Nguyễn Thái Ngọc Duy

Signed-off-by: Nguyễn Thái Ngọc Duy pclo...@gmail.com
---
 builtin/pack-objects.c | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c
index 665853d..daa4349 100644
--- a/builtin/pack-objects.c
+++ b/builtin/pack-objects.c
@@ -1332,7 +1332,8 @@ static void check_object(struct object_entry *entry)
break;
}
 
-   if (base_ref  (base_entry = locate_object_entry(base_ref))) {
+   if (base_ref  (base_entry = locate_object_entry(base_ref)) 
+   (pack_version  4 || entry-type != OBJ_COMMIT)) {
/*
 * If base_ref was set above that means we wish to
 * reuse delta data, and we even found that base
@@ -1416,6 +1417,8 @@ static void get_object_details(void)
check_object(entry);
if (big_file_threshold  entry-size)
entry-no_try_delta = 1;
+   if (pack_version == 4  entry-type == OBJ_COMMIT)
+   entry-no_try_delta = 1;
}
 
free(sorted_by_offset);
-- 
1.8.2.83.gc99314b

--
To unsubscribe from this list: send the line 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 11/11] pack-objects: support writing pack v4

2013-09-08 Thread Nguyễn Thái Ngọc Duy

Signed-off-by: Nguyễn Thái Ngọc Duy pclo...@gmail.com
---
 builtin/pack-objects.c | 85 --
 pack.h |  2 +-
 2 files changed, 76 insertions(+), 11 deletions(-)

diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c
index daa4349..f6586a1 100644
--- a/builtin/pack-objects.c
+++ b/builtin/pack-objects.c
@@ -254,8 +254,10 @@ static unsigned long write_no_reuse_object(struct sha1file 
*f, struct object_ent
enum object_type type;
void *buf;
struct git_istream *st = NULL;
+   char *result = OK;
 
-   if (!usable_delta) {
+   if (!usable_delta ||
+   (pack_version == 4 || entry-type == OBJ_TREE)) {
if (entry-type == OBJ_BLOB 
entry-size  big_file_threshold 
(st = open_istream(entry-idx.sha1, type, size, NULL)) != 
NULL)
@@ -287,7 +289,37 @@ static unsigned long write_no_reuse_object(struct sha1file 
*f, struct object_ent
 
if (st) /* large blob case, just assume we don't compress well */
datalen = size;
-   else if (entry-z_delta_size)
+   else if (pack_version == 4  entry-type == OBJ_COMMIT) {
+   datalen = size;
+   result = pv4_encode_commit(v4, buf, datalen);
+   if (result) {
+   free(buf);
+   buf = result;
+   type = OBJ_PV4_COMMIT;
+   }
+   } else if (pack_version == 4  entry-type == OBJ_TREE) {
+   datalen = size;
+   if (usable_delta) {
+   unsigned long base_size;
+   char *base_buf;
+   base_buf = read_sha1_file(entry-delta-idx.sha1, type,
+ base_size);
+   if (!base_buf || type != OBJ_TREE)
+   die(unable to read %s,
+   sha1_to_hex(entry-delta-idx.sha1));
+   result = pv4_encode_tree(v4, buf, datalen,
+base_buf, base_size,
+entry-delta-idx.sha1);
+   free(base_buf);
+   } else
+   result = pv4_encode_tree(v4, buf, datalen,
+NULL, 0, NULL);
+   if (result) {
+   free(buf);
+   buf = result;
+   type = OBJ_PV4_TREE;
+   }
+   } else if (entry-z_delta_size)
datalen = entry-z_delta_size;
else
datalen = do_compress(buf, size);
@@ -296,7 +328,10 @@ static unsigned long write_no_reuse_object(struct sha1file 
*f, struct object_ent
 * The object header is a byte of 'type' followed by zero or
 * more bytes of length.
 */
-   hdrlen = encode_in_pack_object_header(type, size, header);
+   if (pack_version  4)
+   hdrlen = encode_in_pack_object_header(type, size, header);
+   else
+   hdrlen = pv4_encode_in_pack_object_header(type, size, header);
 
if (type == OBJ_OFS_DELTA) {
/*
@@ -318,7 +353,7 @@ static unsigned long write_no_reuse_object(struct sha1file 
*f, struct object_ent
sha1write(f, header, hdrlen);
sha1write(f, dheader + pos, sizeof(dheader) - pos);
hdrlen += sizeof(dheader) - pos;
-   } else if (type == OBJ_REF_DELTA) {
+   } else if (type == OBJ_REF_DELTA  pack_version  4) {
/*
 * Deltas with a base reference contain
 * an additional 20 bytes for the base sha1.
@@ -332,6 +367,10 @@ static unsigned long write_no_reuse_object(struct sha1file 
*f, struct object_ent
sha1write(f, header, hdrlen);
sha1write(f, entry-delta-idx.sha1, 20);
hdrlen += 20;
+   } else if (type == OBJ_REF_DELTA  pack_version == 4) {
+   hdrlen += encode_sha1ref(v4, entry-delta-idx.sha1,
+   header + hdrlen);
+   sha1write(f, header, hdrlen);
} else {
if (limit  hdrlen + datalen + 20 = limit) {
if (st)
@@ -341,14 +380,26 @@ static unsigned long write_no_reuse_object(struct 
sha1file *f, struct object_ent
}
sha1write(f, header, hdrlen);
}
+
if (st) {
datalen = write_large_blob_data(st, f, entry-idx.sha1);
close_istream(st);
-   } else {
-   sha1write(f, buf, datalen);
-   free(buf);
+   return hdrlen + datalen;
}
 
+   if (!result) {
+   warning(_(can't convert %s object %s),
+   typename(entry-type),
+   sha1_to_hex(entry-idx.sha1));
+   

[PATCH 08/11] pack-objects: create pack v4 tables

2013-09-08 Thread Nguyễn Thái Ngọc Duy

Signed-off-by: Nguyễn Thái Ngọc Duy pclo...@gmail.com
---
 builtin/pack-objects.c | 87 --
 1 file changed, 85 insertions(+), 2 deletions(-)

diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c
index b38d3dc..69a22c1 100644
--- a/builtin/pack-objects.c
+++ b/builtin/pack-objects.c
@@ -18,6 +18,7 @@
 #include refs.h
 #include streaming.h
 #include thread-utils.h
+#include packv4-create.h
 
 static const char *pack_usage[] = {
N_(git pack-objects --stdout [options...] [ ref-list |  
object-list]),
@@ -61,6 +62,8 @@ static struct object_entry *objects;
 static struct pack_idx_entry **written_list;
 static uint32_t nr_objects, nr_alloc, nr_result, nr_written;
 
+static struct packv4_tables v4;
+
 static int non_empty;
 static int reuse_delta = 1, reuse_object = 1;
 static int keep_unreachable, unpack_unreachable, include_tag;
@@ -2039,12 +2042,42 @@ static int add_ref_tag(const char *path, const unsigned 
char *sha1, int flag, vo
return 0;
 }
 
+static int sha1_idx_sort(const void *a_, const void *b_)
+{
+   const struct pack_idx_entry *a = a_;
+   const struct pack_idx_entry *b = b_;
+   return hashcmp(a-sha1, b-sha1);
+}
+
+static void prepare_sha1_table(void)
+{
+   unsigned i;
+   /*
+* This table includes SHA-1s that may not be present in the
+* pack. One of the use of such SHA-1 is for completing thin
+* packs, where index-pack does not need to add SHA-1 to the
+* table at completion time.
+*/
+   v4.all_objs = xmalloc(nr_objects * sizeof(*v4.all_objs));
+   v4.all_objs_nr = nr_objects;
+   for (i = 0; i  nr_objects; i++)
+   v4.all_objs[i] = objects[i].idx;
+   qsort(v4.all_objs, nr_objects, sizeof(*v4.all_objs),
+ sha1_idx_sort);
+}
+
 static void prepare_pack(int window, int depth)
 {
struct object_entry **delta_list;
uint32_t i, nr_deltas;
unsigned n;
 
+   if (pack_version == 4) {
+   sort_dict_entries_by_hits(v4.commit_ident_table);
+   sort_dict_entries_by_hits(v4.tree_path_table);
+   prepare_sha1_table();
+   }
+
get_object_details();
 
/*
@@ -2191,6 +2224,34 @@ static void read_object_list_from_stdin(void)
 
add_preferred_base_object(line+41);
add_object_entry(sha1, 0, line+41, 0);
+
+   if (pack_version == 4) {
+   void *data;
+   enum object_type type;
+   unsigned long size;
+   int (*add_dict_entries)(struct dict_table *, void *, 
unsigned long);
+   struct dict_table *dict;
+
+   switch (sha1_object_info(sha1, size)) {
+   case OBJ_COMMIT:
+   add_dict_entries = add_commit_dict_entries;
+   dict = v4.commit_ident_table;
+   break;
+   case OBJ_TREE:
+   add_dict_entries = add_tree_dict_entries;
+   dict = v4.tree_path_table;
+   break;
+   default:
+   continue;
+   }
+   data = read_sha1_file(sha1, type, size);
+   if (!data)
+   die(cannot unpack %s, sha1_to_hex(sha1));
+   if (add_dict_entries(dict, data, size)  0)
+   die(can't process %s object %s,
+   typename(type), sha1_to_hex(sha1));
+   free(data);
+   }
}
 }
 
@@ -2198,10 +2259,26 @@ static void read_object_list_from_stdin(void)
 
 static void show_commit(struct commit *commit, void *data)
 {
+   if (pack_version == 4) {
+   unsigned long size;
+   enum object_type type;
+   unsigned char *buf;
+
+   /* commit-buffer is NULL most of the time, don't bother */
+   buf = read_sha1_file(commit-object.sha1, type, size);
+   add_commit_dict_entries(v4.commit_ident_table, buf, size);
+   free(buf);
+   }
add_object_entry(commit-object.sha1, OBJ_COMMIT, NULL, 0);
commit-object.flags |= OBJECT_ADDED;
 }
 
+static void show_tree_entry(const struct name_entry *entry, void *data)
+{
+   dict_add_entry(v4.tree_path_table, entry-mode, entry-path,
+  tree_entry_len(entry));
+}
+
 static void show_object(struct object *obj,
const struct name_path *path, const char *last,
void *data)
@@ -2380,7 +2457,9 @@ static void get_object_list(int ac, const char **av)
if (prepare_revision_walk(revs))
die(revision walk setup failed);
mark_edges_uninteresting(revs.commits, revs, 

[PATCH] pull: use $curr_branch_short more

2013-09-08 Thread René Scharfe
One of the first things git-pull.sh does is setting $curr_branch to
the target of HEAD and $curr_branch_short to the same but with the
leading refs/heads/ removed.  Simplify the code by using
$curr_branch_short instead of setting $curr_branch to the same
shortened value.

The only other use of $curr_branch in that function doesn't have to
be replaced with $curr_branch_short because it just checks if the
string is empty.  That property is the same with or without the prefix
unless HEAD points to refs/heads/ alone, which is invalid.

Noticed-by: Felipe Contreras felipe.contre...@gmail.com
Signed-off-by: Rene Scharfe l@web.de
---
Replacement patch.  Corrected the command in the summary and
changed the first part of the description slightly.

 git-pull.sh | 5 ++---
 1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/git-pull.sh b/git-pull.sh
index f0df41c..d8b2708 100755
--- a/git-pull.sh
+++ b/git-pull.sh
@@ -166,9 +166,8 @@ error_on_no_merge_candidates () {
op_prep=with
fi
 
-   curr_branch=${curr_branch#refs/heads/}
-   upstream=$(git config branch.$curr_branch.merge)
-   remote=$(git config branch.$curr_branch.remote)
+   upstream=$(git config branch.$curr_branch_short.merge)
+   remote=$(git config branch.$curr_branch_short.remote)
 
if [ $# -gt 1 ]; then
if [ $rebase = true ]; then
-- 1.8.4 
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] branch: use $curr_branch_short more

2013-09-08 Thread René Scharfe

Am 31.08.2013 19:20, schrieb Felipe Contreras:

A summary should contain as much information that would allow me to
skip the commit message as possible.

If I can't tell from the summary if I can safely skip the commit
message, the summary is not doing a good job.

trivial simplification explains the what, and the why at the
same time, and allows most people to skip the commit message, thus is
a good summary.


No patch should be skipped on the mailing list.  As you wrote, trivial 
patches can still be wrong.


When going through the history I can see that quickly recognizing 
insubstantial changes is useful, but if I see a summary twice then in my 
mind forms a big question mark -- why did the same thing had to be done 
yet again?


As an example, both 0d12e59f (pull: replace unnecessary sed invocation) 
and bc2bbc45 (pull, rebase: simplify to use die()) could arguably have 
had the summary trivial simplification, but I'm glad the author went 
with something a bit more specific.


I agree that some kind of tagging with keywords like trivial, typo 
and so on can be helpful, though.



Again, triviality and correctness are two separate different things.
The patch is trivial even if you can't judge it's correctness.


Well, in terms of impact I agree.


To me, what you are describing is an obvious patch, not a trivial one.
An obvious patch is so obvious that you can judge it's correctness
easily by looking at the diff, a trivial one is of little importance.


That's one definition; I think I had the mathematical notion in mind 
that calls proofs trivial which are immediately evident.


René

--
To unsubscribe from this list: send the line 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] dir: remove dead code

2013-09-08 Thread René Scharfe

Am 08.09.2013 16:42, schrieb Ramkumar Ramachandra:

On Sun, Sep 8, 2013 at 6:00 PM, René Scharfe l@web.de
mailto:l@web.de wrote:

Am 08.09.2013 08:09, schrieb Ramkumar Ramachandra:

Remove dead code around remove_dir_recursively().


This basically reverts ae2f203e (clean: preserve nested git worktree
in subdirectories).  t7300 still seems to pass, though.  I wonder why.


t7300 has nothing to do with ae2f203e.


ae2f203e modified t/t7300-clean.sh.



   dir.c | 21 -
   1 file changed, 4 insertions(+), 17 deletions(-)

diff --git a/dir.c b/dir.c
index 910bfcd..2b31241 100644
--- a/dir.c
+++ b/dir.c
@@ -1464,11 +1464,11 @@ int is_empty_dir(const char *path)
 return ret;
   }

-static int remove_dir_recurse(struct strbuf *path, int flag,
int *kept_up)
+int remove_dir_recursively(struct strbuf *path, int flag)
   {
 DIR *dir;
 struct dirent *e;
-   int ret = 0, original_len = path-len, len, kept_down = 0;
+   int ret = 0, original_len = path-len, len;
 int only_empty = (flag  REMOVE_DIR_EMPTY_ONLY);
 int keep_toplevel = (flag  REMOVE_DIR_KEEP_TOPLEVEL);
 unsigned char submodule_head[20];
@@ -1476,8 +1476,6 @@ static int remove_dir_recurse(struct
strbuf *path, int flag, int *kept_up)
 if ((flag  REMOVE_DIR_KEEP_NESTED_GIT) 
 !resolve_gitlink_ref(path-__buf, HEAD,
submodule_head)) {
 /* Do not descend and nuke a nested git work
tree. */
-   if (kept_up)
-   *kept_up = 1;
 return 0;
 }

@@ -1504,7 +1502,7 @@ static int remove_dir_recurse(struct
strbuf *path, int flag, int *kept_up)
 if (lstat(path-buf, st))
 ; /* fall thru */
 else if (S_ISDIR(st.st_mode)) {
-   if (!remove_dir_recurse(path, flag,
kept_down))
+   if (!remove_dir_recursively(path, flag))


kept_down could have been set to 1 here...


Not possible.


Why?

I guess the answer is that kept_down could have only been set if the 
flag REMOVE_DIR_KEEP_NESTED_GIT is given, which only git clean uses, 
which in turn has its own implementation of remove_dir_recursively() 
named remove_dirs() since f538a91e (git-clean: Display more accurate 
delete messages).


That probably means you can remove even more code from 
remove_dir_recursively().




 continue; /* happy */
 } else if (!only_empty  !unlink(path-buf))
 continue; /* happy, too */
@@ -1516,22 +1514,11 @@ static int remove_dir_recurse(struct
strbuf *path, int flag, int *kept_up)
 closedir(dir);

 strbuf_setlen(path, original_len);
-   if (!ret  !keep_toplevel  !kept_down)
+   if (!ret  !keep_toplevel)
 ret = rmdir(path-buf);


... and would have prevented the rmdir() call here.

Is the removed code really dead?  And if not, why does t7300 still pass?


Yes, it clearly is. Shared secret.


What is the secret and who shares it?

Thanks,
René

--
To unsubscribe from this list: send the line 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] l10n: de.po: use das Tag instead of der Tag

2013-09-08 Thread Ralf Thielow
Use das Tag to avoid confusion with the German word Tag (day).

Reported-by: Dirk Heinrichs dirk.heinri...@altum.de
Signed-off-by: Ralf Thielow ralf.thie...@gmail.com
---
 po/de.po | 22 +++---
 1 file changed, 11 insertions(+), 11 deletions(-)

diff --git a/po/de.po b/po/de.po
index 11dde11..f4076fb 100644
--- a/po/de.po
+++ b/po/de.po
@@ -4694,12 +4694,12 @@ msgstr git describe [Optionen] --dirty
 #: builtin/describe.c:237
 #, c-format
 msgid annotated tag %s not available
-msgstr annotierter Tag %s ist nicht verfügbar
+msgstr annotiertes Tag %s ist nicht verfügbar
 
 #: builtin/describe.c:241
 #, c-format
 msgid annotated tag %s has no embedded name
-msgstr annotierter Tag %s hat keinen eingebetteten Namen
+msgstr annotiertes Tag %s hat keinen eingebetteten Namen
 
 #: builtin/describe.c:243
 #, c-format
@@ -4765,7 +4765,7 @@ msgstr 
 
 #: builtin/describe.c:409
 msgid find the tag that comes after the commit
-msgstr findet den Tag, die nach Commit kommt
+msgstr findet das Tag, das nach Commit kommt
 
 #: builtin/describe.c:410
 msgid debug search strategy on stderr
@@ -4777,7 +4777,7 @@ msgstr verwendet alle Referenzen
 
 #: builtin/describe.c:412
 msgid use any tag, even unannotated
-msgstr verwendet jeden Tag, auch nicht-annotierte
+msgstr verwendet jedes Tag, auch nicht-annotierte
 
 #: builtin/describe.c:413
 msgid always use long format
@@ -4880,7 +4880,7 @@ msgstr Importiert Kennzeichen von dieser Datei
 
 #: builtin/fast-export.c:678
 msgid Fake a tagger when tags lack one
-msgstr erzeugt künstlich einen Tag-Ersteller, wenn der Tag keinen hat
+msgstr erzeugt künstlich einen Tag-Ersteller, wenn das Tag keinen hat
 
 #: builtin/fast-export.c:680
 msgid Output full tree for each commit
@@ -5013,7 +5013,7 @@ msgstr   (kann lokale Referenz nicht aktualisieren)
 
 #: builtin/fetch.c:324
 msgid [new tag]
-msgstr [neuer Tag]
+msgstr [neues Tag]
 
 #: builtin/fetch.c:327
 msgid [new branch]
@@ -7831,7 +7831,7 @@ msgstr 
 #: builtin/push.c:257
 msgid Updates were rejected because the tag already exists in the remote.
 msgstr 
-Aktualisierungen wurden zurückgewiesen, weil der Tag bereits\n
+Aktualisierungen wurden zurückgewiesen, weil das Tag bereits\n
 im Remote-Repository existiert.
 
 #: builtin/push.c:260
@@ -9244,7 +9244,7 @@ msgstr Optionen für Erstellung von Tags
 
 #: builtin/tag.c:454
 msgid annotated tag, needs a message
-msgstr annotierter Tag, benötigt eine Beschreibung
+msgstr annotiertes Tag, benötigt eine Beschreibung
 
 #: builtin/tag.c:456
 msgid tag message
@@ -9252,15 +9252,15 @@ msgstr Tag-Beschreibung
 
 #: builtin/tag.c:458
 msgid annotated and GPG-signed tag
-msgstr annotierter und GPG-signierter Tag
+msgstr annotiertes und GPG-signiertes Tag
 
 #: builtin/tag.c:462
 msgid use another key to sign the tag
-msgstr verwendet einen anderen Schlüssel um den Tag zu signieren
+msgstr verwendet einen anderen Schlüssel um das Tag zu signieren
 
 #: builtin/tag.c:463
 msgid replace the tag if exists
-msgstr ersetzt den Tag, wenn er existiert
+msgstr ersetzt das Tag, wenn es existiert
 
 #: builtin/tag.c:464
 msgid show tag list in columns
-- 
1.8.4.325.g5deb81b

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


Re: [PATCH 0/3] Reject non-ff pulls by default

2013-09-08 Thread brian m. carlson
On Sat, Sep 07, 2013 at 11:37:13PM -0500, Felipe Contreras wrote:
 On Sat, Sep 7, 2013 at 11:18 PM, Jeff King p...@peff.net wrote:
  By svn-like, I mean the people whose workflow is:
 
$ hack hack hack
$ git commit
$ git push ;# oops, somebody else pushed in the meantime
$ git pull
$ git push

It's possible that some teams at work may be using this workflow.  It's
more likely that there would be a rebase if the push failed, but some
teams might do a merge.  I don't know because we don't dictate workflow
to individual teams for the reasons I get into below.  Regardless,
merges are our typical workflow, so forcing rebase mode all the time
wouldn't be appropriate for us.

$ hack hack hack
$ svn commit ;# oops, somebody else committed in the meantime
$ svn update
$ svn commit
 
  Those people would now have to learn enough to choose between merge and
  rebase when running the git pull.
 
 But that's only if they don't care about the shape of history. In my
 experience the people that cling more to centralized VCS do not like
 merges, so they rebase everything to make it a straight line. That is
 much more svn-like.
 
 So chances are they are already doing 'git pull --rebase' (or
 similar), so their workflow wouldn't be affected.

We end up squashing each project branch into one commit (usually using
git reset --soft), so we don't care about the shape of history.  Over
the course of a project branch, in fact, there may be many merges from
the main release branches (including other projects), so history is
going to be very messy otherwise.

-- 
brian m. carlson / brian with sandals: Houston, Texas, US
+1 832 623 2791 | http://www.crustytoothpaste.net/~bmc | My opinion only
OpenPGP: RSA v4 4096b: 88AC E9B2 9196 305B A994 7552 F1BA 225C 0223 B187


signature.asc
Description: Digital signature


Re: [PATCH 0/3] Unconfuse git clone when two branches at are HEAD.

2013-09-08 Thread Junio C Hamano
Philip Oakley philipoak...@iee.org writes:

 What I observed was that all the clones had the same HEAD problem,
 which I think comes from clone.c: guess_remote_head().

Yes.  They share having to guess property because their data
source does not tell them.

 My quick look at clone.c suggested to me that there would be a lot of
 commonality between the bundle data stream and the transport streams
 (identical?), and it was just a case of adding into the bundle data
 the same HEAD symref indication that would solve the normal clone
 problem (including backward compatibility). Is that a reasonable
 assesssment?

You need to find a hole in the existing readers to stick the new
information in a way that do not break existing readers but allow
updated readers to extract that information.  That is exactly what
we did when we added the protocol capability.  I do not offhand
think an equivalent hole exists in the bundle file format.
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 0/3] Reject non-ff pulls by default

2013-09-08 Thread Junio C Hamano
Richard Hansen rhan...@bbn.com writes:

 On 2013-09-07 22:41, Felipe Contreras wrote:
 On Wed, Sep 4, 2013 at 5:59 PM, Junio C Hamano gits...@pobox.com wrote:
 
 Which can be solved by adding the above fail option, and then
 renaming them to pull.integrate and branch.name.integrate to
 clarify what these variables are about (it is no longer do you
 rebase or not---if you choose not to rebase, by definition you are
 going to merge, as there is a third choice to fail), while
 retaining pull.rebase and branch.name.rebase as a deprecated
 synonym.
 
 All these names are completely unintuitive. First of all, why
 integrate? Integrate what to what? And then, why fail? Fail on
 what circumstances? Always?
 
 My proposal that does:
 
   pull.mode = merge/rebase/merge-ff-only
 
 Is way more intuitive.

 +1

 What about something like:

 pull.mergeoptions (defaults to --ff-only)
 pull.rebaseoptions (defaults to empty?  --preserve-merges?)
 branch.name.pull.mergeoptions (defaults to pull.mergeoptions)
 branch.name.pull.rebaseoptions (defaults to pull.rebaseoptions)

As pull has two distinct phases fetch and merge/rebase, your
mergeoptions/rebaseoptions is much better than mode, which does
not tell which phase of pull the mode refers to. It is clear that
they apply to the process to integrate the history obtained from
the other side and your own history into one history.

But it does not help Philip's case, if I understand correctly, where
running git pull on some branches is always a mistake and the user
wants it to stop at fetch the history and objects needed to
complete the history from the other side phase without proceeding
to the then integrate the history from the other side and the
history of your branch into one step, which may be done with either
merge or rebase.  Even if we ignore that always fail, do not do
anything use case, your two seemingly independent mergeoptions
and rebaseoptions do not tell us which one is preferred between
merge and rebase.  A single

pull.someoption = rebase | merge [| always-fail]

makes that choice in a clear way, I think.

Regarding the verb integrate.

We used to explain pull is a fetch followed by a merge.  With
more people using git pull --rebase, the word merge used in that
explanation of pull stopped being generic enough.  Simplarily the
upstream branch of local branch X is what you fetch and merge to
update the branch X but that 'merge' can be 'rebase'.  We needed a
verb to call the process of integrate the two histories into one.

git pull --help since 153d7265 (pull: change the description to
integrate changes, 2013-07-07) uses that verb [*1*].

And that is where the name of the single configuration to pick how
to integrate the history obtained by the first phase of pull came
from.


[Footnote]

*1* I suspect that there may still be places in the documentation
that have not been updated since the days back when the only valid
way to integrate two lines of histories was to merge, and updating
them may be a low-hanging fruit. Hint, hint.
 
--
To unsubscribe from this list: send the line 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-backend: provide Allow header for 405

2013-09-08 Thread brian m. carlson
The HTTP 1.1 standard requires an Allow header for 405 Method Not Allowed:

  The response MUST include an Allow header containing a list of valid methods
  for the requested resource.

So provide such a header when we return a 405 to the user agent.

Signed-off-by: brian m. carlson sand...@crustytoothpaste.net
---
 http-backend.c | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/http-backend.c b/http-backend.c
index 0324417..8c61084 100644
--- a/http-backend.c
+++ b/http-backend.c
@@ -594,8 +594,11 @@ int main(int argc, char **argv)
 
if (strcmp(method, c-method)) {
const char *proto = getenv(SERVER_PROTOCOL);
-   if (proto  !strcmp(proto, HTTP/1.1))
+   if (proto  !strcmp(proto, HTTP/1.1)) {
http_status(405, Method Not Allowed);
+   hdr_str(Allow, !strcmp(GET, 
c-method) ?
+   GET, HEAD : c-method);
+   }
else
http_status(400, Bad Request);
hdr_nocache();
-- 
1.8.4.rc3

--
To unsubscribe from this list: send the line 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/4] Re: [PATCH 3/4] t: rev-parse-parents: avoid yoda conditions

2013-09-08 Thread Junio C Hamano
Jeff King p...@peff.net writes:

 A(ny) sanely defined compare A with B function should yield the
 result of subtracting B from A, i.e. cmp(A,B) should be like (A-B).
 That is what you feed qsort() and bsearch() (it is not limited to C;
 you see the same in sort { $a = $b }).  The definition naturally
 makes cmp(A,B)  0 like A  B and cmp(A,B)  0 like A  B.
 ---

 Ah, you mean if you think that the compare function should behave like
 C *_cmp functions, it should be A-B. Perhaps it is simply that I do not
 think of the function in those terms, but more like show me the
 differences from B to A.




  Otherwise why would so many
  existing test frameworks do it the other way?
 
 Which many existing frameworks do it the other way?

 John mentioned JUnit, NUnit, and PHPUnit earlier in the thread. I
 believe that Ruby's Test::Unit::Assertions also has
 assert_equal(expected, actual).

Especially the last one can be excused.  is A and B equal is a
binary between yes and no.  If A and B are equal, B and A are
equal, and it becomes more like which endianness is correct? as
you mentioned earlier.

I think the real cause of confusion is that cmp(1) is not a
comparison in that sense but is an equality check; test_cmp has a
dual purpose in that its primary use as did the previous step
produce correct result? is an equality check and the order does not
really matter, but its secondary purpose, to show how the actual
output deviated from the norm, has to be done by subtracting the
expected result from the actual result.

As I said, I am somewhat sympathetic to those who want to see such
subtraction spelled as cmp(Actual,Expect), but we are so used to the
order diff(1) takes expect and actual to do that subtraction in
that order, so using diff(Expect,Actual) order is not that wrong.

Calling the abstraction test_diff might have avoided the wasted
brain bandwidth in this thread, but I do not think renaming it in
test-lib-functions.sh is worth the trouble, either ;-)

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


Re: [PATCH 0/3] Reject non-ff pulls by default

2013-09-08 Thread Richard Hansen
On 2013-09-08 14:10, Junio C Hamano wrote:
 Richard Hansen rhan...@bbn.com writes:
 What about something like:

 pull.mergeoptions (defaults to --ff-only)
 pull.rebaseoptions (defaults to empty?  --preserve-merges?)
 branch.name.pull.mergeoptions (defaults to pull.mergeoptions)
 branch.name.pull.rebaseoptions (defaults to pull.rebaseoptions)
 
[snip]
 But it does not help Philip's case, if I understand correctly, where
 running git pull on some branches is always a mistake and the user
 wants it to stop at fetch the history and objects needed to
 complete the history from the other side phase without proceeding
 to the then integrate the history from the other side and the
 history of your branch into one step, which may be done with either
 merge or rebase.

How about:

branch.name.pull.defaultIntegrationMode = merge | rebase | none
If 'merge', pull acts like 'git pull --merge' by default,
merging the other commits into this branch.
If 'rebase', pull acts like 'git pull --rebase' by default,
rebasing this branch onto the other commits.
If 'none', pull acts like 'git fetch' by default.
Default: whatever pull.defaultIntegrationMode is set to.

branch.name.pull.mergeoptions
Arguments to pass to 'git merge' during the merge phase of
'git pull --merge'.
Default: whatever pull.mergeoptions is set to.

branch.name.pull.rebaseoptions
Arguments to pass to 'git rebase' during the rebase phase of
'git pull --rebase'.
Default: whatever pull.rebaseoptions is set to.

pull.defaultIntegrationMode = rebase | merge | none
See branch.name.pull.defaultIntegrationMode.
Default: merge

pull.mergeoptions
See branch.name.pull.mergeoptions.
Default: empty, but warn that a future version will change
this to --ff-only.

pull.rebaseoptions
See branch.name.pull.rebaseoptions.
Default: empty, but warn that a future version will change
this to --preserve-merges?

There's probably a better alternative to the term 'defaultIntegrationMode'.

We could even add a defaultIntegrationMode = merge-there that
reverses the parent order (the other commits become the first parent,
the current branch becomes the second parent).

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


[BUG] rebase not recovering gracefully from repack error

2013-09-08 Thread Yann Dirson
(patches|REBASE 8/9)$ git rebase --continue
Applying: Check for __unix__ instead of __linux
Applying: Completely disable crash handler on archs other than i386 and amd64
Auto packing the repository for optimum performance. You may also
run git gc manually. See git help gc for more information.
error: Could not read a7d470051f53f4e4c9247df752583868a79ec70b
fatal: Failed to traverse parents of commit 
e6d2f264969207e337953717c260d37daa0a8554
error: failed to run repack
(patches|REBASE 10/9)$ cat .git/rebase-apply/next 
10
(patches|REBASE 10/9)$ 


The last patch has been dealt with and I consider the rebase done.
Rebase would be bombing out without cleaning behind it when the auto
repack fails ?


On another aspect, I find the repack error is suspect: git fsck
--no-dangling has nothing to complain about, and the missing commit
is the real ancestor of a grafted commit.  I suppose it has been gc'd
by a buggy git version, as I recall seeing such a fix on the list some
time ago.  (yes, I shouldn't be using grafts any more, but that
particular one dates back to 2006 ;)

-- 
Yann

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


Re: [PATCH 05/11] pack-write.c: add pv4_encode_in_pack_object_header

2013-09-08 Thread Nicolas Pitre
On Sun, 8 Sep 2013, Nguyễn Thái Ngọc Duy wrote:

 
 Signed-off-by: Nguyễn Thái Ngọc Duy pclo...@gmail.com
 ---
  pack-write.c | 29 +
  pack.h   |  1 +
  2 files changed, 30 insertions(+)
 
 diff --git a/pack-write.c b/pack-write.c
 index 88e4788..6f11104 100644
 --- a/pack-write.c
 +++ b/pack-write.c
 @@ -1,6 +1,7 @@
  #include cache.h
  #include pack.h
  #include csum-file.h
 +#include varint.h
  
  void reset_pack_idx_option(struct pack_idx_option *opts)
  {
 @@ -340,6 +341,34 @@ int encode_in_pack_object_header(enum object_type type, 
 uintmax_t size, unsigned
   return n;
  }
  
 +/*
 + * The per-object header is a pretty dense thing, which is
 + *  - first byte: low four bits are size, then three bits of type,
 + *and the high bit is size continues.
 + *  - each byte afterwards: low seven bits are size continuation,
 + *with the high bit being size continues
 + */

This comment is a bit misleading.  It looks almost like the pack v2 
object header encoding which is not a varint encoded value like this one 
is.

 +int pv4_encode_in_pack_object_header(enum object_type type,
 +  uintmax_t size, unsigned char *hdr)

Could we have a somewhat shorter function name? 
pv4_encode_object_header() should be acceptable given pv4 already 
implies a pack.

 +{
 + uintmax_t val;
 + if (type  OBJ_COMMIT || type  OBJ_PV4_TREE || type == OBJ_OFS_DELTA)
 + die(bad type %d, type);

This test has holes, such as types 5 and 8.

I think this would be better as:

switch (type) {
case OBJ_COMMIT:
case OBJ_TREE:
case OBJ_BLOB:
case OBJ_TAG:
case OBJ_REF_DELTA:
case OBJ_PV4_COMMIT:
case OBJ_PV4_TREE:
break;
default:
die(bad type %d, type);
}

The compiler ought to be smart enough to optimize the contiguous case 
range.  And that makes it explicit and obvious what we test for.

 +
 + /*
 +  * We allocate 4 bits in the LSB for the object type which
 +  * should be good for quite a while, given that we effectively
 +  * encodes only 5 object types: commit, tree, blob, delta,
 +  * tag.
 +  */
 + val = size;
 + if (MSB(val, 4))
 + die(fixme: the code doesn't currently cope with big sizes);
 + val = 4;
 + val |= type;
 + return encode_varint(val, hdr);
 +}
 +
  struct sha1file *create_tmp_packfile(char **pack_tmp_name)
  {
   char tmpname[PATH_MAX];
 diff --git a/pack.h b/pack.h
 index 855f6c6..38f869d 100644
 --- a/pack.h
 +++ b/pack.h
 @@ -83,6 +83,7 @@ extern off_t write_pack_header(struct sha1file *f, int, 
 uint32_t);
  extern void fixup_pack_header_footer(int, unsigned char *, const char *, 
 uint32_t, unsigned char *, off_t);
  extern char *index_pack_lockfile(int fd);
  extern int encode_in_pack_object_header(enum object_type, uintmax_t, 
 unsigned char *);
 +extern int pv4_encode_in_pack_object_header(enum object_type, uintmax_t, 
 unsigned char *);
  
  #define PH_ERROR_EOF (-1)
  #define PH_ERROR_PACK_SIGNATURE  (-2)
 -- 
 1.8.2.83.gc99314b
 
 --
 To unsubscribe from this list: send the line 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] send-email: don't call methods on undefined values

2013-09-08 Thread brian m. carlson
If SSL verification is enabled in git send-email, we could attempt to call a
method on an undefined value if the verification failed, since $smtp would end
up being undef.  Look up the error string in a way that will produce a helpful
error message and not cause further errors.

Signed-off-by: brian m. carlson sand...@crustytoothpaste.net
---
 git-send-email.perl | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/git-send-email.perl b/git-send-email.perl
index 2162478..3782c3b 100755
--- a/git-send-email.perl
+++ b/git-send-email.perl
@@ -1234,7 +1234,7 @@ X-Mailer: git-send-email $gitversion
if ($smtp-code == 220) {
$smtp = Net::SMTP::SSL-start_SSL($smtp,
  
ssl_verify_params())
-   or die STARTTLS failed! 
.$smtp-message;
+   or die STARTTLS failed! 
.IO::Socket::SSL::errstr();
$smtp_encryption = '';
# Send EHLO again to receive fresh
# supported commands
-- 
1.8.4.rc3

--
To unsubscribe from this list: send the line 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 03/11] pack v4: move packv4-create.c to libgit.a

2013-09-08 Thread Nicolas Pitre
On Sun, 8 Sep 2013, Nguyễn Thái Ngọc Duy wrote:

 git-packv4-create now becomes test-packv4. Code that will not be used
 by pack-objects.c is moved to test-packv4.c. It may be removed when
 the code transition to pack-objects completes.
 
 Signed-off-by: Nguyễn Thái Ngọc Duy pclo...@gmail.com
 ---
  Makefile|   4 +-
  packv4-create.c | 491 
 +---
  packv4-create.h |  39 +
  test-packv4.c (new) | 476 ++
  4 files changed, 525 insertions(+), 485 deletions(-)
  create mode 100644 test-packv4.c
 
 diff --git a/Makefile b/Makefile
 index 22fc276..af2e3e3 100644
 --- a/Makefile
 +++ b/Makefile
 @@ -550,7 +550,6 @@ PROGRAM_OBJS += shell.o
  PROGRAM_OBJS += show-index.o
  PROGRAM_OBJS += upload-pack.o
  PROGRAM_OBJS += remote-testsvn.o
 -PROGRAM_OBJS += packv4-create.o
  
  # Binary suffix, set to .exe for Windows builds
  X =
 @@ -568,6 +567,7 @@ TEST_PROGRAMS_NEED_X += test-line-buffer
  TEST_PROGRAMS_NEED_X += test-match-trees
  TEST_PROGRAMS_NEED_X += test-mergesort
  TEST_PROGRAMS_NEED_X += test-mktemp
 +TEST_PROGRAMS_NEED_X += test-packv4
  TEST_PROGRAMS_NEED_X += test-parse-options
  TEST_PROGRAMS_NEED_X += test-path-utils
  TEST_PROGRAMS_NEED_X += test-prio-queue
 @@ -702,6 +702,7 @@ LIB_H += notes.h
  LIB_H += object.h
  LIB_H += pack-revindex.h
  LIB_H += pack.h
 +LIB_H += packv4-create.h
  LIB_H += packv4-parse.h
  LIB_H += parse-options.h
  LIB_H += patch-ids.h
 @@ -839,6 +840,7 @@ LIB_OBJS += object.o
  LIB_OBJS += pack-check.o
  LIB_OBJS += pack-revindex.o
  LIB_OBJS += pack-write.o
 +LIB_OBJS += packv4-create.o
  LIB_OBJS += packv4-parse.o
  LIB_OBJS += pager.o
  LIB_OBJS += parse-options.o
 diff --git a/packv4-create.c b/packv4-create.c
 index 920a0b4..cdf82c0 100644
 --- a/packv4-create.c
 +++ b/packv4-create.c
 @@ -18,9 +18,9 @@
  #include packv4-create.h
  
  
 -static int pack_compression_seen;
 -static int pack_compression_level = Z_DEFAULT_COMPRESSION;
 -static int min_tree_copy = 1;
 +int pack_compression_seen;
 +int pack_compression_level = Z_DEFAULT_COMPRESSION;
 +int min_tree_copy = 1;
  
  struct data_entry {
   unsigned offset;
 @@ -28,17 +28,6 @@ struct data_entry {
   unsigned hits;
  };
  
 -struct dict_table {
 - unsigned char *data;
 - unsigned cur_offset;
 - unsigned size;
 - struct data_entry *entry;
 - unsigned nb_entries;
 - unsigned max_entries;
 - unsigned *hash;
 - unsigned hash_size;
 -};

It doesn't seem necessary to move this structure definition to the 
header file.  Only an opaque

struct dict_table;

should be needed in packv4-create.h.  That would keep the dictionary 
handling localized.


Nicolas


[PATCHv2 0/5] branch: Fix --track on a remote-tracking non-branch

2013-09-08 Thread Johan Herland
Hi,

Here is the second iteration of this series. Only one change from the
first iteration: The first patch now also fixes some missing -chaining
noticed by Junio in t2024.

...Johan


Johan Herland (4):
  t2024: Fix -chaining and a couple of typos
  t3200: Minor fix when preparing for tracking failure
  Refer to branch.name.remote/merge when documenting --track
  t3200: Add test demonstrating minor regression in 41c21f2

Per Cederqvist (1):
  branch.c: Relax unnecessary requirement on upstream's remote ref name

 Documentation/git-branch.txt |  6 --
 branch.c |  3 +--
 t/t2024-checkout-dwim.sh |  6 +++---
 t/t3200-branch.sh| 37 -
 4 files changed, 44 insertions(+), 8 deletions(-)

-- 
1.8.3.GIT

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


[PATCHv2 1/5] t2024: Fix -chaining and a couple of typos

2013-09-08 Thread Johan Herland
Improved-by: Junio C Hamano gits...@pobox.com
Signed-off-by: Johan Herland jo...@herland.net
---
 t/t2024-checkout-dwim.sh | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/t/t2024-checkout-dwim.sh b/t/t2024-checkout-dwim.sh
index dee55e4..094b92e 100755
--- a/t/t2024-checkout-dwim.sh
+++ b/t/t2024-checkout-dwim.sh
@@ -104,7 +104,7 @@ test_expect_success 'setup more remotes with unconventional 
refspecs' '
cd repo_c 
test_commit c_master 
git checkout -b bar 
-   test_commit c_bar
+   test_commit c_bar 
git checkout -b spam 
test_commit c_spam
) 
@@ -113,9 +113,9 @@ test_expect_success 'setup more remotes with unconventional 
refspecs' '
cd repo_d 
test_commit d_master 
git checkout -b baz 
-   test_commit f_baz
+   test_commit d_baz 
git checkout -b eggs 
-   test_commit c_eggs
+   test_commit d_eggs
) 
git remote add repo_c repo_c 
git config remote.repo_c.fetch \
-- 
1.8.3.GIT

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


[PATCHv2 4/5] t3200: Add test demonstrating minor regression in 41c21f2

2013-09-08 Thread Johan Herland
In 41c21f2 (branch.c: Validate tracking branches with refspecs instead of
refs/remotes/*), we changed the rules for what is considered a valid tracking
branch (a.k.a. upstream branch). We now use the configured remotes and their
refspecs to determine whether a proposed tracking branch is in fact within
the domain of a remote, and we then use that information to deduce the
upstream configuration (branch.name.remote and branch.name.merge).

However, with that change, we also check that - in addition to a matching
refspec - the result of mapping the tracking branch through that refspec
(i.e. the corresponding ref name in the remote repo) happens to start with
refs/heads/. In other words, we require that a tracking branch refers to
a _branch_ in the remote repo.

Now, consider that you are e.g. setting up an automated building/testing
infrastructure for a group of similar source repositories. The build/test
infrastructure consists of a central scheduler, and a number of build/test
slave machines that perform the actual build/test work. The scheduler
monitors the group of similar repos for changes (e.g. with a periodic
git fetch), and triggers builds/tests to be run on one or more slaves.
Graphically the changes flow between the repos like this:

  Source #1 ---v   Slave #1
 /
  Source #2 - Scheduler - Slave #2
 \
  Source #3 ---^   Slave #3

...   ...

The scheduler maintains a single Git repo with each of the source repos set
up as distinct remotes. The slaves also need access to all the changes from
all of the source repos, so they pull from the scheduler repo, but using the
following custom refspec:

  remote.origin.fetch = +refs/remotes/*:refs/remotes/*

This makes all of the scheduler's remote-tracking branches automatically
available as identical remote-tracking branches in each of the slaves.

Now, consider what happens if a slave tries to create a local branch with
one of the remote-tracking branches as upstream:

  git branch local_branch --track refs/remotes/source-1/some_branch

Git now looks at the configured remotes (in this case there is only origin,
pointing to the scheduler's repo) and sees refs/remotes/source-1/some_branch
matching origin's refspec. Mapping through that refspec we find that the
corresponding remote ref name is refs/remotes/source-1/some_branch.
However, since this remote ref name does not start with refs/heads/, we
discard it as a suitable upstream, and the whole command fails.

This patch adds a testcase demonstrating this failure by creating two
source repos (a and b) that are forwarded through a scheduler (c)
to a slave repo (d), that then tries create a local branch with an
upstream. See the next patch in this series for the exciting conclusion
to this story...

Reported-by: Per Cederqvist ced...@opera.com
Signed-off-by: Johan Herland jo...@herland.net
---
 t/t3200-branch.sh | 34 ++
 1 file changed, 34 insertions(+)

diff --git a/t/t3200-branch.sh b/t/t3200-branch.sh
index 8f6ab8e..4031693 100755
--- a/t/t3200-branch.sh
+++ b/t/t3200-branch.sh
@@ -871,4 +871,38 @@ test_expect_success '--merged catches invalid object 
names' '
test_must_fail git branch --merged 

 '
 
+test_expect_failure 'tracking with unexpected .fetch refspec' '
+   git init a 
+   (
+   cd a 
+   test_commit a
+   ) 
+   git init b 
+   (
+   cd b 
+   test_commit b
+   ) 
+   git init c 
+   (
+   cd c 
+   test_commit c 
+   git remote add a ../a 
+   git remote add b ../b 
+   git fetch --all
+   ) 
+   git init d 
+   (
+   cd d 
+   git remote add c ../c 
+   git config remote.c.fetch +refs/remotes/*:refs/remotes/* 
+   git fetch c 
+   git branch --track local/a/master remotes/a/master 
+   test $(git config branch.local/a/master.remote) = c 
+   test $(git config branch.local/a/master.merge) = 
refs/remotes/a/master 
+   git rev-parse --verify a expect 
+   git rev-parse --verify local/a/master actual 
+   test_cmp expect actual
+   )
+'
+
 test_done
-- 
1.8.3.GIT

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


[PATCHv2 5/5] branch.c: Relax unnecessary requirement on upstream's remote ref name

2013-09-08 Thread Johan Herland
From: Per Cederqvist ced...@opera.com

When creating an upstream relationship, we use the configured remotes and
their refspecs to determine the upstream configuration settings
branch.name.remote and branch.name.merge. However, if the matching
refspec does not have refs/heads/something on the remote side, we end
up rejecting the match, and failing the upstream configuration.

It could be argued that when we set up an branch's upstream, we want that
upstream to also be a proper branch in the remote repo. Although this is
typically the common case, there are cases (as demonstrated by the previous
patch in this series) where this requirement prevents a useful upstream
relationship from being formed. Furthermore:

 - We have fundamentally no say in how the remote repo have organized its
   branches. The remote repo may put branches (or branch-like constructs
   that are insteresting for downstreams to track) outside refs/heads/*.

 - The user may intentionally want to track a non-branch from a remote
   repo, by using a branch and configured upstream in the local repo.

Relaxing the checking to only require a matching remote/refspec allows the
testcase introduced in the previous patch to succeed, and has no negative
effect on the rest of the test suite.

This patch fixes a behavior (arguably a regression) first introduced in
41c21f2 (branch.c: Validate tracking branches with refspecs instead of
refs/remotes/*) on 2013-04-21 (released in = v1.8.3.2).

Signed-off-by: Johan Herland jo...@herland.net
---
 branch.c  | 3 +--
 t/t3200-branch.sh | 2 +-
 2 files changed, 2 insertions(+), 3 deletions(-)

diff --git a/branch.c b/branch.c
index c5c6984..2d15c19 100644
--- a/branch.c
+++ b/branch.c
@@ -203,8 +203,7 @@ static int check_tracking_branch(struct remote *remote, 
void *cb_data)
struct refspec query;
memset(query, 0, sizeof(struct refspec));
query.dst = tracking_branch;
-   return !(remote_find_tracking(remote, query) ||
-prefixcmp(query.src, refs/heads/));
+   return !remote_find_tracking(remote, query);
 }
 
 static int validate_remote_tracking_branch(char *ref)
diff --git a/t/t3200-branch.sh b/t/t3200-branch.sh
index 4031693..f010303 100755
--- a/t/t3200-branch.sh
+++ b/t/t3200-branch.sh
@@ -871,7 +871,7 @@ test_expect_success '--merged catches invalid object names' 
'
test_must_fail git branch --merged 

 '
 
-test_expect_failure 'tracking with unexpected .fetch refspec' '
+test_expect_success 'tracking with unexpected .fetch refspec' '
git init a 
(
cd a 
-- 
1.8.3.GIT

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


[PATCHv2 2/5] t3200: Minor fix when preparing for tracking failure

2013-09-08 Thread Johan Herland
We're testing that trying to --track a ref that is not covered by any remote
refspec should fail. For that, we want to have refs/remotes/local/master
present, but we also want the remote.local.fetch refspec to NOT match
refs/remotes/local/master (so that the tracking setup will fail, as intended).
However, when doing git fetch local to ensure the existence of
refs/remotes/local/master, we must not already have changed remote.local.fetch
so as to cause refs/remotes/local/master not to be fetched. Therefore, set
remote.local.fetch to refs/heads/*:refs/remotes/local/* BEFORE we fetch, and
then reset it to refs/heads/s:refs/remotes/local/s AFTER we have fetched
(but before we test --track).

Signed-off-by: Johan Herland jo...@herland.net
---
 t/t3200-branch.sh | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/t/t3200-branch.sh b/t/t3200-branch.sh
index 44ec6a4..8f6ab8e 100755
--- a/t/t3200-branch.sh
+++ b/t/t3200-branch.sh
@@ -319,8 +319,9 @@ test_expect_success 'test tracking setup (non-wildcard, 
matching)' '
 
 test_expect_success 'tracking setup fails on non-matching refspec' '
git config remote.local.url . 
-   git config remote.local.fetch refs/heads/s:refs/remotes/local/s 
+   git config remote.local.fetch refs/heads/*:refs/remotes/local/* 
(git show-ref -q refs/remotes/local/master || git fetch local) 
+   git config remote.local.fetch refs/heads/s:refs/remotes/local/s 
test_must_fail git branch --track my5 local/master 
test_must_fail git config branch.my5.remote 
test_must_fail git config branch.my5.merge
-- 
1.8.3.GIT

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


[PATCHv2 3/5] Refer to branch.name.remote/merge when documenting --track

2013-09-08 Thread Johan Herland
Make it easier for readers to find the actual config variables that
implement the upstream relationship.

Suggested-by: Per Cederqvist ced...@opera.com
Signed-off-by: Johan Herland jo...@herland.net
---
 Documentation/git-branch.txt | 6 --
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/Documentation/git-branch.txt b/Documentation/git-branch.txt
index b7cb625..311b336 100644
--- a/Documentation/git-branch.txt
+++ b/Documentation/git-branch.txt
@@ -48,7 +48,8 @@ working tree to it; use git checkout newbranch to switch 
to the
 new branch.
 
 When a local branch is started off a remote-tracking branch, Git sets up the
-branch so that 'git pull' will appropriately merge from
+branch (specifically the `branch.name.remote` and `branch.name.merge`
+configuration entries) so that 'git pull' will appropriately merge from
 the remote-tracking branch. This behavior may be changed via the global
 `branch.autosetupmerge` configuration flag. That setting can be
 overridden by using the `--track` and `--no-track` options, and
@@ -156,7 +157,8 @@ This option is only applicable in non-verbose mode.
 
 -t::
 --track::
-   When creating a new branch, set up configuration to mark the
+   When creating a new branch, set up `branch.name.remote` and
+   `branch.name.merge` configuration entries to mark the
start-point branch as upstream from the new branch. This
configuration will tell git to show the relationship between the
two branches in `git status` and `git branch -v`. Furthermore,
-- 
1.8.3.GIT

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


Re: [PATCH 0/3] Unconfuse git clone when two branches at are HEAD.

2013-09-08 Thread Philip Oakley

From: Junio C Hamano gits...@pobox.com
Sent: Sunday, September 08, 2013 6:35 PM

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


What I observed was that all the clones had the same HEAD problem,
which I think comes from clone.c: guess_remote_head().


Yes.  They share having to guess property because their data
source does not tell them.


My quick look at clone.c suggested to me that there would be a lot of
commonality between the bundle data stream and the transport streams
(identical?), and it was just a case of adding into the bundle data
the same HEAD symref indication that would solve the normal clone
problem (including backward compatibility). Is that a reasonable
assesssment?


You need to find a hole in the existing readers to stick the new
information in a way that do not break existing readers but allow
updated readers to extract that information.  That is exactly what
we did when we added the protocol capability.  I do not offhand
think an equivalent hole exists in the bundle file format.
--


I've been rummaging about as to options.

One is to extend the ref format such that
 sha1 refs/heads/Test:HEAD
would be considered a valid indicator of a symref relationship (i.e. 
using the typical 'colon' style). It would be appended after the regular 
refs, so all the existing refs are still transported.


The point is that while it produces an error, it doesn't stop the 
cloning, and the error message

error: * Ignoring funny ref 'refs/remotes/origin/Test:HEAD' locally
gives a pretty clear statement of intent to those with older versions of 
git.


Another alternative is to add an additional name space (e.g.)
  sha1 refs/remotes/origin/HEAD/Test
which would simply be an extra directory layer that reflects where the 
HEAD should have been. Though this namespace example has the D/F 
conflict.


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 0/3] Reject non-ff pulls by default

2013-09-08 Thread Felipe Contreras
On Sun, Sep 8, 2013 at 12:26 PM, brian m. carlson
sand...@crustytoothpaste.net wrote:
 On Sat, Sep 07, 2013 at 11:37:13PM -0500, Felipe Contreras wrote:
 On Sat, Sep 7, 2013 at 11:18 PM, Jeff King p...@peff.net wrote:

$ hack hack hack
$ svn commit ;# oops, somebody else committed in the meantime
$ svn update
$ svn commit
 
  Those people would now have to learn enough to choose between merge and
  rebase when running the git pull.

 But that's only if they don't care about the shape of history. In my
 experience the people that cling more to centralized VCS do not like
 merges, so they rebase everything to make it a straight line. That is
 much more svn-like.

 So chances are they are already doing 'git pull --rebase' (or
 similar), so their workflow wouldn't be affected.

 We end up squashing each project branch into one commit (usually using
 git reset --soft), so we don't care about the shape of history.  Over
 the course of a project branch, in fact, there may be many merges from
 the main release branches (including other projects), so history is
 going to be very messy otherwise.

Yeah, but the key question at hand in this discussion is; what happens
when 'git pull' stops working for them, and they don't know what to
do, will they choose 'git pull --rebase' by mistake?

I say the answer is no, because:

1) As you say in your scenario, somebody is telling these guys what to
do, so when 'git pull' fails, somebody will figure out that they were
doing a merge, so 'git pull --merge' is what they want to type from
now on.

2) Git itself would be warning them for months that a 'non
fast-forward was found, and a merge will be done for them', so when
the warning turns to an error, they'll know they want a merge, so
they'll do 'git pull --merge', either because the warning told them
that's git was doing all along, or because they figured that out by
googling, or reading the man page, or whatever.

Either way, it would not be a big deal for these people, their
user-experience wouldn't be totally broken by this proposed change,
and that is the important conclusion.

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


Re: [PATCH 0/3] Reject non-ff pulls by default

2013-09-08 Thread Philip Oakley

From: Junio C Hamano gits...@pobox.com
Sent: Sunday, September 08, 2013 7:10 PM

Richard Hansen rhan...@bbn.com writes:


On 2013-09-07 22:41, Felipe Contreras wrote:
On Wed, Sep 4, 2013 at 5:59 PM, Junio C Hamano gits...@pobox.com 
wrote:



Which can be solved by adding the above fail option, and then
renaming them to pull.integrate and branch.name.integrate to
clarify what these variables are about (it is no longer do you
rebase or not---if you choose not to rebase, by definition you are
going to merge, as there is a third choice to fail), while
retaining pull.rebase and branch.name.rebase as a deprecated
synonym.


All these names are completely unintuitive. First of all, why
integrate? Integrate what to what? And then, why fail? Fail on
what circumstances? Always?

My proposal that does:

  pull.mode = merge/rebase/merge-ff-only

Is way more intuitive.


+1

What about something like:

pull.mergeoptions (defaults to --ff-only)
pull.rebaseoptions (defaults to empty?  --preserve-merges?)
branch.name.pull.mergeoptions (defaults to pull.mergeoptions)
branch.name.pull.rebaseoptions (defaults to pull.rebaseoptions)


As pull has two distinct phases fetch and merge/rebase, your
mergeoptions/rebaseoptions is much better than mode, which does
not tell which phase of pull the mode refers to. It is clear that
they apply to the process to integrate the history obtained from
the other side and your own history into one history.

But it does not help Philip's case, if I understand correctly, where
running git pull on some branches is always a mistake


Not quite always, it's when it won't fast forward


and the user
wants it to stop at fetch the history and objects needed to
complete the history from the other side phase without proceeding
to the then integrate the history from the other side and the
history of your branch into one step,


Yes, it/Git should stop and wait for instructions...


  which may be done with either
merge or rebase.


Here I would typically rebase onto an adjusted destination, e.g. onto 
pu, or maybe next, rather than master (or vice versa depending on 
expectations). That is its a feature branch that needs to decide what 
it's on top of (well, I need to decide ;-)



   Even if we ignore that always fail, do not do
anything use case, your two seemingly independent mergeoptions
and rebaseoptions do not tell us which one is preferred between
merge and rebase.  A single

   pull.someoption = rebase | merge [| always-fail]

makes that choice in a clear way, I think.


or 'fail on non-ff' (which may or may not be the users, or Git's 
default, as per the series title ;-)




Regarding the verb integrate.

We used to explain pull is a fetch followed by a merge.  With
more people using git pull --rebase, the word merge used in that
explanation of pull stopped being generic enough.  Simplarily the
upstream branch of local branch X is what you fetch and merge to
update the branch X but that 'merge' can be 'rebase'.  We needed a
verb to call the process of integrate the two histories into one.

git pull --help since 153d7265 (pull: change the description to
integrate changes, 2013-07-07) uses that verb [*1*].

And that is where the name of the single configuration to pick how
to integrate the history obtained by the first phase of pull came
from.


[Footnote]

*1* I suspect that there may still be places in the documentation
that have not been updated since the days back when the only valid
way to integrate two lines of histories was to merge, and updating
them may be a low-hanging fruit. Hint, hint.



--
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 0/3] Reject non-ff pulls by default

2013-09-08 Thread Felipe Contreras
On Sun, Sep 8, 2013 at 1:10 PM, Junio C Hamano gits...@pobox.com wrote:

 pull.someoption = rebase | merge [| always-fail]

 makes that choice in a clear way, I think.

 Regarding the verb integrate.

I doubt anybody thinks of pull being an integration, and even if it
is, it's still doesn't explain what 'integration = merge' means. To be
human friendly you would need to say 'integration-type' or
'integration-kind', or 'integration-mode', then a human would
understand, oh yeah, the mode I'm using to integrated is a merge, got
ya'.

But why bother with yet another useless concept the user has to learn?
The user doesn't need to learn about this concept of integration,
all the user wants is to map:

git pull --rebase
= pull.name = rebase

git pull --merge
pull.name = merge

That's it. And my proposed name, 'mode' does the trick just fine.

pull.mode = rebase | merge | merge-no-ff

-- 
Felipe Contreras
--
To unsubscribe from this list: send the line 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] sequencer: trivial cleanup

2013-09-08 Thread Ramkumar Ramachandra
Signed-off-by: Ramkumar Ramachandra artag...@gmail.com
---
 sequencer.c | 5 +
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/sequencer.c b/sequencer.c
index 351548f..8ed9f98 100644
--- a/sequencer.c
+++ b/sequencer.c
@@ -466,10 +466,7 @@ static int allow_empty(struct replay_opts *opts, struct 
commit *commit)
empty_commit = is_original_commit_empty(commit);
if (empty_commit  0)
return empty_commit;
-   if (!empty_commit)
-   return 0;
-   else
-   return 1;
+   return empty_commit ? 0 : 1;
 }
 
 static int do_pick_commit(struct commit *commit, struct replay_opts *opts)
-- 
1.8.4.100.gde18f6d.dirty

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


Re: Git tag output order is incorrect (IMHO)

2013-09-08 Thread Felipe Contreras
On Thu, Jul 18, 2013 at 10:27 AM, Rahul Bansal rahul.ban...@rtcamp.com wrote:
 I am posting here first time, so please excuse me if this is not right place 
 to send something like this.

 Please check - 
 http://stackoverflow.com/questions/6091306/can-i-make-git-print-x-y-z-style-tag-names-in-a-sensible-order

 And also - https://github.com/gitlabhq/gitlabhq/issues/4565

 IMHO git tag is expected to show tag-list ordered by versions.

 It may be case, that people do not follow same version numbering convention. 
 Most people after x.9.x increment major version (that is why they may not be 
 affected because of this)

 Another option like git tag --date-asc can be added which will print tags 
 by creation date. (As long as people do not create backdated tag, this will 
 work).

I completely agree, and there was a proposal to an option like this a
long time ago:

http://article.gmane.org/gmane.comp.version-control.git/111032

-- 
Felipe Contreras
--
To unsubscribe from this list: send the line 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] sequencer: trivial cleanup

2013-09-08 Thread Felipe Contreras
On Sun, Sep 8, 2013 at 5:42 PM, Ramkumar Ramachandra artag...@gmail.com wrote:
 Signed-off-by: Ramkumar Ramachandra artag...@gmail.com
 ---
  sequencer.c | 5 +
  1 file changed, 1 insertion(+), 4 deletions(-)

 diff --git a/sequencer.c b/sequencer.c
 index 351548f..8ed9f98 100644
 --- a/sequencer.c
 +++ b/sequencer.c
 @@ -466,10 +466,7 @@ static int allow_empty(struct replay_opts *opts, struct 
 commit *commit)
 empty_commit = is_original_commit_empty(commit);
 if (empty_commit  0)
 return empty_commit;
 -   if (!empty_commit)
 -   return 0;
 -   else
 -   return 1;
 +   return empty_commit ? 0 : 1;
  }

Isn't it the other way around? Moreover, 'return !!empty_commit;'
would be simpler.

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


Re: [PATCH 1/3] reset: add --stage and --work options

2013-09-08 Thread Felipe Contreras
On Sun, Sep 8, 2013 at 5:05 PM, Ramkumar Ramachandra artag...@gmail.com wrote:
 Felipe Contreras wrote:

 @@ -290,6 +294,22 @@ int cmd_reset(int argc, const char **argv, const char
 *prefix)
 hashcpy(sha1, tree-object.sha1);
 }

 +   if (stage = 0 || working_tree = 0) {
 +   if (reset_type != NONE)
 +   die(_(--{stage,work} are incompatible with
 --{hard,mixed,soft,merge}));
 +
 +   if (working_tree == 1) {
 +   if (stage == 0)
 +   die(_(--no-stage doesn't make sense with
 --work));
 +   reset_type = HARD;
 +   } else {
 +   if (stage == 1)
 +   reset_type = NONE;
 +   else
 +   reset_type = SOFT;
 +   }
 +   }
 +


 Not making sense at this point. Why does --stage set a reset_type?

Yeah, we would need another patch to cleanup the variable names, but
for now it's better to minimize the changes.

Either way it doesn't matter because Junio is determined to stand
alone versus the rest of the world in this issue.

-- 
Felipe Contreras
--
To unsubscribe from this list: send the line 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] sequencer: trivial cleanup

2013-09-08 Thread Ramkumar Ramachandra
Felipe Contreras wrote:
  sequencer.c | 5 +
  1 file changed, 1 insertion(+), 4 deletions(-)

 diff --git a/sequencer.c b/sequencer.c
 index 351548f..8ed9f98 100644
 --- a/sequencer.c
 +++ b/sequencer.c
 @@ -466,10 +466,7 @@ static int allow_empty(struct replay_opts *opts, struct 
 commit *commit)
 empty_commit = is_original_commit_empty(commit);
 if (empty_commit  0)
 return empty_commit;
 -   if (!empty_commit)
 -   return 0;
 -   else
 -   return 1;
 +   return empty_commit ? 0 : 1;
  }

 Isn't it the other way around? Moreover, 'return !!empty_commit;'
 would be simpler.

Yeah, thanks for pointing out this grave stupidity. This seems to be
inconsequential as far as the tests are concerned: have to do some
major yak shaving.
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 0/3] Reject non-ff pulls by default

2013-09-08 Thread Ramkumar Ramachandra
Felipe Contreras wrote:
 On Sun, Sep 8, 2013 at 1:10 PM, Junio C Hamano gits...@pobox.com wrote:

 pull.someoption = rebase | merge [| always-fail]

 makes that choice in a clear way, I think.

The core issue is that users rarely want to merge locally: that's the
maintainer's job. Users simply want to rebase, and develop on
different branches that they will rebase onto origin. I like Felipe's
idea for using a pull.mode.
--
To unsubscribe from this list: send the line 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] branch: use $curr_branch_short more

2013-09-08 Thread Felipe Contreras
On Sun, Sep 8, 2013 at 10:21 AM, René Scharfe l@web.de wrote:
 Am 31.08.2013 19:20, schrieb Felipe Contreras:

 A summary should contain as much information that would allow me to
 skip the commit message as possible.

 If I can't tell from the summary if I can safely skip the commit
 message, the summary is not doing a good job.

 trivial simplification explains the what, and the why at the
 same time, and allows most people to skip the commit message, thus is
 a good summary.


 No patch should be skipped on the mailing list.  As you wrote, trivial
 patches can still be wrong.

What patches each persons skips is each person's own decision, don't
be patronizing, if I want to skip a trivial patch, I will, I can't
read each and every patch from the dozens of mailing lists I'm
subscribed to, and there's no way each and every reader is going to
read each and every patch. They should be prioritized, and trivial
ones can be safely skipped by most people.

Here's a good example from a simple summary that I didn't write:

t2024: Fix inconsequential typos
http://article.gmane.org/gmane.comp.version-control.git/234038

Do I have to read this patch? No. I know it's inconsequential, I can
safely skip it, the key word being *I*. *Somebody* should read it,
sure, and I'm sure at least Junio would, but I don't need to.

 When going through the history I can see that quickly recognizing
 insubstantial changes is useful, but if I see a summary twice then in my
 mind forms a big question mark -- why did the same thing had to be done yet
 again?

 As an example, both 0d12e59f (pull: replace unnecessary sed invocation) and
 bc2bbc45 (pull, rebase: simplify to use die()) could arguably have had the
 summary trivial simplification, but I'm glad the author went with
 something a bit more specific.

Well I wont. Because it takes long to read, and after reading I still
don't don't if they are trivial or not, I might actually have to read
the commit message, but to be honest, I would probably go right into
the diff itself, because judging from Git's history, chances are that
somebody wrote a novel there with the important bit I'm looking for
just at the end, to don't ruin the suspense.

In the first commit, it's saying it's a single invocation, so I take
it it's trivial, but what is it replaced with? Is the code simpler, is
it more complex? I don't know, I'm still not being told *why* that
patch is made. It says 'unnecessary' but why is it unnecessary?

In the second commit, it's saying it's a simplification, but I don't
know if it's just one instance, or a thousand, so I don't know what
would be the impact of the patch.

Either way I'm forced to read more just to know if it was safe for me
to skip them, at which point the whole purpose of a summary is
defeated.

 Again, triviality and correctness are two separate different things.
 The patch is trivial even if you can't judge it's correctness.

 Well, in terms of impact I agree.

No, in all terms. A patch can be:

Trivial and correct
Trivial and incorrect
Non-trivial and correct
Non-trivial and incorrect

 To me, what you are describing is an obvious patch, not a trivial one.
 An obvious patch is so obvious that you can judge it's correctness
 easily by looking at the diff, a trivial one is of little importance.

 That's one definition; I think I had the mathematical notion in mind that
 calls proofs trivial which are immediately evident.

We are not talking about mathematics, we are talking about the English
human language.

-- 
Felipe Contreras
--
To unsubscribe from this list: send the line 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/4] Re: [PATCH 3/4] t: rev-parse-parents: avoid yoda conditions

2013-09-08 Thread Felipe Contreras
On Sun, Sep 8, 2013 at 1:33 PM, Junio C Hamano gits...@pobox.com wrote:
 Jeff King p...@peff.net writes:

 Calling the abstraction test_diff might have avoided the wasted
 brain bandwidth in this thread, but I do not think renaming it in
 test-lib-functions.sh is worth the trouble, either ;-)

Yes, but then it wouldn't be clear what's the main purpose of
test_diff(). Primarily what we want is to check that they are the
same. The diff is secondary, and it's not actually *needed*.

-- 
Felipe Contreras
--
To unsubscribe from this list: send the line 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/4] Re: [PATCH 3/4] t: rev-parse-parents: avoid yoda conditions

2013-09-08 Thread Felipe Contreras
On Sun, Sep 8, 2013 at 12:02 AM, Jeff King p...@peff.net wrote:
 On Sat, Sep 07, 2013 at 11:52:10PM -0500, Felipe Contreras wrote:

  Ah, you mean if you think that the compare function should behave like
  C *_cmp functions, it should be A-B. Perhaps it is simply that I do not
  think of the function in those terms, but more like show me the
  differences from B to A.

 But that is the problem, you are unable to ignore the implementation.
 You don't see test_cmp(), you see 'diff -u'.

 Yes, I already said earlier in the thread:

   I certainly think of test_cmp A B as differences from A to B, and
   the order makes sense. IOW, the test_cmp is diff abstraction is
   leaky, and that is fine (if it were not leaky, then order would not
   matter at all, but it clearly does).

Then I don't think you can give a fair and objective opinion about
what should be the ideal ordering of the arguments. You would be
forever biased to whatever is the order of 'diff -u'.

 And I do not think it is a problem. The point of the function is not to
 abstract away the idea of comparison. The point is to give a hook for
 people on systems without diff -u to run the test suite.

The point according to whom? I say it's the other way around.

  John mentioned JUnit, NUnit, and PHPUnit earlier in the thread. I
  believe that Ruby's Test::Unit::Assertions also has
  assert_equal(expected, actual).

 That's because they all do first expect, then actual.

 assert_equal( expected, actual, failure_message = nil )
 assert_not_equal( expected, actual, failure_message = nil )

 That's why.

 I do not see any reason why not_equal would not also work as
 assert_not_equal(actual, expected). Maybe I am missing your point.

All right, maybe it's because Ruby started in Japan, and their
sentences have very different orderings, maybe it's legacy from
another test framework, maybe there's no reason at all and somebody
just randomly picked them.

Either way the fact that others are doing it differently doesn't mean
that's the best way, that would be argumentum ad populum, and mothers
are keen to remind us that if other kids are jumping the bridge, that
doesn't mean we should too.

-- 
Felipe Contreras
--
To unsubscribe from this list: send the line 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/4] Re: [PATCH 3/4] t: rev-parse-parents: avoid yoda conditions

2013-09-08 Thread Jeff King
On Sun, Sep 08, 2013 at 06:25:45PM -0500, Felipe Contreras wrote:

  And I do not think it is a problem. The point of the function is not to
  abstract away the idea of comparison. The point is to give a hook for
  people on systems without diff -u to run the test suite.
 
 The point according to whom? I say it's the other way around.

The point according to 82ebb0b (add test_cmp function for test scripts,
2008-03-12). I wish I had simply called it test_diff back then, and then
this conversation could have never occurred.

 Either way the fact that others are doing it differently doesn't mean
 that's the best way, that would be argumentum ad populum, and mothers
 are keen to remind us that if other kids are jumping the bridge, that
 doesn't mean we should too.

Did I once say my way of thinking about it is the best way? No. I said
I think it is a matter of preference. I mentioned other systems using
a particular ordering to show that the set of people who prefer it the
other way is non-zero.

Feel free to respond, but I have no interest in discussing this any
further with you. This thread has become a giant time sink, and I have
nothing else to say on the matter that I have not already said.

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


Re: [PATCH 0/3] Reject non-ff pulls by default

2013-09-08 Thread brian m. carlson
On Sun, Sep 08, 2013 at 05:38:50PM -0500, Felipe Contreras wrote:
 Yeah, but the key question at hand in this discussion is; what happens
 when 'git pull' stops working for them, and they don't know what to
 do, will they choose 'git pull --rebase' by mistake?

I agree, they will not choose git pull --rebase by mistake.

 I say the answer is no, because:
 
 1) As you say in your scenario, somebody is telling these guys what to
 do, so when 'git pull' fails, somebody will figure out that they were
 doing a merge, so 'git pull --merge' is what they want to type from
 now on.

Yes, that would be me.  My hesitance here is that as the one usually
driving git updates (which so far have happened once a year), I will end
up retraining forty developers.  I don't think the current behavior is
broken or really problematic at all: merging has always been the
default, and people have come to expect that.  People using workflows
that don't want merge have always either needed to set a configuration
option or use --rebase.  As the man page says, --rebase is unsafe, and
that's why it's not the default.

I would be much less unhappy with your earlier change that did not
affect uses with arguments.  That would limit the number of use cases
affected.

 2) Git itself would be warning them for months that a 'non
 fast-forward was found, and a merge will be done for them', so when
 the warning turns to an error, they'll know they want a merge, so
 they'll do 'git pull --merge', either because the warning told them
 that's git was doing all along, or because they figured that out by
 googling, or reading the man page, or whatever.

Again, you assume that git updates happen on a regular basis, and you
assume that most developers really know what happens under the hood.

I don't see a warning now; in fact, I see:

  vauxhall ok % git status
  # On branch master
  # Your branch and 'upstream/master' have diverged,
  # and have 1 and 128 different commits each, respectively.
  #   (use git pull to merge the remote branch into yours)
  #

The current behavior of git is to explicitly encourage this behavior,
and now you want to make it not work.  I think this change is a bad
idea, and I think the number of changes required to the test suite
indicates that.  If there's going to be a change here, it should have a
deprecation period with the above message changed and appropriate
warnings, not a flag day; your patches don't do that.

-- 
brian m. carlson / brian with sandals: Houston, Texas, US
+1 832 623 2791 | http://www.crustytoothpaste.net/~bmc | My opinion only
OpenPGP: RSA v4 4096b: 88AC E9B2 9196 305B A994 7552 F1BA 225C 0223 B187


signature.asc
Description: Digital signature


Re: [PATCH 1/3] reset: add --stage and --work options

2013-09-08 Thread Ramkumar Ramachandra
Felipe Contreras wrote:
 Either way it doesn't matter because Junio is determined to stand
 alone versus the rest of the world in this issue.

Which is why he's the maintainer. Send in incremental updates, and he
should be fine.
--
To unsubscribe from this list: send the line 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] sequencer: trivial cleanup

2013-09-08 Thread SZEDER Gábor
Hi,

On Sun, Sep 08, 2013 at 05:53:19PM -0500, Felipe Contreras wrote:
 On Sun, Sep 8, 2013 at 5:42 PM, Ramkumar Ramachandra artag...@gmail.com 
 wrote:
  Signed-off-by: Ramkumar Ramachandra artag...@gmail.com
  ---
   sequencer.c | 5 +
   1 file changed, 1 insertion(+), 4 deletions(-)
 
  diff --git a/sequencer.c b/sequencer.c
  index 351548f..8ed9f98 100644
  --- a/sequencer.c
  +++ b/sequencer.c
  @@ -466,10 +466,7 @@ static int allow_empty(struct replay_opts *opts, 
  struct commit *commit)
  empty_commit = is_original_commit_empty(commit);
  if (empty_commit  0)
  return empty_commit;
  -   if (!empty_commit)
  -   return 0;
  -   else
  -   return 1;
  +   return empty_commit ? 0 : 1;
   }
 
 Isn't it the other way around? Moreover, 'return !!empty_commit;'
 would be simpler.

Considering the possible return values from
is_original_commit_empty(), I think all this could be written as

  return is_original_commit_empty(commit);


Best,
Gábor

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


Re: [PATCH 0/3] Reject non-ff pulls by default

2013-09-08 Thread Felipe Contreras
On Sun, Sep 8, 2013 at 7:01 PM, brian m. carlson
sand...@crustytoothpaste.net wrote:
 On Sun, Sep 08, 2013 at 05:38:50PM -0500, Felipe Contreras wrote:
 Yeah, but the key question at hand in this discussion is; what happens
 when 'git pull' stops working for them, and they don't know what to
 do, will they choose 'git pull --rebase' by mistake?

 I agree, they will not choose git pull --rebase by mistake.

 I say the answer is no, because:

 1) As you say in your scenario, somebody is telling these guys what to
 do, so when 'git pull' fails, somebody will figure out that they were
 doing a merge, so 'git pull --merge' is what they want to type from
 now on.

 Yes, that would be me.  My hesitance here is that as the one usually
 driving git updates (which so far have happened once a year), I will end
 up retraining forty developers.  I don't think the current behavior is
 broken or really problematic at all: merging has always been the
 default, and people have come to expect that.

It may not be broken for you, but it is for other people. Would you be
so egocentric as to ignore everybody else because it works for you?

 People using workflows
 that don't want merge have always either needed to set a configuration
 option or use --rebase.  As the man page says, --rebase is unsafe, and
 that's why it's not the default.

Yes, but the problem is that people using other workflows end up
avoiding 'git pull' at all, so at the end of the day we have one core
command that the majority of users avoid, that's not good.

 I would be much less unhappy with your earlier change that did not
 affect uses with arguments.  That would limit the number of use cases
 affected.

I have no problem with:
git pull $remote $branch

Allowing non-fast-forward merges.

And:
git pull $remote
git pull

Not allowing them by default.

But the problem is that it's not easy to implement.

Either way, I'll venture that you don't want 'git pull $remote' to
change, so it would be a waste of the time to try to get the above to
work.

 2) Git itself would be warning them for months that a 'non
 fast-forward was found, and a merge will be done for them', so when
 the warning turns to an error, they'll know they want a merge, so
 they'll do 'git pull --merge', either because the warning told them
 that's git was doing all along, or because they figured that out by
 googling, or reading the man page, or whatever.

 Again, you assume that git updates happen on a regular basis, and you
 assume that most developers really know what happens under the hood.

No. The developers don't have to know what happens under the hood, Git
would be telling them WARNING: we are doing a merge, what else is
the developer to think, but that 'git pull' is doing a merge?

As for the updates, yes, I assume updates happen at least each three
months. If your company updates each year, I don't see what much more
we can do to you help you. Doing a single change per year is certainly
going to hold the project back.

Fortunately this was only point 2), there's still point 1); you can
tell them to use 'git pull --merge' from now on, and since you update
once every year, you can do it while you give the training for the
year.

Or there's another option:

3) Distribute Git in your company with /etc/gitconfig having pull.mode
= merge. This way nothing will change.

I think we are being very accommodating to your company's use-case
which is very far from the norm. Even in the absolute worst case
scenario, you would have to tell people to use 'git pull --merge'
instead, is that really so horrible? Should we really halt Git's
progress because you would have to tell people to type nine extra
characters or run one configuration command?

 I don't see a warning now; in fact, I see:

   vauxhall ok % git status
   # On branch master
   # Your branch and 'upstream/master' have diverged,
   # and have 1 and 128 different commits each, respectively.
   #   (use git pull to merge the remote branch into yours)
   #

 The current behavior of git is to explicitly encourage this behavior,
 and now you want to make it not work.

Yes, that's why it's a change.

 I think this change is a bad
 idea, and I think the number of changes required to the test suite
 indicates that.  If there's going to be a change here, it should have a
 deprecation period with the above message changed and appropriate
 warnings, not a flag day; your patches don't do that.

My patches pretty much do nothing else but introduce a warning.
Nothing is broken, nothing is changed in the test suite:

http://article.gmane.org/gmane.comp.version-control.git/233669

You are confusing my proposal with Junio's one.

Also, my proposal was to enable this behavior (pull.mode =
merge-ff-only) only for Git v2.0, which might happen probably way
later than a year from now, so you your users might actually see the
warning after all. But yeah, that's _my_ proposal.

-- 
Felipe Contreras
--
To unsubscribe from this list: send the line 

Re: [PATCH 3/5] config: set errno in numeric git_parse_* functions

2013-09-08 Thread Eric Sunshine
On Sun, Sep 8, 2013 at 4:36 AM, Jeff King p...@peff.net wrote:
 When we are parsing an integer or unsigned long, we use
 the strto*max functions, which properly set errno to ERANGE
 if we get a large value. However, we also do further range
 checks after applying our multiplication factor, but do not
 set ERANGE. This means that a caller cannot tell if an error
 was caused by ERANGE or if the input was simply not a valid
 number.

 This patch teaches git_parse_signed and git_parse_unsigned
 reliably set ERANGE for range errors, and EINVAL for other

Missing to: s/reliably/to reliably/

Or, if you don't like splitting the infinitive:

s/reliably set ERANGE/to set ERANGE reliably/

 errors.

 Signed-off-by: Jeff King p...@peff.net
--
To unsubscribe from this list: send the line unsubscribe git in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH 0/3] Reject non-ff pulls by default

2013-09-08 Thread Felipe Contreras
On Sun, Sep 8, 2013 at 7:29 PM, Felipe Contreras
felipe.contre...@gmail.com wrote:

 My patches pretty much do nothing else but introduce a warning.
 Nothing is broken, nothing is changed in the test suite:

 http://article.gmane.org/gmane.comp.version-control.git/233669

 You are confusing my proposal with Junio's one.

Actually my mistake. My patches don't even add a warning, so nothing
is changed at all (unless you manually configure pull.mode =
merge-ff-only).

I only suggested to add the warning, but didn't actually implement it.
I'll do that soon.

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


  1   2   >