Re: [GSoC 2014] Replacing object loading/writing layer by libgit2

2014-04-07 Thread Guanglin Xu
Hi all,

I withdraw this proposal because I realize that I won't be eligible to
work in July and August as an F-1 student.

Good luck to other applicants!

Guanglin

2014-03-20 23:37 GMT+08:00 Guanglin Xu :
> Hello,
>
> My name is Guanglin Xu. I am a second-year master student at Sun
> Yat-sen University in China, majoring in Software Engineering. I am
> also a perspective PhD student matriculated in the US. I'm planning on
> doing summer projects which I can work remotely. The GSoC 2014 program
> of Git project is a great choice.
>
> I am kind of a "skillful" Git user with 4 years' experience in 3
> projects. For example, I am a Top 5 contributor in LibVMI project
> (https://github.com/bdpayne/libvmi); I host a team-made mobile app in
> Github (https://itunes.apple.com/us/app/ying-yue/id689566688?ls=1&mt=8).
> For more of my projects see here
> (http://www.andrew.cmu.edu/user/guanglin)
>
> To get familiar with the flow of Git development, I worked on
> microproject [2] and had corresponding conversations with Eric
> Sunshine, Jacopo Notarstefano and Sun He in threads. Thank you for
> their comments on my work.
>
> Now I've submitted my proposal to google-melange. In brief, I propose
> to replace object loading/writing layer by libgit2, which comes from
> the GSoC 2014 ideas page of Git project. Particularly, since I didn't
> realize where the hardest part is when I looked into the initial aim
> of this idea, I added a performance requirement that the new
> implementation should at least not run slower than previous one. Maybe
> I underestimated specific challenge in working with Git, suggestions
> or warnings for this topic are all welcomed.
>
> Thanks for your consideration for GSoC 2014.
>
> Guanglin
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: What's cooking in git.git (Apr 2014, #01; Fri, 4)

2014-04-07 Thread Duy Nguyen
On Tue, Apr 8, 2014 at 1:35 AM, Johannes Sixt  wrote:
> Am 05.04.2014 11:19, schrieb Johannes Sixt:
>> Am 04.04.2014 22:58, schrieb Junio C Hamano:
>>> * sz/mingw-index-pack-threaded (2014-03-19) 1 commit
>>>  - Enable index-pack threading in msysgit.
>>>
>>>  What is the status of this topic?  A failure report exists
>>>  ($gmane/245170), and I am aware of Duy's $gmane/245034 but that was
>>>  where the discussion stalled.  Is everybody waiting for everybody
>>>  else to get the discussion unstuck?
>>
>> I still have to cross-check Duy's patch. I'll hopefully get to it in the
>> next days and report back.
>
> The test suite passes with Duy's patch ($gmane/245034), but t5302 fails
> with this patch with a MinGW build.

Is "this patch" the one on 'pu', or mine?

> The patches touch the Cygwin configuration, but I cannot test a Cygwin build.

If no one can test the Cygwin changes, I'm happy to revert it back for safety.

> I have, however, lost track of what the objective of these patches is.
> Is the threaded version significantly faster, and these patches are
> worth it?

It depends on the repo, how much deltas it has, how deep. According to
b8a2486 (index-pack: support multithreaded delta resolving -
2012-05-06), going to two cores saves ~20% time. But some actual
numbers on Windows would be nice.
-- 
Duy
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH v3 2/2] commit: add --ignore-submodules[=] parameter

2014-04-07 Thread Ronald Weiss
Git commit honors the 'ignore' setting from .gitmodules or .git/config,
but didn't allow to override it from command line, like other commands do.

Useful  values for commit are 'all' (default) or 'none'. The others
('dirty' and 'untracked') have same effect as 'none', as commit is only
interested in whether the submodule's HEAD differs from what is commited
in the superproject.

This patch depends on Jens Lehmann's patch "commit -m: commit staged
submodules regardless of ignore config". Without it,
"commit -m --ignore-submodules" would not work and tests introduced
here would fail.

Signed-off-by: Ronald Weiss 
---
 Documentation/git-commit.txt|  6 ++
 builtin/commit.c|  8 ++-
 t/t7513-commit-ignore-submodules.sh | 42 +
 3 files changed, 55 insertions(+), 1 deletion(-)
 create mode 100644 t/t7513-commit-ignore-submodules.sh

diff --git a/Documentation/git-commit.txt b/Documentation/git-commit.txt
index 1a7616c..8d3b2db 100644
--- a/Documentation/git-commit.txt
+++ b/Documentation/git-commit.txt
@@ -13,6 +13,7 @@ SYNOPSIS
   [-F  | -m ] [--reset-author] [--allow-empty]
   [--allow-empty-message] [--no-verify] [-e] [--author=]
   [--date=] [--cleanup=] [--[no-]status]
+  [--ignore-submodules[=]]
   [-i | -o] [-S[]] [--] [...]
 
 DESCRIPTION
@@ -271,6 +272,11 @@ The possible options are:
 The default can be changed using the status.showUntrackedFiles
 configuration variable documented in linkgit:git-config[1].
 
+--ignore-submodules[=]::
+   Can be used to override any settings of the 'submodule.*.ignore'
+   option in linkgit:git-config[1] or linkgit:gitmodules[5].
+can be either "none" or "all", which is the default.
+
 -v::
 --verbose::
Show unified diff between the HEAD commit and what
diff --git a/builtin/commit.c b/builtin/commit.c
index 0db215b..121c185 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -360,7 +360,7 @@ static char *prepare_index(int argc, const char **argv, 
const char *prefix,
 */
if (all || (also && pathspec.nr)) {
fd = hold_locked_index(&index_lock, 1);
-   add_files_to_cache(also ? prefix : NULL, &pathspec, 0, NULL);
+   add_files_to_cache(also ? prefix : NULL, &pathspec, 0, 
ignore_submodule_arg);
refresh_cache_or_die(refresh_flags);
update_main_cache_tree(WRITE_TREE_SILENT);
if (write_cache(fd, active_cache, active_nr) ||
@@ -1492,6 +1492,9 @@ int cmd_commit(int argc, const char **argv, const char 
*prefix)
OPT_BOOL(0, "amend", &amend, N_("amend previous commit")),
OPT_BOOL(0, "no-post-rewrite", &no_post_rewrite, N_("bypass 
post-rewrite hook")),
{ OPTION_STRING, 'u', "untracked-files", &untracked_files_arg, 
N_("mode"), N_("show untracked files, optional modes: all, normal, no. 
(Default: all)"), PARSE_OPT_OPTARG, NULL, (intptr_t)"all" },
+   { OPTION_STRING, 0, "ignore-submodules", &ignore_submodule_arg, 
N_("when"),
+ N_("ignore changes to submodules, optional when: all, none. 
(Default: all)"),
+ PARSE_OPT_OPTARG, NULL, (intptr_t)"all" },
/* end commit contents options */
 
OPT_HIDDEN_BOOL(0, "allow-empty", &allow_empty,
@@ -1531,6 +1534,9 @@ int cmd_commit(int argc, const char **argv, const char 
*prefix)
argc = parse_and_validate_options(argc, argv, builtin_commit_options,
  builtin_commit_usage,
  prefix, current_head, &s);
+
+   s.ignore_submodule_arg = ignore_submodule_arg;
+
if (dry_run)
return dry_run_commit(argc, argv, prefix, current_head, &s);
index_file = prepare_index(argc, argv, prefix, current_head, 0);
diff --git a/t/t7513-commit-ignore-submodules.sh 
b/t/t7513-commit-ignore-submodules.sh
new file mode 100644
index 000..83ce04c
--- /dev/null
+++ b/t/t7513-commit-ignore-submodules.sh
@@ -0,0 +1,42 @@
+#!/bin/sh
+#
+# Copyright (c) 2014 Ronald Weiss
+#
+
+test_description='Test of git commit --ignore-submodules'
+
+. ./test-lib.sh
+
+test_expect_success 'create submodule' '
+   test_create_repo sm && (
+   cd sm &&
+   >foo &&
+   git add foo &&
+   git commit -m "Add foo"
+   ) &&
+   git submodule add ./sm &&
+   git commit -m "Add sm"
+'
+
+update_sm () {
+   (cd sm &&
+   echo bar >> foo &&
+   git add foo &&
+   git commit -m "Updated foo"
+   )
+}
+
+test_expect_success 'commit -a --ignore-submodules=all ignores dirty 
submodule' '
+   update_sm &&
+   test_must_fail git commit -a --ignore-submodules=all -m "Update sm"
+'
+
+test_expect_success 'commit -a --ignore-submodules=none overrides ignore=all 
setting' '
+   update_sm &&
+   git config su

[PATCH v3 1/2] add: add --ignore-submodules[=] parameter

2014-04-07 Thread Ronald Weiss
Allow overriding the ignore setting from config, using the command line
parameter like diff and status have. Git add currently doesn't honor
ignore from .gitmodules, but it does honor it from .git/config. And
support for .gitmodules will come in another patch.

Useful  values are 'none' and 'all' (the default), the other values
('dirty' and 'untracked') being equivalent to 'none' for add's purposes.

Also add ignore_submodules_arg parameter to function add_files_to_cache,
which will allow implementing --ignore-submodules also for other commands
using this function (for commit command, in particular, coming in
subsequent commit). This requires compilo fixes in checkout.c and commit.c

Signed-off-by: Ronald Weiss 
---
I have changed order of commits, from what Jens proposed, to avoid the patch
for commit (coming right after this one) having to mess too much with add's
source code.

If anyone disagrees, let me know, and I will redo it as needed.

I'll look in to the related "add [-f] vs .gitmodules:ignore=all" problem
soon.

 Documentation/git-add.txt|  7 ++-
 builtin/add.c| 21 +++
 builtin/checkout.c   |  2 +-
 builtin/commit.c |  2 +-
 cache.h  |  2 +-
 t/t3704-add-ignore-submodules.sh | 45 
 6 files changed, 71 insertions(+), 8 deletions(-)
 create mode 100644 t/t3704-add-ignore-submodules.sh

diff --git a/Documentation/git-add.txt b/Documentation/git-add.txt
index 48754cb..be2e7b5 100644
--- a/Documentation/git-add.txt
+++ b/Documentation/git-add.txt
@@ -11,7 +11,7 @@ SYNOPSIS
 'git add' [-n] [-v] [--force | -f] [--interactive | -i] [--patch | -p]
  [--edit | -e] [--[no-]all | --[no-]ignore-removal | [--update | -u]]
  [--intent-to-add | -N] [--refresh] [--ignore-errors] 
[--ignore-missing]
- [--] [...]
+ [--ignore-submodules[=]] [--] [...]
 
 DESCRIPTION
 ---
@@ -160,6 +160,11 @@ today's "git add ...", ignoring removed files.
be ignored, no matter if they are already present in the work
tree or not.
 
+--ignore-submodules[=]::
+   Can be used to override any settings of the 'submodule.*.ignore'
+   option in linkgit:git-config[1] or linkgit:gitmodules[5].
+can be either "none" or "all", which is the default.
+
 \--::
This option can be used to separate command-line options from
the list of files, (useful when filenames might be mistaken
diff --git a/builtin/add.c b/builtin/add.c
index 672adc0..72ef792 100644
--- a/builtin/add.c
+++ b/builtin/add.c
@@ -168,7 +168,8 @@ static void update_callback(struct diff_queue_struct *q,
 
 static void update_files_in_cache(const char *prefix,
  const struct pathspec *pathspec,
- struct update_callback_data *data)
+ struct update_callback_data *data,
+ const char *ignore_submodules_arg)
 {
struct rev_info rev;
 
@@ -180,17 +181,24 @@ static void update_files_in_cache(const char *prefix,
rev.diffopt.format_callback = update_callback;
rev.diffopt.format_callback_data = data;
rev.max_count = 0; /* do not compare unmerged paths with stage #2 */
+
+   if (ignore_submodules_arg) {
+   DIFF_OPT_SET(&rev.diffopt, OVERRIDE_SUBMODULE_CONFIG);
+   handle_ignore_submodules_arg(&rev.diffopt, 
ignore_submodules_arg);
+   }
+
run_diff_files(&rev, DIFF_RACY_IS_MODIFIED);
 }
 
 int add_files_to_cache(const char *prefix,
-  const struct pathspec *pathspec, int flags)
+  const struct pathspec *pathspec, int flags,
+  const char *ignore_submodules_arg)
 {
struct update_callback_data data;
 
memset(&data, 0, sizeof(data));
data.flags = flags;
-   update_files_in_cache(prefix, pathspec, &data);
+   update_files_in_cache(prefix, pathspec, &data, ignore_submodules_arg);
return !!data.add_errors;
 }
 
@@ -342,6 +350,8 @@ static int ignore_add_errors, intent_to_add, ignore_missing;
 static int addremove = ADDREMOVE_DEFAULT;
 static int addremove_explicit = -1; /* unspecified */
 
+static char *ignore_submodule_arg;
+
 static int ignore_removal_cb(const struct option *opt, const char *arg, int 
unset)
 {
/* if we are told to ignore, we are not adding removals */
@@ -367,6 +377,9 @@ static struct option builtin_add_options[] = {
OPT_BOOL( 0 , "refresh", &refresh_only, N_("don't add, only refresh the 
index")),
OPT_BOOL( 0 , "ignore-errors", &ignore_add_errors, N_("just skip files 
which cannot be added because of errors")),
OPT_BOOL( 0 , "ignore-missing", &ignore_missing, N_("check if - even 
missing - files are ignored in dry run")),
+   { OPTION_STRING, 0, "ignore-submodules", &ignore_submodule_arg, 
N_("when"),
+ N_("ignore changes 

Re: [PATCH] git-p4: explicitly specify that HEAD is a revision

2014-04-07 Thread Junio C Hamano
Pete Wyckoff  writes:

> vdog...@ixiacom.com wrote on Mon, 07 Apr 2014 16:19 +0300:
>> 'git p4 rebase' fails with the following message if there is a file
>> named HEAD in the current directory:
>> 
>>  fatal: ambiguous argument 'HEAD': both revision and filename
>>  Use '--' to separate paths from revisions, like this:
>>  'git  [...] -- [...]'
>> 
>> Take the suggestion above and explicitly state that HEAD should be
>> treated as a revision.
>> 
>> Signed-off-by: Vlad Dogaru 
>
> This looks obviously good to me, thanks!
>
> Junio, could you carry it into the next release?  As a trivial
> fixup.
>
> Acked-by: Pete Wyckoff 

Thanks; will apply directly on 'master'.

>
>> ---
>>  git-p4.py | 2 +-
>>  1 file changed, 1 insertion(+), 1 deletion(-)
>> 
>> diff --git a/git-p4.py b/git-p4.py
>> index cdfa2df..8d11b25 100755
>> --- a/git-p4.py
>> +++ b/git-p4.py
>> @@ -3086,7 +3086,7 @@ class P4Rebase(Command):
>>  print "Rebasing the current branch onto %s" % upstream
>>  oldHead = read_pipe("git rev-parse HEAD").strip()
>>  system("git rebase %s" % upstream)
>> -system("git diff-tree --stat --summary -M %s HEAD" % oldHead)
>> +system("git diff-tree --stat --summary -M %s HEAD --" % oldHead)
>>  return True
>>  
>>  class P4Clone(P4Sync):
>> -- 
>> 1.8.5.2
>> 
>> 
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH] git-p4: explicitly specify that HEAD is a revision

2014-04-07 Thread Pete Wyckoff
vdog...@ixiacom.com wrote on Mon, 07 Apr 2014 16:19 +0300:
> 'git p4 rebase' fails with the following message if there is a file
> named HEAD in the current directory:
> 
>   fatal: ambiguous argument 'HEAD': both revision and filename
>   Use '--' to separate paths from revisions, like this:
>   'git  [...] -- [...]'
> 
> Take the suggestion above and explicitly state that HEAD should be
> treated as a revision.
> 
> Signed-off-by: Vlad Dogaru 

This looks obviously good to me, thanks!

Junio, could you carry it into the next release?  As a trivial
fixup.

Acked-by: Pete Wyckoff 

> ---
>  git-p4.py | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/git-p4.py b/git-p4.py
> index cdfa2df..8d11b25 100755
> --- a/git-p4.py
> +++ b/git-p4.py
> @@ -3086,7 +3086,7 @@ class P4Rebase(Command):
>  print "Rebasing the current branch onto %s" % upstream
>  oldHead = read_pipe("git rev-parse HEAD").strip()
>  system("git rebase %s" % upstream)
> -system("git diff-tree --stat --summary -M %s HEAD" % oldHead)
> +system("git diff-tree --stat --summary -M %s HEAD --" % oldHead)
>  return True
>  
>  class P4Clone(P4Sync):
> -- 
> 1.8.5.2
> 
> 
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


What's cooking in git.git (Apr 2014, #02; Mon, 7)

2014-04-07 Thread Junio C Hamano
Here are the topics that have been cooking.  Commits prefixed with
'-' are only in 'pu' (proposed updates) while commits prefixed with
'+' are in 'next'.

You can find the changes described here in the integration branches
of the repositories listed at

http://git-blame.blogspot.com/p/git-public-repositories.html

--
[New Topics]

* jl/status-added-submodule-is-never-ignored (2014-04-07) 2 commits
 - commit -m: commit staged submodules regardless of ignore config
 - status/commit: show staged submodules regardless of ignore config


* mh/multimail (2014-04-07) 1 commit
 - git-multimail: update to version 1.0.0

--
[Stalled]

* tr/merge-recursive-index-only (2014-02-05) 3 commits
 - merge-recursive: -Xindex-only to leave worktree unchanged
 - merge-recursive: internal flag to avoid touching the worktree
 - merge-recursive: remove dead conditional in update_stages()
 (this branch is used by tr/remerge-diff.)

 Will hold.


* tr/remerge-diff (2014-02-26) 5 commits
 . log --remerge-diff: show what the conflict resolution changed
 . name-hash: allow dir hashing even when !ignore_case
 . merge-recursive: allow storing conflict hunks in index
 . revision: fold all merge diff variants into an enum merge_diff_mode
 . combine-diff: do not pass revs->dense_combined_merges redundantly
 (this branch uses tr/merge-recursive-index-only.)

 "log -p" output learns a new way to let users inspect a merge
 commit by showing the differences between the automerged result
 with conflicts the person who recorded the merge would have seen
 and the final conflict resolution that was recorded in the merge.

 Needs to be rebased, now kb/fast-hashmap topic is in.


* sz/mingw-index-pack-threaded (2014-03-19) 1 commit
 - Enable index-pack threading in msysgit.

 What is the status of this topic?  A failure report exists
 ($gmane/245170), and I am aware of Duy's $gmane/245034 but that was
 where the discussion stalled.  Is everybody waiting for everybody
 else to get the discussion unstuck?


* bc/blame-crlf-test (2014-02-18) 1 commit
 - blame: add a failing test for a CRLF issue.

 I have a feeling that a fix for this should be fairly isolated and
 trivial (it should be just the matter of paying attention to the
 crlf settings when synthesizing the fake commit)---perhaps somebody
 can squash in a fix to this?


* jk/makefile (2014-02-05) 16 commits
 - FIXUP
 - move LESS/LV pager environment to Makefile
 - Makefile: teach scripts to include make variables
 - FIXUP
 - Makefile: auto-build C strings from make variables
 - Makefile: drop *_SQ variables
 - FIXUP
 - Makefile: add c-quote helper function
 - Makefile: introduce sq function for shell-quoting
 - Makefile: always create files via make-var
 - Makefile: store GIT-* sentinel files in MAKE/
 - Makefile: prefer printf to echo for GIT-*
 - Makefile: use tempfile/mv strategy for GIT-*
 - Makefile: introduce make-var helper function
 - Makefile: fix git-instaweb dependency on gitweb
 - Makefile: drop USE_GETTEXT_SCHEME from GIT-CFLAGS

 Simplify the Makefile rules and macros that exist primarily for
 quoting purposes, and make it easier to robustly express the
 dependency rules.

 Expecting a reroll.


* po/everyday-doc (2014-01-27) 1 commit
 - Make 'git help everyday' work

 This may make the said command to emit something, but the source is
 not meant to be formatted into a manual pages to begin with, and
 also its contents are a bit stale.  It may be a good first step in
 the right direction, but needs more work to at least get the
 mark-up right before public consumption.

 Will hold.


* jk/branch-at-publish-rebased (2014-01-17) 5 commits
 - t1507 (rev-parse-upstream): fix typo in test title
 - implement @{publish} shorthand
 - branch_get: provide per-branch pushremote pointers
 - branch_get: return early on error
 - sha1_name: refactor upstream_mark

 Give an easier access to the tracking branches from "other" side in
 a triangular workflow by introducing B@{publish} that works in a
 similar way to how B@{upstream} does.

 Meant to be used as a basis for whatever Ram wants to build on.

 Will hold.


* rb/merge-prepare-commit-msg-hook (2014-01-10) 4 commits
 - merge: drop unused arg from abort_commit method signature
 - merge: make prepare_to_commit responsible for write_merge_state
 - t7505: ensure cleanup after hook blocks merge
 - t7505: add missing &&

 Expose more merge states (e.g. $GIT_DIR/MERGE_MODE) to hooks that
 run during "git merge".  The log message stresses too much on one
 hook, prepare-commit-msg, but it would equally apply to other hooks
 like post-merge, I think.

 Waiting for a reroll.


* jl/submodule-recursive-checkout (2013-12-26) 5 commits
 - Teach checkout to recursively checkout submodules
 - submodule: teach unpack_trees() to update submodules
 - submodule: teach unpack_trees() to repopulate submodules
 - submodule: teach unpack_trees() to remove submodule 

Re: [PATCH v9 11/11] Documentation: add documentation for 'git interpret-trailers'

2014-04-07 Thread Junio C Hamano
Christian Couder  writes:

> From: Junio C Hamano 
>>
>> A different way to sell a colon, e.g.
>> 
>> Consider the instruction sed takes on its command line.
>> (e.g. "sed 's/frotz/nitfol/' > form, you would always give it as the value of an '-e' option
>> (e.g. "sed -e 's/frotz/nitfol' > be loose in limited occassions.  "Key:value" is like that, and
>> in the most general form, it actually needs to be spelled as
>> "-e 'Key:value'".
>> 
>> is possible, but I do not think it is a particularly good analogy,
>> because what you have as the alternative is "Key=value", and not
>> "-e 'Key:value'", or "--Key=value" (the last would probably be the 
>> most natural way to express this).
>
> The analogy that I would use is rather that Perl lets people use
> 's:foo:bar:' as well as 's=foo=bar=' instead of 's/foo/bar/' if they
> prefer.

I could *almost* buy that, but that does not hold as you are not
allowing (and I do not think you need to in this case) the user to
pick any termination character like "s|foo|bar|".  The only thing
you are doing is forbidding both ":" and "=" from the set of allowed
characters for labels.

However.

I think we could buy the syntax if the "Key:value" form were the
*only* form, *without* accepting "Key=value".

The latter is a poor attempt to pretend as if it is a normal command
line option, but because that form does not even take double-dashes
at the beginning, it even fails to mimic as a command line option.

It would be one way to reduce the unnecessary cognitive load from
the users when learning the Git command line argument convention to
reject the "key=value" form and only stick to "key: value" form.
After all, because of the shape of the footer we add to the log
message (i.e. a keyword label followed by a colon followed by a SP
followed by the value), it is clear that we can use ":" as the
separator without inconveniencing the users who want to use some
unusual characters in the label part, but there is no strong reason
to reject an equal sign in the label.
--
To unsubscribe from this list: send the line "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: notes.rewriteRef doesn't apply to rebases that skip the commit

2014-04-07 Thread Kevin Ballard
On Apr 7, 2014, at 2:33 PM, Junio C Hamano  wrote:

> Kevin Ballard  writes:
> 
>> I’ve started using notes recently, and I have notes.rewriteRef set so that
>> when I rebase, my notes will be kept. Unfortunately, it turns out that if a
>> rebase deletes my local commit because it already exists in upstream, it
>> doesn’t copy the note to the upstream commit. It seems perfectly reasonable 
>> to
>> me to expect the note to be copied to the upstream commit, as it represents
>> the same change.
> 
> That would cut both ways, depending on the use case.  I suspect that
> those who use notes as remainder of what are still to be sent out
> would appreciate the current behavior.

It depends on how things are sent out. I know Git operates by sending all
patches to the ML, which are then reapplied, so they end up with a different
commit hash. But in most of the projects I've worked in, the main workflow
ends up with commits getting merged into master without getting rewritten. The
reason why I'm requesting this behavior is that committing without rewriting
isn't necessarily a strict rule.

For example, in the project that I'm using notes for, every commit needs to go
through Gerrit for code review. Normally it gets reviewed and merged into
origin/master without a rewrite, and my note is preserved. But sometimes
someone else will sneak a commit in first and I'll need to rebase. If I rebase
locally, that works, but Gerrit also offers to rebase my commit for me. And if
I let Gerrit do it, I still want my note to be preserved. In the end, there
should be no practical difference between me rebasing and Gerrit rebasing.

In general, Git doesn't know what the user is using notes for. If the user has
requested that notes persist through rewrite operations, it seems reasonable
that Git should recognize rewrites that happened remotely too, not just
locally.

As for your particular example of tracking what still needs to be sent out,
I'm not sure I understand that example. If I `git push` or use format-patch
and send an email, isn't that sending it out? Therefore I need to
update/delete my note explicitly. And if I want to track what hasn't made it
into origin/master yet, well, the origin/master ref already does that for me.

>> Another potential issues is if the commit exists upstream, but the 
>> surrounding
>> context has changed enough that it contains a different patch-id. In this
>> case, I would want Git to take the extra effort to correlate the upstream
>> commit with my local one (it has the same message, modulo any Signed-Off-By
>> lines, the same authorship info, and all the - and + lines in the diff are
>> identical).
> 
> That would be an orthogonal improvement, I would think.  Such a
> smarter "patch-id may mistake it, but it is a moral equivalent"
> detection would not only be useful for copying notes, but also for
> skipping the commit from getting replayed in the first place, no?

Perhaps, but replaying an empty commit already does nothing. Although I
suppose `git rebase` does have the `--keep-empty` flag, so it might be useful
there.

>> On a semi-related note, I don't see why Git should be warning about
>> notes.displayRef evaluating to a reference that doesn't exist. It doesn't
>> exist because I haven't created any notes for that ref in this repository 
>> yet.
>> But that doesn't mean I won't be creating them eventually, and when I do I
>> want them to be displayed.
> 
> That also cuts both ways. I think a warning is primarily to let
> those who mistyped the refname take notice.

I get that, but I don't think that's particularly important. There's no
practical difference between typoing the ref in notes.displayRef and forgtting
to set up notes.displayRef in the first place. Git certainly can't warn about
the latter. And the warning about the former is quite annoying if I did not
in fact typo, but rather just haven’t created any notes in that ref yet.

-Kevin Ballard--
To unsubscribe from this list: send the line "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] commit: add --ignore-submodules[=] parameter

2014-04-07 Thread Ronald Weiss
On 6. 4. 2014 18:28, Jens Lehmann wrote:
> Am 02.04.2014 21:56, schrieb Ronald Weiss:
>> On 2. 4. 2014 20:53, Jens Lehmann wrote:
>>> Am 01.04.2014 23:59, schrieb Ronald Weiss:
 On 1. 4. 2014 22:23, Jens Lehmann wrote:
> Am 01.04.2014 01:35, schrieb Ronald Weiss:
>> On 1. 4. 2014 0:50, Ronald Weiss wrote:
>>> On 31. 3. 2014 23:47, Ronald Weiss wrote:
 On Mon, Mar 31, 2014 at 8:58 PM, Jens Lehmann  
 wrote:
> As Junio mentioned it would be great if you could teach the add
> command also honor the --ignore-submodule command line option in
> a companion patch. In the course of doing so you'll easily see if
> I was right or not, then please just order them in the most logical
> way.

 Well, if You (or Junio) really don't want my patch without another one
 for git add, I may try to do it. However, git add does not even honor
 the submodules' ignore setting from .gitmodules (just tested with git
 1.9.1: "git add -u" doesn't honor it, while "git commit -a" does). So
 teaching git add the --ignore-submodules switch in current state
 doesn't seem right to me. You might propose to add also support for
 the ignore setting, to make "add -u" and "commit -a" more consistent.
 That seems like a good idea, but the effort needed is getting bigger,
>>>
>>> Well, now I actually looked at it, and it was pretty easy after all.
>>> The changes below seem to enable support for both ignore setting in
>>> .gitmodules, and also --ignore-submodules switch, for git add, on top
>>> of my patch for commit.
>>
>> There is a catch. With the changes below, submodules are ignored by add
>> even if explitely named on command line (eg. "git add x" does nothing
>> if x is submodule with new commits, but with ignore=all in .gitmodules).
>> That doesn't seem right.
>>
>> Any ideas, what to do about that? When exactly should such submodule be
>> actually ignored?
>
> Me thinks git add should require the '-f' option to add an ignored
> submodule (just like it does for files) unless the user uses the
> '--ignore-submodules=none' option. And if neither of these are given
> it should "fail with a list of ignored files" as the documentation
> states.

 It's still not clear, at least not to me. Should '-f' suppress the
 ignore setting of all involved submodules? That would make it a
 synonyme (or a superset) of --ignore-submodules=none. Or only if the
 submodule is explicitly named on command line? That seems fuzzy to me,
 and also more tricky to implement.
>>>
>>> Maybe my impression that doing "add" together with "commit" would be
>>> easy wasn't correct after all. I won't object if you try to tackle
>>> commit first (but I have the slight suspicion that similar questions
>>> will arise concerning the "add"ish functionality in commit too. So
>>> maybe after resolving those things might look clearer ;-)
>>
>> There is one big distinction. My patch for commit doesn't add any new
>> problems. It just adds the --ignore-submodules argument, which is easy
>> to implement and no unclear behavior decisions are needed.
>>
>> You are right that when specifying ignored submodules on commit's
>> command line, there is the same problem as with git add. However, it's
>> already there anyway. I don't feel in position to solve it, I'd just
>> like to have "git commit --ignore-submodules=none".
>>
>> With git add however, changing it to honor settings from .gitmodules
>> would change behavior people might be used to, so I would be afraid to
>> do that. Btw add also has the problem already, but only if somebody
>> configures the submodule's ignore setting in .git/config, rather than
>> .gitmodules. I don't know how much real use case that is.
>>
>> As I see it, there are now these rather easy possibilities (sorted
>> from the easiest):
>>
>> 1) Just teach commit the --ignore-submodules argument, as I proposed.
> 
> 1a) Teach commit to honor ignore from .git/config.

But commit already honors that. It honors submodule..ignore from
both .git/config and .gitmodules. It's just add which doesn't honor it
from .gitmodules, because cmd_add() function lacks a gitmodules_config()
call. Or do I miss something?

>> 2) Teach both add and commit to --ignore-submodules, but dont add that
>> problematic gitmodules_config() in add.c.
> 
> Why is that problematic after add learned --ignore-submodules=none?

First, because it changes current behaviour. Which is obviously
inconsistent currently, however I didn't find it easy to tell what's
the right thing to do.

And second, because the "-f implies --ignore-submodules=none" proposal,
which seems to be the easy cure for those accustomed to the current
behavior, seems non-trivial. Below You wrote that
--ignore-submodules=none should be implied by -f only for files
specified on the command line. OK.

Re: [PATCH v10 12/12] trailer: add blank line before the trailers if needed

2014-04-07 Thread Junio C Hamano
Christian Couder  writes:

> Signed-off-by: Christian Couder 
> ---

Hmph, this is more fixing a mistake made earlier in the series at
the end than adding a new feature or something.  Can you start from
a version that does not have the mistake from the beginning?
--
To unsubscribe from this list: send the line "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: notes.rewriteRef doesn't apply to rebases that skip the commit

2014-04-07 Thread Junio C Hamano
Kevin Ballard  writes:

> I’ve started using notes recently, and I have notes.rewriteRef set so that
> when I rebase, my notes will be kept. Unfortunately, it turns out that if a
> rebase deletes my local commit because it already exists in upstream, it
> doesn’t copy the note to the upstream commit. It seems perfectly reasonable to
> me to expect the note to be copied to the upstream commit, as it represents
> the same change.

That would cut both ways, depending on the use case.  I suspect that
those who use notes as remainder of what are still to be sent out
would appreciate the current behaviour.

> One complication I can see is when my local commit is deleted not because it
> exists upstream, but because it ends up being an empty commit due to the
> changes existing across multiple upstream commits. In this case I see no
> alternative but to have the note disappear. But I think that's acceptable.

Oh, no question about that.

> Another potential issues is if the commit exists upstream, but the surrounding
> context has changed enough that it contains a different patch-id. In this
> case, I would want Git to take the extra effort to correlate the upstream
> commit with my local one (it has the same message, modulo any Signed-Off-By
> lines, the same authorship info, and all the - and + lines in the diff are
> identical).

That would be an orthogonal improvement, I would think.  Such a
smarter "patch-id may mistake it, but it is a moral equivalent"
detection would not only be useful for copying notes, but also for
skipping the commit from getting replayed in the first place, no?

> On a semi-related note, I don't see why Git should be warning about
> notes.displayRef evaluating to a reference that doesn't exist. It doesn't
> exist because I haven't created any notes for that ref in this repository yet.
> But that doesn't mean I won't be creating them eventually, and when I do I
> want them to be displayed.

That also cuts both ways. I think a warning is primarily to let
those who mistyped the refname take notice.

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


notes.rewriteRef doesn't apply to rebases that skip the commit

2014-04-07 Thread Kevin Ballard

I’ve started using notes recently, and I have notes.rewriteRef set so that
when I rebase, my notes will be kept. Unfortunately, it turns out that if a
rebase deletes my local commit because it already exists in upstream, it
doesn’t copy the note to the upstream commit. It seems perfectly reasonable to
me to expect the note to be copied to the upstream commit, as it represents
the same change.

One complication I can see is when my local commit is deleted not because it
exists upstream, but because it ends up being an empty commit due to the
changes existing across multiple upstream commits. In this case I see no
alternative but to have the note disappear. But I think that's acceptable.

Another potential issues is if the commit exists upstream, but the surrounding
context has changed enough that it contains a different patch-id. In this
case, I would want Git to take the extra effort to correlate the upstream
commit with my local one (it has the same message, modulo any Signed-Off-By
lines, the same authorship info, and all the - and + lines in the diff are
identical). That said, I'd still understand if it didn't do that and lost my
note. It would be unfortunate, but it would match today's behavior. I'm ok
with copying over my notes when necessary, I just want Git to handle it when
it's obviously correct (e.g. when the patch-id matches).

---

On a semi-related note, I don't see why Git should be warning about
notes.displayRef evaluating to a reference that doesn't exist. It doesn't
exist because I haven't created any notes for that ref in this repository yet.
But that doesn't mean I won't be creating them eventually, and when I do I
want them to be displayed.

For reference, I've been using git v1.9.0. The v1.9.1 release notes don't
mention anything notes-related so I assume these issues still exist.

-Kevin Ballard

--
To unsubscribe from this list: send the line "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 18/19] tree-diff: rework diff_tree() to generate diffs for multiparent cases as well

2014-04-07 Thread Kirill Smelkov
On Mon, Apr 07, 2014 at 10:29:46AM -0700, Junio C Hamano wrote:
> Kirill Smelkov  writes:
> 
> > The following
> > ...
> > maybe looks a bit simpler, but calls tree_entry_pathcmp twice more times.
> >
> > Besides for important nparent=1 case we were not calling
> > tree_entry_pathcmp at all and here we'll call it once, which would slow
> > execution down a bit, as base_name_compare shows measurable enough in 
> > profile.
> > To avoid that we'll need to add 'if (i==imin) continue' and this won't
> > be so simple then. And for general nparent case, as I've said, we'll be
> > calling tree_entry_pathcmp twice more times...
> >
> > Because of all that I'd suggest to go with my original version.
> 
> OK.

Thanks.

> > ... After some break on the topic,
> > with a fresh eye I see a lot of confusion goes from the notation I've
> > chosen initially (because of how I was reasoning about it on paper, when
> > it was in flux) - i.e. xi for x[imin] and also using i as looping
> > variable. And also because xi was already used for x[imin] I've used
> > another letter 'k' denoting all other x'es, which leads to confusion...
> >
> >
> > I propose we do the following renaming to clarify things:
> >
> > A/a ->  T/t (to match resulting tree t name in the code)
> > X/x ->  P/p (to match parents trees tp in the code)
> > i   ->  imin(so that i would be free for other tasks)
> >
> > then the above (with a prologue) would look like
> >
> >  8< 
> >  *   T P1   Pn
> >  *   - --
> >  *  |t|   |p1| |pn|
> >  *  |-|   |--| ... |--|  imin = argmin(p1...pn)
> >  *  | |   |  | |  |
> >  *  |-|   |--| |--|
> >  *  |.|   |. | |. |
> >  *   . ..
> >  *   . ..
> >  *
> >  * at any time there could be 3 cases:
> >  *
> >  *  1)  t < p[imin];
> >  *  2)  t > p[imin];
> >  *  3)  t = p[imin].
> >  *
> >  * Schematic deduction of what every case means, and what to do, follows:
> >  *
> >  * 1)  t < p[imin]  ->  ∀j t ∉ Pj  ->  "+t" ∈ D(T,Pj)  ->  D += "+t";  t↓
> >  *
> >  * 2)  t > p[imin]
> >  *
> >  * 2.1) ∃j: pj > p[imin]  ->  "-p[imin]" ∉ D(T,Pj)  ->  D += ø;  ∀ 
> > pi=p[imin]  pi↓
> >  * 2.2) ∀i  pi = p[imin]  ->  pi ∉ T  ->  "-pi" ∈ D(T,Pi)  ->  D += 
> > "-p[imin]";  ∀i pi↓
> >  *
> >  * 3)  t = p[imin]
> >  *
> >  * 3.1) ∃j: pj > p[imin]  ->  "+t" ∈ D(T,Pj)  ->  only pi=p[imin] 
> > remains to investigate
> >  * 3.2) pi = p[imin]  ->  investigate δ(t,pi)
> >  *  |
> >  *  |
> >  *  v
> >  *
> >  * 3.1+3.2) looking at δ(t,pi) ∀i: pi=p[imin] - if all != ø  ->
> >  *
> >  *   ⎧δ(t,pi)  - if pi=p[imin]
> >  *  ->  D += ⎨
> >  *   ⎩"+t" - if pi>p[imin]
> >  *
> >  *
> >  * in any case t↓  ∀ pi=p[imin]  pi↓
> > ...
> > now xk is gone and i matches p[i] (= pi) etc so variable names correlate
> > to algorithm description better.
> >
> > Does that maybe clarify things?
> 
> That sounds more consistent (modulo perhaps s/argmin/min/ at the
> beginning?).

Thanks. argmin is there on purpose - min(p1...pn) is the minimal p, and
argmin(p1...pn) is imin such that p[imin] is minimal. As we are finding
the index of the minimal element we should use argmin.


> > P.S. Sorry for maybe some crept-in mistakes - I've tried to verify it
> > thoroughly, but am too sleepy to be completely sure. On the other hand I
> > think and hope the patch should be ok.
> 
> Thanks and do not be sorry for "mistakes"---we have the review
> process exactly for catching them.

Thanks, I appreciate that.


On Mon, Apr 07, 2014 at 11:07:47AM -0700, Junio C Hamano wrote:
> Kirill Smelkov  writes:
> 
> >> > +if (!DIFF_OPT_TST(opt, FIND_COPIES_HARDER)) {
> >> > +for (i = 0; i < nparent; ++i)
> >> > +if (tp[i].entry.mode & 
> >> > S_IFXMIN_NEQ)
> >> > +goto skip_emit_tp;
> >> > +}
> >> > +
> >> > +p = emit_path(p, base, opt, nparent,
> >> > +/*t=*/NULL, tp, imin);
> >> > +
> >> > +skip_emit_tp:
> >> > +/* ∀ xk=ximin  xk↓ */
> >> > +update_tp_entries(tp, nparent);
> >> 
> >> There are parents whose path sort earlier than what is in 't'
> >> (i.e. they were lost in the result---we would want to show
> >> removal).  What makes us jump to the skip label?
> >> 
> >> We are looking at path in 't', and some parents have paths that
> >> sort earlier than that path.  We will not go to skip label if
> >> any one of the parent's entry sorts after some other parent (or
> >> the parent in question has ran out its entries), which means we
> >> show the entry from the parents only when all the parents have
> >> that same path,

Re: [PATCH] Unicode: update of combining code points

2014-04-07 Thread Jonathan Nieder
Hi,

Torsten Bögershausen wrote:

> Unicode 6.3 defines the following code as combining or accents,
> git_wcwidth() should return 0.
>
> Earlier unicode standards had defined these code point as "reserved":

Thanks for the update.  Could the commit message also explain how this
was noticed and what the user-visible effect is?

For example:

 "Unicode just announced that <...>.  That means we should mark the
  relevant code points as combining characters so git knows they are
  zero-width and doesn't screw up the alignment when presenting branch
  names in columns with 'git branch --column'"

or something like that.

[...]
> 358 COMBINING DOT ABOVE RIGHT
> 359 COMBINING ASTERISK BELOW

I'm not sure this list is needed --- the code + the reference to the
Unicode 6.3 standard seems like enough (but if you think otherwise,
I don't really mind).

> This commit touches only the range 300-6FF, there may be more to be updated.

The "there may be more" here sounds ominous.  Does that mean Unicode
6.3 also added some zero-width characters in other ranges that should
be dealt with in the future?  How many such ranges?  How do we know
when we're done?

Just biting off the most important characters first and putting off
the rest for later sounds fine to me --- my complaint is that the
above comment doesn't make clear what the to-do list is for finishing
the update later.

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


Re: What's cooking in git.git (Apr 2014, #01; Fri, 4)

2014-04-07 Thread Ramsay Jones
On 07/04/14 19:35, Johannes Sixt wrote:
> Am 05.04.2014 11:19, schrieb Johannes Sixt:
>> Am 04.04.2014 22:58, schrieb Junio C Hamano:
>>> * sz/mingw-index-pack-threaded (2014-03-19) 1 commit
>>>  - Enable index-pack threading in msysgit.
>>>
>>>  What is the status of this topic?  A failure report exists
>>>  ($gmane/245170), and I am aware of Duy's $gmane/245034 but that was
>>>  where the discussion stalled.  Is everybody waiting for everybody
>>>  else to get the discussion unstuck?
>>
>> I still have to cross-check Duy's patch. I'll hopefully get to it in the
>> next days and report back.
> 
> The test suite passes with Duy's patch ($gmane/245034), but t5302 fails
> with this patch with a MinGW build. The patches touch the Cygwin
> configuration, but I cannot test a Cygwin build.

I haven't tested these on cygwin yet. However, only the old version of
cygwin is affected (newer cygwin has a thread-safe pread) and, since I
no longer have an old installation, I _can't_ test it anyway. :(
(I updated cygwin earlier today and received a brand new cygwin dll
with today's date!).

> I have, however, lost track of what the objective of these patches is.
> Is the threaded version significantly faster, and these patches are
> worth it?

Indeed. I haven't seen any numbers.

ATB,
Ramsay Jones



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


Re: [PATCH v2 00/25] Lockfile correctness and refactoring

2014-04-07 Thread Jeff King
On Mon, Apr 07, 2014 at 01:33:42AM +0200, Michael Haggerty wrote:

> This is a second attempt at renovating the lock file code.  Thanks to
> Peff, Junio, Torsten, and Eric for their helpful reviews of v1.
> 
> v1 of this patch series [1] did some refactoring and then added a new
> feature to the lock_file API: the ability to activate a new version of
> a locked file while retaining the lock.
> 
> But the review of v1 turned up even more correctness issues in the
> existing implementation of lock files.  So this v2 dials back the
> scope of the changes (it omits the new feature) but does more work to
> fix problems with the current lock file implementation.
> 
> The main theme of this patch series is to better define the state
> diagram for lock_file objects and to fix code that left them in
> incorrect, indeterminate, or unexpected states.  There are also a few
> patches that convert several functions to use strbufs instead of
> limiting pathnames to a maximum length.

Looks OK to me, modulo the few comments I sent.

I still think resolve_symref should probably not be "best-effort", but
that can come later on top.

-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] Unicode: update of combining code points

2014-04-07 Thread Torsten Bögershausen
Unicode 6.3 defines the following code as combining or accents,
git_wcwidth() should return 0.

Earlier unicode standards had defined these code point as "reserved":

358 COMBINING DOT ABOVE RIGHT
359 COMBINING ASTERISK BELOW
35A COMBINING DOUBLE RING BELOW
35B COMBINING ZIGZAG ABOVE
35C COMBINING DOUBLE BREVE BELOW
487 COMBINING CYRILLIC POKRYTIE
5A2 HEBREW ACCENT ATNAH HAFUKH,
5BA HEBREW POINT HOLAM HASER FOR VAV
5C5 HEBREW MARK LOWER DOT
5C7 HEBREW POINT QAMATS QATAN
604 ARABIC SIGN SAMVAT
616 ARABIC SMALL HIGH LIGATURE ALEF WITH LAM WITH YEH
617 ARABIC SMALL HIGH ZAIN
618 ARABIC SMALL FATHA
619 ARABIC SMALL DAMMA
61A ARABIC SMALL KASRA
659 ARABIC ZWARAKAY
65A ARABIC VOWEL SIGN SMALL V ABOVE
65B ARABIC VOWEL SIGN INVERTED SMALL V ABOVE
65C ARABIC VOWEL SIGN DOT BELOW
65D ARABIC REVERSED DAMMA
65E ARABIC FATHA WITH TWO DOTS
65F ARABIC WAVY HAMZA BELOW

This commit touches only the range 300-6FF, there may be more to be updated.

Signed-off-by: Torsten Bögershausen 
---
 utf8.c | 9 -
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/utf8.c b/utf8.c
index a831d50..77c28d4 100644
--- a/utf8.c
+++ b/utf8.c
@@ -84,11 +84,10 @@ static int git_wcwidth(ucs_char_t ch)
 *   "uniset +cat=Me +cat=Mn +cat=Cf -00AD +1160-11FF +200B c".
 */
static const struct interval combining[] = {
-   { 0x0300, 0x0357 }, { 0x035D, 0x036F }, { 0x0483, 0x0486 },
-   { 0x0488, 0x0489 }, { 0x0591, 0x05A1 }, { 0x05A3, 0x05B9 },
-   { 0x05BB, 0x05BD }, { 0x05BF, 0x05BF }, { 0x05C1, 0x05C2 },
-   { 0x05C4, 0x05C4 }, { 0x0600, 0x0603 }, { 0x0610, 0x0615 },
-   { 0x064B, 0x0658 }, { 0x0670, 0x0670 }, { 0x06D6, 0x06E4 },
+   { 0x0300, 0x036F }, { 0x0483, 0x0489 }, { 0x0591, 0x05BD },
+   { 0x05BF, 0x05BF }, { 0x05C1, 0x05C2 }, { 0x05C4, 0x05C5 },
+   { 0x05C7, 0x05C7 }, { 0x0600, 0x0604 }, { 0x0610, 0x061A },
+   { 0x064B, 0x065F }, { 0x0670, 0x0670 }, { 0x06D6, 0x06E4 },
{ 0x06E7, 0x06E8 }, { 0x06EA, 0x06ED }, { 0x070F, 0x070F },
{ 0x0711, 0x0711 }, { 0x0730, 0x074A }, { 0x07A6, 0x07B0 },
{ 0x0901, 0x0902 }, { 0x093C, 0x093C }, { 0x0941, 0x0948 },
-- 
1.9.0

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


[PATCH] Unicode: update of combining code points

2014-04-07 Thread Torsten Bögershausen
Unicode 6.3 defines the following code as combining or accents,
git_wcwidth() should return 0.

Earlier unicode standards had defined these code point as "reserved":

358 COMBINING DOT ABOVE RIGHT
359 COMBINING ASTERISK BELOW
35A COMBINING DOUBLE RING BELOW
35B COMBINING ZIGZAG ABOVE
35C COMBINING DOUBLE BREVE BELOW
487 COMBINING CYRILLIC POKRYTIE
5A2 HEBREW ACCENT ATNAH HAFUKH,
5BA HEBREW POINT HOLAM HASER FOR VAV
5C5 HEBREW MARK LOWER DOT
5C7 HEBREW POINT QAMATS QATAN
604 ARABIC SIGN SAMVAT
616 ARABIC SMALL HIGH LIGATURE ALEF WITH LAM WITH YEH
617 ARABIC SMALL HIGH ZAIN
618 ARABIC SMALL FATHA
619 ARABIC SMALL DAMMA
61A ARABIC SMALL KASRA
659 ARABIC ZWARAKAY
65A ARABIC VOWEL SIGN SMALL V ABOVE
65B ARABIC VOWEL SIGN INVERTED SMALL V ABOVE
65C ARABIC VOWEL SIGN DOT BELOW
65D ARABIC REVERSED DAMMA
65E ARABIC FATHA WITH TWO DOTS
65F ARABIC WAVY HAMZA BELOW

This commit touches only the range 300-6FF, there may be more to be updated.

Signed-off-by: Torsten Bögershausen 
---
 utf8.c | 9 -
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/utf8.c b/utf8.c
index a831d50..77c28d4 100644
--- a/utf8.c
+++ b/utf8.c
@@ -84,11 +84,10 @@ static int git_wcwidth(ucs_char_t ch)
 *   "uniset +cat=Me +cat=Mn +cat=Cf -00AD +1160-11FF +200B c".
 */
static const struct interval combining[] = {
-   { 0x0300, 0x0357 }, { 0x035D, 0x036F }, { 0x0483, 0x0486 },
-   { 0x0488, 0x0489 }, { 0x0591, 0x05A1 }, { 0x05A3, 0x05B9 },
-   { 0x05BB, 0x05BD }, { 0x05BF, 0x05BF }, { 0x05C1, 0x05C2 },
-   { 0x05C4, 0x05C4 }, { 0x0600, 0x0603 }, { 0x0610, 0x0615 },
-   { 0x064B, 0x0658 }, { 0x0670, 0x0670 }, { 0x06D6, 0x06E4 },
+   { 0x0300, 0x036F }, { 0x0483, 0x0489 }, { 0x0591, 0x05BD },
+   { 0x05BF, 0x05BF }, { 0x05C1, 0x05C2 }, { 0x05C4, 0x05C5 },
+   { 0x05C7, 0x05C7 }, { 0x0600, 0x0604 }, { 0x0610, 0x061A },
+   { 0x064B, 0x065F }, { 0x0670, 0x0670 }, { 0x06D6, 0x06E4 },
{ 0x06E7, 0x06E8 }, { 0x06EA, 0x06ED }, { 0x070F, 0x070F },
{ 0x0711, 0x0711 }, { 0x0730, 0x074A }, { 0x07A6, 0x07B0 },
{ 0x0901, 0x0902 }, { 0x093C, 0x093C }, { 0x0941, 0x0948 },
-- 
1.9.0

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


[PATCH] Unicode: update of combining code points

2014-04-07 Thread Torsten Bögershausen
Unicode 6.3 defines the following code as combining or accents,
git_wcwidth() should return 0.

Earlier unicode standards had defined these code point as "reserved":

358 COMBINING DOT ABOVE RIGHT
359 COMBINING ASTERISK BELOW
35A COMBINING DOUBLE RING BELOW
35B COMBINING ZIGZAG ABOVE
35C COMBINING DOUBLE BREVE BELOW
487 COMBINING CYRILLIC POKRYTIE
5A2 HEBREW ACCENT ATNAH HAFUKH,
5BA HEBREW POINT HOLAM HASER FOR VAV
5C5 HEBREW MARK LOWER DOT
5C7 HEBREW POINT QAMATS QATAN
604 ARABIC SIGN SAMVAT
616 ARABIC SMALL HIGH LIGATURE ALEF WITH LAM WITH YEH
617 ARABIC SMALL HIGH ZAIN
618 ARABIC SMALL FATHA
619 ARABIC SMALL DAMMA
61A ARABIC SMALL KASRA
659 ARABIC ZWARAKAY
65A ARABIC VOWEL SIGN SMALL V ABOVE
65B ARABIC VOWEL SIGN INVERTED SMALL V ABOVE
65C ARABIC VOWEL SIGN DOT BELOW
65D ARABIC REVERSED DAMMA
65E ARABIC FATHA WITH TWO DOTS
65F ARABIC WAVY HAMZA BELOW

This commit touches only the range 300-6FF, there may be more to be updated.

Signed-off-by: Torsten Bögershausen 
---
 utf8.c | 9 -
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/utf8.c b/utf8.c
index a831d50..77c28d4 100644
--- a/utf8.c
+++ b/utf8.c
@@ -84,11 +84,10 @@ static int git_wcwidth(ucs_char_t ch)
 *   "uniset +cat=Me +cat=Mn +cat=Cf -00AD +1160-11FF +200B c".
 */
static const struct interval combining[] = {
-   { 0x0300, 0x0357 }, { 0x035D, 0x036F }, { 0x0483, 0x0486 },
-   { 0x0488, 0x0489 }, { 0x0591, 0x05A1 }, { 0x05A3, 0x05B9 },
-   { 0x05BB, 0x05BD }, { 0x05BF, 0x05BF }, { 0x05C1, 0x05C2 },
-   { 0x05C4, 0x05C4 }, { 0x0600, 0x0603 }, { 0x0610, 0x0615 },
-   { 0x064B, 0x0658 }, { 0x0670, 0x0670 }, { 0x06D6, 0x06E4 },
+   { 0x0300, 0x036F }, { 0x0483, 0x0489 }, { 0x0591, 0x05BD },
+   { 0x05BF, 0x05BF }, { 0x05C1, 0x05C2 }, { 0x05C4, 0x05C5 },
+   { 0x05C7, 0x05C7 }, { 0x0600, 0x0604 }, { 0x0610, 0x061A },
+   { 0x064B, 0x065F }, { 0x0670, 0x0670 }, { 0x06D6, 0x06E4 },
{ 0x06E7, 0x06E8 }, { 0x06EA, 0x06ED }, { 0x070F, 0x070F },
{ 0x0711, 0x0711 }, { 0x0730, 0x074A }, { 0x07A6, 0x07B0 },
{ 0x0901, 0x0902 }, { 0x093C, 0x093C }, { 0x0941, 0x0948 },
-- 
1.9.0

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


[PATCH] Unicode: update of combining code points

2014-04-07 Thread Torsten Bögershausen
Unicode 6.3 defines the following code as combining or accents,
git_wcwidth() should return 0.

Earlier unicode standards had defined these code point as "reserved":

358 COMBINING DOT ABOVE RIGHT
359 COMBINING ASTERISK BELOW
35A COMBINING DOUBLE RING BELOW
35B COMBINING ZIGZAG ABOVE
35C COMBINING DOUBLE BREVE BELOW
487 COMBINING CYRILLIC POKRYTIE
5A2 HEBREW ACCENT ATNAH HAFUKH,
5BA HEBREW POINT HOLAM HASER FOR VAV
5C5 HEBREW MARK LOWER DOT
5C7 HEBREW POINT QAMATS QATAN
604 ARABIC SIGN SAMVAT
616 ARABIC SMALL HIGH LIGATURE ALEF WITH LAM WITH YEH
617 ARABIC SMALL HIGH ZAIN
618 ARABIC SMALL FATHA
619 ARABIC SMALL DAMMA
61A ARABIC SMALL KASRA
659 ARABIC ZWARAKAY
65A ARABIC VOWEL SIGN SMALL V ABOVE
65B ARABIC VOWEL SIGN INVERTED SMALL V ABOVE
65C ARABIC VOWEL SIGN DOT BELOW
65D ARABIC REVERSED DAMMA
65E ARABIC FATHA WITH TWO DOTS
65F ARABIC WAVY HAMZA BELOW

This commit touches only the range 300-6FF, there may be more to be updated.

Signed-off-by: Torsten Bögershausen 
---
 utf8.c | 9 -
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/utf8.c b/utf8.c
index a831d50..77c28d4 100644
--- a/utf8.c
+++ b/utf8.c
@@ -84,11 +84,10 @@ static int git_wcwidth(ucs_char_t ch)
 *   "uniset +cat=Me +cat=Mn +cat=Cf -00AD +1160-11FF +200B c".
 */
static const struct interval combining[] = {
-   { 0x0300, 0x0357 }, { 0x035D, 0x036F }, { 0x0483, 0x0486 },
-   { 0x0488, 0x0489 }, { 0x0591, 0x05A1 }, { 0x05A3, 0x05B9 },
-   { 0x05BB, 0x05BD }, { 0x05BF, 0x05BF }, { 0x05C1, 0x05C2 },
-   { 0x05C4, 0x05C4 }, { 0x0600, 0x0603 }, { 0x0610, 0x0615 },
-   { 0x064B, 0x0658 }, { 0x0670, 0x0670 }, { 0x06D6, 0x06E4 },
+   { 0x0300, 0x036F }, { 0x0483, 0x0489 }, { 0x0591, 0x05BD },
+   { 0x05BF, 0x05BF }, { 0x05C1, 0x05C2 }, { 0x05C4, 0x05C5 },
+   { 0x05C7, 0x05C7 }, { 0x0600, 0x0604 }, { 0x0610, 0x061A },
+   { 0x064B, 0x065F }, { 0x0670, 0x0670 }, { 0x06D6, 0x06E4 },
{ 0x06E7, 0x06E8 }, { 0x06EA, 0x06ED }, { 0x070F, 0x070F },
{ 0x0711, 0x0711 }, { 0x0730, 0x074A }, { 0x07A6, 0x07B0 },
{ 0x0901, 0x0902 }, { 0x093C, 0x093C }, { 0x0941, 0x0948 },
-- 
1.9.0

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


Re: [PATCH v2 18/25] lockfile: avoid transitory invalid states

2014-04-07 Thread Jeff King
On Mon, Apr 07, 2014 at 03:12:49PM +0200, Michael Haggerty wrote:

> > How far *do* you want to go? I'm certainly not opposed to field-test your
> > current changeset (plus and adjustment to use sig_atomic_t) -- overall it
> > is an improvement. And then we will see how it works.
> 
> For now I think I'd just like to get the biggest problems fixed without
> making anything worse.  Given that there might be a GSoC student working
> in this neighborhood, he/she might be able to take up the baton.
> 
> I changed the patch series to use a new "volatile sig_atomic_t active"
> field rather than a bit in a "flags" field.

That seems like a good place to stop for now.

If any code touches the fields, it can unset the "active" flag (even
temporarily), and restore it when the structure is in a known state.

I'm not sure if we can ever reach full safety. If you have an event
loop, the sane thing to do is set an atomic flag in your signal handler
and then handle it on the next iteration of the loop. But all of our
signal handlers are jumped to from arbitrary code, and are just going to
die(). There's nothing to return to, so any useful work we do has to be
done from the handler.

-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 v9 11/11] Documentation: add documentation for 'git interpret-trailers'

2014-04-07 Thread Junio C Hamano
Christian Couder  writes:

>> I do not see these two as valid arguments to make the command line
>> more complex to the end users
>
> I don't think that it makes the command more complex to the end users.
>
>> ---who now need to know that only this
>> command treats its command line in a funny way, accepting a colon in
>> place of an equal sign.

I meant that it makes learning the "command line syntax of Git" more
complex to new users.  If one is too narrowly focused on this single
command, it may not seem that "the command" is not made more
complex, but I am more interested in making sure that the entire Git
command line experience does not get unnecessarily harder to learn.
--
To unsubscribe from this list: send the line "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 17/25] commit_lock_file(): make committing an unlocked lockfile a NOP

2014-04-07 Thread Jeff King
On Mon, Apr 07, 2014 at 01:33:59AM +0200, Michael Haggerty wrote:

> It was previously a bug to call commit_lock_file() with a lock_file
> object that was not active (an illegal access would happen within the
> function).  It was presumably never done, but this would be an easy
> programming error to overlook.  So guard the file-renaming code with
> an if statement to change committing an unlocked file into a NOP.
> 
> Signed-off-by: Michael Haggerty 
> ---
> Alternatively, we could make it a fatal error (e.g., an assert() or
> if...die()) to call commit_lock_file() on an unlocked file, or omit a
> warning in this case.  But since it is so hard to test code related to
> locking failures, I have the feeling that such an error is most likely
> to occur in some error-handling path, maybe when some other lockfile
> acquisition has failed, and it would be better to let the code
> continue its attempted cleanup instead of dying.  But it would be easy
> to persuade me to change my opinion.

Yeah, I would have expected a die("BUG") here.

I think it is worth making it a fatal mistake and catching it. Rolling
back an uninitialized lockfile is probably OK; we are canceling an
operation that never started. But committing a lockfile that we didn't
actually fill out could be a sign of a serious error, and we may be
propagating a bogus success code. E.g., imagine that receive-pack claims
to have written your ref, but actually commit_lock_file was a silent
NOP. I'd much rather have it die loudly so we can track down the case.

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


Re: [PATCH v3 19/27] refs: add a concept of a reference transaction

2014-04-07 Thread Junio C Hamano
Michael Haggerty  writes:

> +void ref_transaction_create(struct ref_transaction *transaction,
> + const char *refname,
> + unsigned char *new_sha1,
> + int flags)
> +{
> + struct ref_update *update = add_update(transaction, refname);
> +
> + assert(!is_null_sha1(new_sha1));
> + hashcpy(update->new_sha1, new_sha1);
> + hashclr(update->old_sha1);
> + update->flags = flags;
> + update->have_old = 1;
> +}
> +
> +void ref_transaction_delete(struct ref_transaction *transaction,
> + const char *refname,
> + unsigned char *old_sha1,
> + int flags, int have_old)
> +{
> + struct ref_update *update = add_update(transaction, refname);
> +
> + update->flags = flags;
> + update->have_old = have_old;
> + if (have_old) {
> + assert(!is_null_sha1(old_sha1));
> + hashcpy(update->old_sha1, old_sha1);
> + }
> +}

These assert()s will often turn into no-op in production builds.  If
it is a bug in the code (i.e. the callers are responsible for
catching these conditions and issuing errors, and there are actually
such checks implemented in the callers), it is fine to have these as
assert()s, but otherwise these should be 'if (...) die("BUG:")', I
think.

Other than that, I did not spot anything questionable in this round.

Thanks; will replace the series (but on the same base as I needed to
apply the series there to compare what got changed with the old
version of corresponding change for each patches).
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [RFC] git submodule split

2014-04-07 Thread Jens Lehmann
Am 06.04.2014 23:18, schrieb Michal Sojka:
> On Sun, Apr 06 2014, Jens Lehmann wrote:
>> Am 02.04.2014 23:52, schrieb Michal Sojka:
>>> Hello,
>>>
>>> I needed to convert a subdirectory of a repo to a submodule and have the
>>> histories of both repos linked together. I found that this was discussed
>>> few years back [1], but the code seemed quite complicated and was not
>>> merged.
>>>
>>> [1]: 
>>> http://git.661346.n2.nabble.com/RFC-What-s-the-best-UI-for-git-submodule-split-tp2318127.html
>>>
>>> Now, the situation is better, because git subtree can already do most of
>>> the work. Below is a script that I used to split a submodule from my
>>> repo. It basically consist of a call to 'git subtree split' followed by
>>> 'git filter-branch' to link the histories together.
>>>
>>> I'd like to get some initial feedback on it before attempting to
>>> integrate it with git sources (i.e. writing tests and doc). What do you
>>> think?
>>
>> Why do want to rewrite the whole history of the superproject,
>> wouldn't it suffice to turn a directory into a submodule with
>> the same content in a simple commit? 
> 
> I wanted to publish a project including its history but a part of that
> project could not be made public due to legal reasons. Putting that part
> into submodule seemed like best idea.

Yep, that makes lots of sense.

I'm not sure yet if this functionality is needed often enough to
put the script under contrib, but I won't object as long as you'd
be willing to maintain it (and help people on this list when they
report any issues).
--
To unsubscribe from this list: send the line "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 v9 11/11] Documentation: add documentation for 'git interpret-trailers'

2014-04-07 Thread Christian Couder
From: Junio C Hamano 
>
> Christian Couder  writes:
> 
>> First accepting both ':' and '=' means one can see the "git
>> interpret-trailers" as acting on trailers only. Not just on trailers
>> from the intput message and option parameters from the command line.
> 
> Sorry, you lost me.  What does "acting on trailers only" really
> mean?

It means that the command can seen as processing only trailers, (from
stdin and from its arguments), sorry if I used the wrong verb.

> Do you mean the command should/can be run without any command
> line options, pick up the existing "Signed-off-by:" and friends in
> its input and emit its output, somehow taking these existing ones as
> its instruction regarding how to transform the input to its output?
>
>> And second there is also a practical advantage, as the user can
>> copy-paste trailers directly from other messages into the command line
>> to pass them as arguments to "git interpret-trailers" without the need
>> to replace the ':' with '='. Even if this command is not often used
>> directly by users, it might simplify scripts using it.
>>
>> Third there is a technical advantage which is that the code that
>> parses arguments from the command line can be the same as the code
>> that parses trailers from the input message.
> 
> I do not see these two as valid arguments to make the command line
> more complex to the end users

I don't think that it makes the command more complex to the end users.

> ---who now need to know that only this
> command treats its command line in a funny way, accepting a colon in
> place of an equal sign.

It accepts both. So if they think that it is like a regular command,
which uses '=' for (key, value) pairs, it will work, and if they think
it works on trailers, which use ':' for (key, value) pairs, it will
also work.

> A different way to sell a colon, e.g.
> 
> Consider the instruction sed takes on its command line.
> (e.g. "sed 's/frotz/nitfol/'  form, you would always give it as the value of an '-e' option
> (e.g. "sed -e 's/frotz/nitfol'  be loose in limited occassions.  "Key:value" is like that, and
> in the most general form, it actually needs to be spelled as
> "-e 'Key:value'".
> 
> is possible, but I do not think it is a particularly good analogy,
> because what you have as the alternative is "Key=value", and not
> "-e 'Key:value'", or "--Key=value" (the last would probably be the 
> most natural way to express this).

The analogy that I would use is rather that Perl lets people use
's:foo:bar:' as well as 's=foo=bar=' instead of 's/foo/bar/' if they
prefer.

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


Re: [PATCH] git-multimail: update to version 1.0.0

2014-04-07 Thread Junio C Hamano
Michael Haggerty  writes:

> ...
> Contributions-by: Raphaël Hertzog 
> Contributions-by: Eric Berberich 
> Contributions-by: Michiel Holtkamp 
> Contributions-by: Malte Swart 
> Signed-off-by: Michael Haggerty 
> ---
> Junio, how would you like other people's contributions to be recorded
> within the Git project?  I have listed them above as
> "Contributions-by".  All of these people have signed off on their
> contributions (recorded in my GitHub repo).  So should I also/instead
> add "Signed-off-by" for those people?

Either is fine, as long as somewhere in that directory:

 - we make it clear that the copy we have in contrib/ is merely for
   "batteries included" convenience;

 - we refer to the canonical source that is your repository;

 - we tell readers to go there to get the authoritative and up to
   date copy, as what we have in contrib/ is possibly stale.

In the longer term, I have a feeling that we may be better off to
make the "git core" tree not be the "batteris included" convenience
tree, though.  In the early days, Linus's rationale for including
"gitk" held true: having tools that are not quite core is a good way
to get people (especially those without C background) involved in
the still-small project in its infancy to help nurture the developer
community.  The same reasoning stood behind the merging of "gitweb".

We already are beyond that stage, and good tools like iMerge and
multimail that can stand on its own may be better off flourishing
outside "git core" tree, still within the same developer community.
--
To unsubscribe from this list: send the line "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 02/25] unable_to_lock_die(): rename function from unable_to_lock_index_die()

2014-04-07 Thread Jeff King
On Mon, Apr 07, 2014 at 01:33:44AM +0200, Michael Haggerty wrote:

> This function is used for other things besides the index, so rename it
> accordingly.

Oh, and here it is. I should really have just read ahead before
responding to patch 1.

We can either re-order these first two, or just not worry about 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 v2 01/25] api-lockfile: expand the documentation

2014-04-07 Thread Jeff King
On Mon, Apr 07, 2014 at 01:33:43AM +0200, Michael Haggerty wrote:

> +unable_to_lock_error::
> +
> + Emit an error describing that there was an error locking the
> + specified path.  The err parameter should be the errno of the
> + problem that caused the failure.
> +
> +unable_to_lock_die::
> +
> + Like `unable_to_lock_error()`, but also `die()`.

The die() function is still called unable_to_lock_index_die() at this
point in the series.  Presumably you change it later. I don't know if it
is worth caring about the order or not; it's a doc change, so it's not
like it breaks bisectability.

-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: The fetch command should "always" honor remote..fetch

2014-04-07 Thread Lewis Diamond
On Mon, Apr 7, 2014 at 2:23 PM, Junio C Hamano  wrote:
> Lewis Diamond  writes:
>
>> 'git fetch foo develop' would result in:
>> fatal: Couldn't find remote ref test2 //Not OK, (case 1)
>
> I have no idea where the "test2" comes from, as it does not appear
> anywhere in the above write-up, and it could be a bug.
>

Sorry, "test2" was a local test to copy the error message. It should read "foo".

>> 'git fetch foo master' would result in (FETCH_HEAD omitted):
>> [new ref] refs/heads/master -> foo/master //OK, but missing another
>> ref! (case 2)
>> //It should also fetch refs/users/bob/heads/master -> foo/bob/master
>
> This is an incorrect expectation.

Indeed this is the "correct" behaviour since it works as designed.
However, this behaviour is inconsistent with the push command. An
expectation is never "incorrect" as we are talking about intuitive vs
non-intuitive.

>
> The user who gave the command line said only "master", and did not
> want to grab "users/bob/heads/master".  If the user wanted to get it
> as well, the command line would have said so, e.g.
>
> git fetch there master users/bob/heads/master
>

Actually, the user specifically configured the remote to fetch
refs/users/bob/heads/*, meaning "those are the branches I'm interested
in".

>> If you remove this configuration line: fetch =
>> +refs/heads/*:refs/remotes/foo/*
>> Then you run 'git fetch foo master', this would result in:
>>  * branch master -> FETCH_HEAD //Debatable whether this is OK or not,
>> but it's definitely missing bob's master! (case 3)
>
> Likewise.
>
> The 'master' short-hand is designed not to match refs/users/any/thing.
>

Sure, this shorthand is designed to match refs listed in the rev parse
rules list. However, a quick survey showed me that most people would
expect their configuration to be honoured when using the shorthand for
fetching (like it is for push). This thread is about improving the
fetch command so that the short-hand works in such cases (and make it
consistent with what push does).
--
To unsubscribe from this list: send the line "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 v10 07/12] trailer: add interpret-trailers command

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

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

diff --git a/.gitignore b/.gitignore
index dc600f9..c2a0b19 100644
--- a/.gitignore
+++ b/.gitignore
@@ -74,6 +74,7 @@
 /git-index-pack
 /git-init
 /git-init-db
+/git-interpret-trailers
 /git-instaweb
 /git-log
 /git-ls-files
diff --git a/Makefile b/Makefile
index 179be0a..499ca30 100644
--- a/Makefile
+++ b/Makefile
@@ -944,6 +944,7 @@ BUILTIN_OBJS += builtin/hash-object.o
 BUILTIN_OBJS += builtin/help.o
 BUILTIN_OBJS += builtin/index-pack.o
 BUILTIN_OBJS += builtin/init-db.o
+BUILTIN_OBJS += builtin/interpret-trailers.o
 BUILTIN_OBJS += builtin/log.o
 BUILTIN_OBJS += builtin/ls-files.o
 BUILTIN_OBJS += builtin/ls-remote.o
diff --git a/builtin.h b/builtin.h
index c47c110..8ca0065 100644
--- a/builtin.h
+++ b/builtin.h
@@ -73,6 +73,7 @@ extern int cmd_hash_object(int argc, const char **argv, const 
char *prefix);
 extern int cmd_help(int argc, const char **argv, const char *prefix);
 extern int cmd_index_pack(int argc, const char **argv, const char *prefix);
 extern int cmd_init_db(int argc, const char **argv, const char *prefix);
+extern int cmd_interpret_trailers(int argc, const char **argv, const char 
*prefix);
 extern int cmd_log(int argc, const char **argv, const char *prefix);
 extern int cmd_log_reflog(int argc, const char **argv, const char *prefix);
 extern int cmd_ls_files(int argc, const char **argv, const char *prefix);
diff --git a/builtin/interpret-trailers.c b/builtin/interpret-trailers.c
new file mode 100644
index 000..0c8ca72
--- /dev/null
+++ b/builtin/interpret-trailers.c
@@ -0,0 +1,33 @@
+/*
+ * Builtin "git interpret-trailers"
+ *
+ * Copyright (c) 2013, 2014 Christian Couder 
+ *
+ */
+
+#include "cache.h"
+#include "builtin.h"
+#include "parse-options.h"
+#include "trailer.h"
+
+static const char * const git_interpret_trailers_usage[] = {
+   N_("git interpret-trailers [--trim-empty] 
[([(=|:)])...]"),
+   NULL
+};
+
+int cmd_interpret_trailers(int argc, const char **argv, const char *prefix)
+{
+   int trim_empty = 0;
+
+   struct option options[] = {
+   OPT_BOOL(0, "trim-empty", &trim_empty, N_("trim empty 
trailers")),
+   OPT_END()
+   };
+
+   argc = parse_options(argc, argv, prefix, options,
+git_interpret_trailers_usage, 0);
+
+   process_trailers(trim_empty, argc, argv);
+
+   return 0;
+}
diff --git a/git.c b/git.c
index 9efd1a3..d432f11 100644
--- a/git.c
+++ b/git.c
@@ -380,6 +380,7 @@ static struct cmd_struct commands[] = {
{ "index-pack", cmd_index_pack, RUN_SETUP_GENTLY },
{ "init", cmd_init_db },
{ "init-db", cmd_init_db },
+   { "interpret-trailers", cmd_interpret_trailers, RUN_SETUP },
{ "log", cmd_log, RUN_SETUP },
{ "ls-files", cmd_ls_files, RUN_SETUP },
{ "ls-remote", cmd_ls_remote, RUN_SETUP_GENTLY },
-- 
1.9.0.163.g8ca203c


--
To unsubscribe from this list: send the line "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 v10 02/12] trailer: process trailers from stdin and arguments

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

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

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

Signed-off-by: Christian Couder 
Signed-off-by: Junio C Hamano 
---
 trailer.c | 198 ++
 1 file changed, 198 insertions(+)

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

[PATCH v10 01/12] trailer: add data structures and basic functions

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

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

Signed-off-by: Christian Couder 
Signed-off-by: Junio C Hamano 
---
 Makefile  |  1 +
 trailer.c | 49 +
 2 files changed, 50 insertions(+)
 create mode 100644 trailer.c

diff --git a/Makefile b/Makefile
index c5316a3..179be0a 100644
--- a/Makefile
+++ b/Makefile
@@ -879,6 +879,7 @@ LIB_OBJS += submodule.o
 LIB_OBJS += symlinks.o
 LIB_OBJS += tag.o
 LIB_OBJS += trace.o
+LIB_OBJS += trailer.o
 LIB_OBJS += transport.o
 LIB_OBJS += transport-helper.o
 LIB_OBJS += tree-diff.o
diff --git a/trailer.c b/trailer.c
new file mode 100644
index 000..db93a63
--- /dev/null
+++ b/trailer.c
@@ -0,0 +1,49 @@
+#include "cache.h"
+/*
+ * Copyright (c) 2013, 2014 Christian Couder 
+ */
+
+enum action_where { WHERE_AFTER, WHERE_BEFORE };
+enum action_if_exists { EXISTS_ADD_IF_DIFFERENT, 
EXISTS_ADD_IF_DIFFERENT_NEIGHBOR,
+   EXISTS_ADD, EXISTS_OVERWRITE, EXISTS_DO_NOTHING };
+enum action_if_missing { MISSING_ADD, MISSING_DO_NOTHING };
+
+struct conf_info {
+   char *name;
+   char *key;
+   char *command;
+   enum action_where where;
+   enum action_if_exists if_exists;
+   enum action_if_missing if_missing;
+};
+
+struct trailer_item {
+   struct trailer_item *previous;
+   struct trailer_item *next;
+   const char *token;
+   const char *value;
+   struct conf_info conf;
+};
+
+static int same_token(struct trailer_item *a, struct trailer_item *b, int 
alnum_len)
+{
+   return !strncasecmp(a->token, b->token, alnum_len);
+}
+
+static int same_value(struct trailer_item *a, struct trailer_item *b)
+{
+   return !strcasecmp(a->value, b->value);
+}
+
+static int same_trailer(struct trailer_item *a, struct trailer_item *b, int 
alnum_len)
+{
+   return same_token(a, b, alnum_len) && same_value(a, b);
+}
+
+/* Get the length of buf from its beginning until its last alphanumeric 
character */
+static size_t alnum_len(const char *buf, size_t len)
+{
+   while (len > 0 && !isalnum(buf[len - 1]))
+   len--;
+   return len;
+}
-- 
1.9.0.163.g8ca203c


--
To unsubscribe from this list: send the line "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 v10 08/12] trailer: add tests for "git interpret-trailers"

2014-04-07 Thread Christian Couder
Signed-off-by: Christian Couder 
Signed-off-by: Junio C Hamano 
---
 t/t7513-interpret-trailers.sh | 351 ++
 1 file changed, 351 insertions(+)
 create mode 100755 t/t7513-interpret-trailers.sh

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

[PATCH v10 04/12] trailer: process command line trailer arguments

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

Signed-off-by: Christian Couder 
Signed-off-by: Junio C Hamano 
---
 trailer.c | 117 ++
 1 file changed, 117 insertions(+)

diff --git a/trailer.c b/trailer.c
index c7c0f54..89ebff1 100644
--- a/trailer.c
+++ b/trailer.c
@@ -391,3 +391,120 @@ static int git_trailer_config(const char *conf_key, const 
char *value, void *cb)
}
return 0;
 }
+
+static int parse_trailer(struct strbuf *tok, struct strbuf *val, const char 
*trailer)
+{
+   size_t len = strcspn(trailer, "=:");
+   if (len == 0)
+   return error(_("empty trailer token in trailer '%s'"), trailer);
+   if (len < strlen(trailer)) {
+   strbuf_add(tok, trailer, len);
+   strbuf_trim(tok);
+   strbuf_addstr(val, trailer + len + 1);
+   strbuf_trim(val);
+   } else {
+   strbuf_addstr(tok, trailer);
+   strbuf_trim(tok);
+   }
+   return 0;
+}
+
+
+static void duplicate_conf(struct conf_info *dst, struct conf_info *src)
+{
+   *dst = *src;
+   if (src->name)
+   dst->name = xstrdup(src->name);
+   if (src->key)
+   dst->key = xstrdup(src->key);
+   if (src->command)
+   dst->command = xstrdup(src->command);
+}
+
+static const char *token_from_item(struct trailer_item *item)
+{
+   if (item->conf.key)
+   return item->conf.key;
+
+   return item->conf.name;
+}
+
+static struct trailer_item *new_trailer_item(struct trailer_item *conf_item,
+char *tok, char *val)
+{
+   struct trailer_item *new = xcalloc(sizeof(*new), 1);
+   new->value = val;
+
+   if (conf_item) {
+   duplicate_conf(&new->conf, &conf_item->conf);
+   new->token = xstrdup(token_from_item(conf_item));
+   free(tok);
+   } else
+   new->token = tok;
+
+   return new;
+}
+
+static int token_matches_item(const char *tok, struct trailer_item *item, int 
alnum_len)
+{
+   if (!strncasecmp(tok, item->conf.name, alnum_len))
+   return 1;
+   return item->conf.key ? !strncasecmp(tok, item->conf.key, alnum_len) : 
0;
+}
+
+static struct trailer_item *create_trailer_item(const char *string)
+{
+   struct strbuf tok = STRBUF_INIT;
+   struct strbuf val = STRBUF_INIT;
+   struct trailer_item *item;
+   int tok_alnum_len;
+
+   if (parse_trailer(&tok, &val, string))
+   return NULL;
+
+   tok_alnum_len = alnum_len(tok.buf, tok.len);
+
+   /* Lookup if the token matches something in the config */
+   for (item = first_conf_item; item; item = item->next) {
+   if (token_matches_item(tok.buf, item, tok_alnum_len)) {
+   strbuf_release(&tok);
+   return new_trailer_item(item,
+   NULL,
+   strbuf_detach(&val, NULL));
+   }
+   }
+
+   return new_trailer_item(NULL,
+   strbuf_detach(&tok, NULL),
+   strbuf_detach(&val, NULL));
+}
+
+static void add_trailer_item(struct trailer_item **first,
+struct trailer_item **last,
+struct trailer_item *new)
+{
+   if (!new)
+   return;
+   if (!*last) {
+   *first = new;
+   *last = new;
+   } else {
+   (*last)->next = new;
+   new->previous = *last;
+   *last = new;
+   }
+}
+
+static struct trailer_item *process_command_line_args(int argc, const char 
**argv)
+{
+   int i;
+   struct trailer_item *arg_tok_first = NULL;
+   struct trailer_item *arg_tok_last = NULL;
+
+   for (i = 0; i < argc; i++) {
+   struct trailer_item *new = create_trailer_item(argv[i]);
+   add_trailer_item(&arg_tok_first, &arg_tok_last, new);
+   }
+
+   return arg_tok_first;
+}
-- 
1.9.0.163.g8ca203c


--
To unsubscribe from this list: send the line "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 v10 10/12] trailer: add tests for commands in config file

2014-04-07 Thread Christian Couder
And add a few other tests for some special cases.

Signed-off-by: Christian Couder 
Signed-off-by: Junio C Hamano 
---
 t/t7513-interpret-trailers.sh | 116 ++
 1 file changed, 116 insertions(+)

diff --git a/t/t7513-interpret-trailers.sh b/t/t7513-interpret-trailers.sh
index 0e5d57f..262f7bf 100755
--- a/t/t7513-interpret-trailers.sh
+++ b/t/t7513-interpret-trailers.sh
@@ -348,4 +348,120 @@ test_expect_success 'using "ifMissing = doNothing"' '
test_cmp expected actual
 '
 
+test_expect_success 'with simple command' '
+   git config trailer.sign.key "Signed-off-by: " &&
+   git config trailer.sign.where "after" &&
+   git config trailer.sign.ifExists "addIfDifferentNeighbor" &&
+   git config trailer.sign.command "echo \"A U Thor 
\"" &&
+   cat complex_message_body >expected &&
+   sed -e "s/ Z\$/ /" >>expected <<-\EOF &&
+   Fixes: Z
+   Acked-by= Z
+   Reviewed-by: Z
+   Signed-off-by: Z
+   Signed-off-by: A U Thor 
+   EOF
+   git interpret-trailers "review:" "fix=22" actual &&
+   test_cmp expected actual
+'
+
+test_expect_success 'with command using commiter information' '
+   git config trailer.sign.ifExists "addIfDifferent" &&
+   git config trailer.sign.command "echo \"\$GIT_COMMITTER_NAME 
<\$GIT_COMMITTER_EMAIL>\"" &&
+   cat complex_message_body >expected &&
+   sed -e "s/ Z\$/ /" >>expected <<-\EOF &&
+   Fixes: Z
+   Acked-by= Z
+   Reviewed-by: Z
+   Signed-off-by: Z
+   Signed-off-by: C O Mitter 
+   EOF
+   git interpret-trailers "review:" "fix=22" actual &&
+   test_cmp expected actual
+'
+
+test_expect_success 'with command using author information' '
+   git config trailer.sign.key "Signed-off-by: " &&
+   git config trailer.sign.where "after" &&
+   git config trailer.sign.ifExists "addIfDifferentNeighbor" &&
+   git config trailer.sign.command "echo \"\$GIT_AUTHOR_NAME 
<\$GIT_AUTHOR_EMAIL>\"" &&
+   cat complex_message_body >expected &&
+   sed -e "s/ Z\$/ /" >>expected <<-\EOF &&
+   Fixes: Z
+   Acked-by= Z
+   Reviewed-by: Z
+   Signed-off-by: Z
+   Signed-off-by: A U Thor 
+   EOF
+   git interpret-trailers "review:" "fix=22" actual &&
+   test_cmp expected actual
+'
+
+test_expect_success 'setup a commit' '
+   echo "Content of the first commit." > a.txt &&
+   git add a.txt &&
+   git commit -m "Add file a.txt"
+'
+
+test_expect_success 'with command using $ARG' '
+   git config trailer.fix.ifExists "overwrite" &&
+   git config trailer.fix.command "git log -1 --oneline --format=\"%h 
(%s)\" --abbrev-commit --abbrev=14 \$ARG" &&
+   FIXED=$(git log -1 --oneline --format="%h (%s)" --abbrev-commit 
--abbrev=14 HEAD) &&
+   cat complex_message_body >expected &&
+   sed -e "s/ Z\$/ /" >>expected <<-EOF &&
+   Fixes: $FIXED
+   Acked-by= Z
+   Reviewed-by: Z
+   Signed-off-by: Z
+   Signed-off-by: A U Thor 
+   EOF
+   git interpret-trailers "review:" "fix=HEAD" actual &&
+   test_cmp expected actual
+'
+
+test_expect_success 'with failing command using $ARG' '
+   git config trailer.fix.ifExists "overwrite" &&
+   git config trailer.fix.command "false \$ARG" &&
+   cat complex_message_body >expected &&
+   sed -e "s/ Z\$/ /" >>expected <<-EOF &&
+   Fixes: Z
+   Acked-by= Z
+   Reviewed-by: Z
+   Signed-off-by: Z
+   Signed-off-by: A U Thor 
+   EOF
+   git interpret-trailers "review:" "fix=HEAD" actual &&
+   test_cmp expected actual
+'
+
+test_expect_success 'with empty tokens' '
+   cat >expected <<-EOF &&
+   Signed-off-by: A U Thor 
+   EOF
+   git interpret-trailers ":" ":test" >actual <<-EOF &&
+   EOF
+   test_cmp expected actual
+'
+
+test_expect_success 'with command but no key' '
+   git config --unset trailer.sign.key &&
+   cat >expected <<-EOF &&
+   sign: A U Thor 
+   EOF
+   git interpret-trailers >actual <<-EOF &&
+   EOF
+   test_cmp expected actual
+'
+
+test_expect_success 'with no command and no key' '
+   git config --unset trailer.review.key &&
+   cat >expected <<-EOF &&
+   review: Junio
+   sign: A U Thor 
+   EOF
+   git interpret-trailers "review:Junio" >actual <<-EOF &&
+   EOF
+   test_cmp expected actual
+'
+
 test_done
-- 
1.9.0.163.g8ca203c


--
To unsubscribe from this list: send the line "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 v10 09/12] trailer: execute command from 'trailer..command'

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

Signed-off-by: Christian Couder 
Signed-off-by: Junio C Hamano 
---
 trailer.c | 64 +++
 1 file changed, 64 insertions(+)

diff --git a/trailer.c b/trailer.c
index 16465e5..09db2c2 100644
--- a/trailer.c
+++ b/trailer.c
@@ -1,4 +1,5 @@
 #include "cache.h"
+#include "run-command.h"
 #include "trailer.h"
 /*
  * Copyright (c) 2013, 2014 Christian Couder 
@@ -13,11 +14,14 @@ struct conf_info {
char *name;
char *key;
char *command;
+   unsigned command_uses_arg : 1;
enum action_where where;
enum action_if_exists if_exists;
enum action_if_missing if_missing;
 };
 
+#define TRAILER_ARG_STRING "$ARG"
+
 struct trailer_item {
struct trailer_item *previous;
struct trailer_item *next;
@@ -59,6 +63,13 @@ static inline int contains_only_spaces(const char *str)
return !*s;
 }
 
+static inline void strbuf_replace(struct strbuf *sb, const char *a, const char 
*b)
+{
+   const char *ptr = strstr(sb->buf, a);
+   if (ptr)
+   strbuf_splice(sb, ptr - sb->buf, strlen(a), b, strlen(b));
+}
+
 static void free_trailer_item(struct trailer_item *item)
 {
free(item->conf.name);
@@ -402,6 +413,7 @@ static int git_trailer_config(const char *conf_key, const 
char *value, void *cb)
if (conf->command)
warning(_("more than one %s"), conf_key);
conf->command = xstrdup(value);
+   conf->command_uses_arg = !!strstr(conf->command, 
TRAILER_ARG_STRING);
break;
case TRAILER_WHERE:
if (set_where(conf, value))
@@ -438,6 +450,45 @@ static int parse_trailer(struct strbuf *tok, struct strbuf 
*val, const char *tra
return 0;
 }
 
+static int read_from_command(struct child_process *cp, struct strbuf *buf)
+{
+   if (run_command(cp))
+   return error("running trailer command '%s' failed", 
cp->argv[0]);
+   if (strbuf_read(buf, cp->out, 1024) < 1)
+   return error("reading from trailer command '%s' failed", 
cp->argv[0]);
+   strbuf_trim(buf);
+   return 0;
+}
+
+static const char *apply_command(const char *command, const char *arg)
+{
+   struct strbuf cmd = STRBUF_INIT;
+   struct strbuf buf = STRBUF_INIT;
+   struct child_process cp;
+   const char *argv[] = {NULL, NULL};
+   const char *result;
+
+   strbuf_addstr(&cmd, command);
+   if (arg)
+   strbuf_replace(&cmd, TRAILER_ARG_STRING, arg);
+
+   argv[0] = cmd.buf;
+   memset(&cp, 0, sizeof(cp));
+   cp.argv = argv;
+   cp.env = local_repo_env;
+   cp.no_stdin = 1;
+   cp.out = -1;
+   cp.use_shell = 1;
+
+   if (read_from_command(&cp, &buf)) {
+   strbuf_release(&buf);
+   result = xstrdup("");
+   } else
+   result = strbuf_detach(&buf, NULL);
+
+   strbuf_release(&cmd);
+   return result;
+}
 
 static void duplicate_conf(struct conf_info *dst, struct conf_info *src)
 {
@@ -468,6 +519,10 @@ static struct trailer_item *new_trailer_item(struct 
trailer_item *conf_item,
duplicate_conf(&new->conf, &conf_item->conf);
new->token = xstrdup(token_from_item(conf_item));
free(tok);
+   if (conf_item->conf.command_uses_arg || !val) {
+   new->value = apply_command(conf_item->conf.command, 
val);
+   free(val);
+   }
} else
new->token = tok;
 
@@ -529,12 +584,21 @@ static struct trailer_item *process_command_line_args(int 
argc, const char **arg
int i;
struct trailer_item *arg_tok_first = NULL;
struct trailer_item *arg_tok_last = NULL;
+   struct trailer_item *item;
 
for (i = 0; i < argc; i++) {
struct trailer_item *new = create_trailer_item(argv[i]);
add_trailer_item(&arg_tok_first, &arg_tok_last, new);
}
 
+   /* Add conf commands that don't use $ARG */
+   for (item = first_conf_item; item; item = item->next) {
+   if (item->conf.command && !item->conf.command_uses_arg) {
+   struct trailer_item *new = new_trailer_item(item, NULL, 
NULL);
+   add_trailer_item(&arg_tok_first, &arg_tok_last, new);
+   }
+   }
+
return arg_tok_first;
 }
 
-- 
1.9.0.163.g8ca203c


--
To unsubscribe from this list: send the line "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 v10 12/12] trailer: add blank line before the trailers if needed

2014-04-07 Thread Christian Couder
Signed-off-by: Christian Couder 
---
 t/t7513-interpret-trailers.sh | 12 +++-
 trailer.c | 26 ++
 2 files changed, 29 insertions(+), 9 deletions(-)

diff --git a/t/t7513-interpret-trailers.sh b/t/t7513-interpret-trailers.sh
index 262f7bf..44a7131 100755
--- a/t/t7513-interpret-trailers.sh
+++ b/t/t7513-interpret-trailers.sh
@@ -34,6 +34,7 @@ test_expect_success 'setup' '
 
 test_expect_success 'without config' '
sed -e "s/ Z\$/ /" >expected <<-\EOF &&
+
ack: Peff
Reviewed-by: Z
Acked-by: Johan
@@ -44,6 +45,7 @@ test_expect_success 'without config' '
 
 test_expect_success '--trim-empty without config' '
cat >expected <<-\EOF &&
+
ack: Peff
Acked-by: Johan
EOF
@@ -55,6 +57,7 @@ test_expect_success '--trim-empty without config' '
 test_expect_success 'with config setup' '
git config trailer.ack.key "Acked-by: " &&
cat >expected <<-\EOF &&
+
Acked-by: Peff
EOF
git interpret-trailers --trim-empty "ack = Peff" >actual &&
@@ -68,6 +71,7 @@ test_expect_success 'with config setup' '
 test_expect_success 'with config setup and = sign' '
git config trailer.ack.key "Acked-by= " &&
cat >expected <<-\EOF &&
+
Acked-by= Peff
EOF
git interpret-trailers --trim-empty "ack = Peff" >actual &&
@@ -81,6 +85,7 @@ test_expect_success 'with config setup and = sign' '
 test_expect_success 'with config setup and # sign' '
git config trailer.bug.key "Bug #" &&
cat >expected <<-\EOF &&
+
Bug #42
EOF
git interpret-trailers --trim-empty "bug = 42" >actual &&
@@ -88,8 +93,10 @@ test_expect_success 'with config setup and # sign' '
 '
 
 test_expect_success 'with commit basic message' '
+   cat basic_message >expected &&
+   echo >>expected &&
git interpret-trailers actual &&
-   test_cmp basic_message actual
+   test_cmp expected actual
 '
 
 test_expect_success 'with commit complex message' '
@@ -436,6 +443,7 @@ test_expect_success 'with failing command using $ARG' '
 
 test_expect_success 'with empty tokens' '
cat >expected <<-EOF &&
+
Signed-off-by: A U Thor 
EOF
git interpret-trailers ":" ":test" >actual <<-EOF &&
@@ -446,6 +454,7 @@ test_expect_success 'with empty tokens' '
 test_expect_success 'with command but no key' '
git config --unset trailer.sign.key &&
cat >expected <<-EOF &&
+
sign: A U Thor 
EOF
git interpret-trailers >actual <<-EOF &&
@@ -456,6 +465,7 @@ test_expect_success 'with command but no key' '
 test_expect_success 'with no command and no key' '
git config --unset trailer.review.key &&
cat >expected <<-EOF &&
+
review: Junio
sign: A U Thor 
EOF
diff --git a/trailer.c b/trailer.c
index 09db2c2..639f657 100644
--- a/trailer.c
+++ b/trailer.c
@@ -618,12 +618,14 @@ static struct strbuf **read_stdin(void)
 }
 
 /*
- * Return the the (0 based) index of the first trailer line
+ * Return the (0 based) index of the first trailer line
  * or the line count if there are no trailers.
+ * The has_blank_line parameter tells if there is a blank
+ * line before the trailers.
  */
-static int find_trailer_start(struct strbuf **lines)
+static int find_trailer_start(struct strbuf **lines, int *has_blank_line)
 {
-   int start, empty = 1, count = 0;
+   int start, only_spaces = 1, count = 0;
 
/* Get the line count */
while (lines[count])
@@ -635,32 +637,40 @@ static int find_trailer_start(struct strbuf **lines)
 */
for (start = count - 1; start >= 0; start--) {
if (contains_only_spaces(lines[start]->buf)) {
-   if (empty)
+   if (only_spaces)
continue;
+   *has_blank_line = 1;
return start + 1;
}
if (strchr(lines[start]->buf, ':')) {
-   if (empty)
-   empty = 0;
+   if (only_spaces)
+   only_spaces = 0;
continue;
}
+   *has_blank_line = start == count - 1 ?
+ 0 : contains_only_spaces(lines[start + 1]->buf);
return count;
}
 
-   return empty ? count : start + 1;
+   *has_blank_line = only_spaces ? count > 0 : 0;
+   return only_spaces ? count : start + 1;
 }
 
 static void process_stdin(struct trailer_item **in_tok_first,
  struct trailer_item **in_tok_last)
 {
struct strbuf **lines = read_stdin();
-   int start = find_trailer_start(lines);
+   int has_blank_line;
+   int start = find_trailer_start(lines, &has_blank_line);
int

[PATCH v10 05/12] trailer: parse trailers from stdin

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

Signed-off-by: Christian Couder 
Signed-off-by: Junio C Hamano 
---
 trailer.c | 76 +++
 1 file changed, 76 insertions(+)

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


--
To unsubscribe from this list: send the line "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 v10 03/12] trailer: read and process config information

2014-04-07 Thread Christian Couder
Read the configuration to get trailer information, and then process
it and storing it in a doubly linked list.

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

static struct trailer_item *first_conf_item;

Signed-off-by: Christian Couder 
Signed-off-by: Junio C Hamano 
---
 trailer.c | 146 ++
 1 file changed, 146 insertions(+)

diff --git a/trailer.c b/trailer.c
index 52108c2..c7c0f54 100644
--- a/trailer.c
+++ b/trailer.c
@@ -25,6 +25,8 @@ struct trailer_item {
struct conf_info conf;
 };
 
+static struct trailer_item *first_conf_item;
+
 static int same_token(struct trailer_item *a, struct trailer_item *b, int 
alnum_len)
 {
return !strncasecmp(a->token, b->token, alnum_len);
@@ -245,3 +247,147 @@ static void process_trailers_lists(struct trailer_item 
**in_tok_first,
apply_arg_if_missing(in_tok_first, in_tok_last, arg_tok);
}
 }
+
+static int set_where(struct conf_info *item, const char *value)
+{
+   if (!strcmp("after", value))
+   item->where = WHERE_AFTER;
+   else if (!strcmp("before", value))
+   item->where = WHERE_BEFORE;
+   else
+   return -1;
+   return 0;
+}
+
+static int set_if_exists(struct conf_info *item, const char *value)
+{
+   if (!strcmp("addIfDifferent", value))
+   item->if_exists = EXISTS_ADD_IF_DIFFERENT;
+   else if (!strcmp("addIfDifferentNeighbor", value))
+   item->if_exists = EXISTS_ADD_IF_DIFFERENT_NEIGHBOR;
+   else if (!strcmp("add", value))
+   item->if_exists = EXISTS_ADD;
+   else if (!strcmp("overwrite", value))
+   item->if_exists = EXISTS_OVERWRITE;
+   else if (!strcmp("doNothing", value))
+   item->if_exists = EXISTS_DO_NOTHING;
+   else
+   return -1;
+   return 0;
+}
+
+static int set_if_missing(struct conf_info *item, const char *value)
+{
+   if (!strcmp("doNothing", value))
+   item->if_missing = MISSING_DO_NOTHING;
+   else if (!strcmp("add", value))
+   item->if_missing = MISSING_ADD;
+   else
+   return -1;
+   return 0;
+}
+
+static struct trailer_item *get_conf_item(const char *name)
+{
+   struct trailer_item *item;
+   struct trailer_item *previous;
+
+   /* Look up item with same name */
+   for (previous = NULL, item = first_conf_item;
+item;
+previous = item, item = item->next) {
+   if (!strcasecmp(item->conf.name, name))
+   return item;
+   }
+
+   /* Item does not already exists, create it */
+   item = xcalloc(sizeof(struct trailer_item), 1);
+   item->conf.name = xstrdup(name);
+
+   if (!previous)
+   first_conf_item = item;
+   else {
+   previous->next = item;
+   item->previous = previous;
+   }
+
+   return item;
+}
+
+enum trailer_info_type { TRAILER_KEY, TRAILER_COMMAND, TRAILER_WHERE,
+TRAILER_IF_EXISTS, TRAILER_IF_MISSING };
+
+static struct {
+   const char *name;
+   enum trailer_info_type type;
+} trailer_config_items[] = {
+   { "key", TRAILER_KEY },
+   { "command", TRAILER_COMMAND },
+   { "where", TRAILER_WHERE },
+   { "ifexists", TRAILER_IF_EXISTS },
+   { "ifmissing", TRAILER_IF_MISSING }
+};
+
+static int git_trailer_config(const char *conf_key, const char *value, void 
*cb)
+{
+   const char *trailer_item, *variable_name;
+   struct trailer_item *item;
+   struct conf_info *conf;
+   char *name = NULL;
+   enum trailer_info_type type;
+   int i;
+
+   trailer_item = skip_prefix(conf_key, "trailer.");
+   if (!trailer_item)
+   return 0;
+
+   variable_name = strrchr(trailer_item, '.');
+   if (!variable_name) {
+   warning(_("two level trailer config variable %s"), conf_key);
+   return 0;
+   }
+
+   variable_name++;
+   for (i = 0; i < ARRAY_SIZE(trailer_config_items); i++) {
+   if (strcmp(trailer_config_items[i].name, variable_name))
+   continue;
+   name = xstrndup(trailer_item,  variable_name - trailer_item - 
1);
+   type = trailer_config_items[i].type;
+   break;
+   }
+
+   if (!name)
+   return 0;
+
+   item = get_conf_item(name);
+   conf = &item->conf;
+   free(name);
+
+   switch (type) {
+   case TRAILER_KEY:
+   if (conf->key)
+   warning(_("more than one %s"), conf_key);
+   conf->key = xstrdup(value);
+   break;
+   case TRAILER_COMMAND:
+   if (conf->command)
+   warning(_("more than one %s"), conf_key);
+   conf->command = xstrdup(value);
+   break;
+   case TRAILER_WHERE:
+

[PATCH v10 11/12] Documentation: add documentation for 'git interpret-trailers'

2014-04-07 Thread Christian Couder
Signed-off-by: Christian Couder 
Signed-off-by: Junio C Hamano 
---
 Documentation/git-interpret-trailers.txt | 123 +++
 1 file changed, 123 insertions(+)
 create mode 100644 Documentation/git-interpret-trailers.txt

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

[PATCH v10 06/12] trailer: put all the processing together and print

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

Signed-off-by: Christian Couder 
Signed-off-by: Junio C Hamano 
---
 trailer.c | 49 +
 trailer.h |  6 ++
 2 files changed, 55 insertions(+)
 create mode 100644 trailer.h

diff --git a/trailer.c b/trailer.c
index 6d2da32..16465e5 100644
--- a/trailer.c
+++ b/trailer.c
@@ -1,4 +1,5 @@
 #include "cache.h"
+#include "trailer.h"
 /*
  * Copyright (c) 2013, 2014 Christian Couder 
  */
@@ -68,6 +69,26 @@ static void free_trailer_item(struct trailer_item *item)
free(item);
 }
 
+static void print_tok_val(const char *tok, const char *val)
+{
+   char c = tok[strlen(tok) - 1];
+   if (isalnum(c))
+   printf("%s: %s\n", tok, val);
+   else if (isspace(c) || c == '#')
+   printf("%s%s\n", tok, val);
+   else
+   printf("%s %s\n", tok, val);
+}
+
+static void print_all(struct trailer_item *first, int trim_empty)
+{
+   struct trailer_item *item;
+   for (item = first; item; item = item->next) {
+   if (!trim_empty || strlen(item->value) > 0)
+   print_tok_val(item->token, item->value);
+   }
+}
+
 static void add_arg_to_input_list(struct trailer_item *in_tok,
  struct trailer_item *arg_tok)
 {
@@ -584,3 +605,31 @@ static void process_stdin(struct trailer_item 
**in_tok_first,
 
strbuf_list_free(lines);
 }
+
+static void free_all(struct trailer_item **first)
+{
+   while (*first) {
+   struct trailer_item *item = remove_first(first);
+   free_trailer_item(item);
+   }
+}
+
+void process_trailers(int trim_empty, int argc, const char **argv)
+{
+   struct trailer_item *in_tok_first = NULL;
+   struct trailer_item *in_tok_last = NULL;
+   struct trailer_item *arg_tok_first;
+
+   git_config(git_trailer_config, NULL);
+
+   /* Print the non trailer part of stdin */
+   process_stdin(&in_tok_first, &in_tok_last);
+
+   arg_tok_first = process_command_line_args(argc, argv);
+
+   process_trailers_lists(&in_tok_first, &in_tok_last, &arg_tok_first);
+
+   print_all(in_tok_first, trim_empty);
+
+   free_all(&in_tok_first);
+}
diff --git a/trailer.h b/trailer.h
new file mode 100644
index 000..9323b1e
--- /dev/null
+++ b/trailer.h
@@ -0,0 +1,6 @@
+#ifndef TRAILER_H
+#define TRAILER_H
+
+void process_trailers(int trim_empty, int argc, const char **argv);
+
+#endif /* TRAILER_H */
-- 
1.9.0.163.g8ca203c


--
To unsubscribe from this list: send the line "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 v10 00/12] Add interpret-trailers builtin

2014-04-07 Thread Christian Couder
This patch series implements a new command:

git interpret-trailers

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

1) Rationale:

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

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

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

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

It is better to keep builtin/commit.c uncontaminated by any more
hard-wired logic, like what we have for the signed-off-by line.  Any
new things can and should be doable in hooks, and this filter would
help writing these hooks.

And that is why the design goal of the filter is to make it at least
as powerful as the built-in logic we have for signed-off-by lines;
that would allow us to later eject the hard-wired logic for
signed-off-by line from the main codepath, if/when we wanted to.

Alternatively, we could build a library-ish API around this filter
code and replace the hard-wired logic for signed-off-by line with a
call into that API, if/when we wanted to, but that requires (in
addition to the "at least as powerful as the built-in logic") that
the implementation of this stand-alone filter can be cleanly made
into a reusable library, so that is a bit higher bar to cross than
"everything can be doable with hooks" alternative.

2) Current state:

Currently the usage string of this command is:

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

The following features are implemented:

- the result is printed on stdout
- the [[=]>] arguments are interpreted
- a commit message read from stdin is interpreted
- the "trailer..key" options in the config are interpreted
- the "trailer..where" options are interpreted
- the "trailer..ifExist" options are interpreted
- the "trailer..ifMissing" options are interpreted
- the "trailer..command" config works
- $ARG can be used in commands
- there are 31 tests (4 more than in version 9)
- there is some documentation

The following features are planned but not yet implemented:
- add examples in documentation

Possible improvements:
- integration with "git commit"
- support GIT_COMMIT_PROTO env variable in commands

3) Changes since version 9, thanks to Jonathan and Junio:

* added 1 test with empty trailers in patch 10/12
* fixed bugs when there was no 'key' in the config in patch
  4/12 and added 2 related tests in patch 10/12
* fixed bug when command failed in patch 9/12 and added 1
  related test in patch 10/12
* added patch 12/12 which add one blank line before the
  trailers if there is not one already

This means code changes only in patches 4/12, 9/12, 10/12
and 12/12.


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

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

-- 
1.9.0.163.g8ca203c

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


Re: What's cooking in git.git (Apr 2014, #01; Fri, 4)

2014-04-07 Thread Johannes Sixt
Am 05.04.2014 11:19, schrieb Johannes Sixt:
> Am 04.04.2014 22:58, schrieb Junio C Hamano:
>> * sz/mingw-index-pack-threaded (2014-03-19) 1 commit
>>  - Enable index-pack threading in msysgit.
>>
>>  What is the status of this topic?  A failure report exists
>>  ($gmane/245170), and I am aware of Duy's $gmane/245034 but that was
>>  where the discussion stalled.  Is everybody waiting for everybody
>>  else to get the discussion unstuck?
> 
> I still have to cross-check Duy's patch. I'll hopefully get to it in the
> next days and report back.

The test suite passes with Duy's patch ($gmane/245034), but t5302 fails
with this patch with a MinGW build. The patches touch the Cygwin
configuration, but I cannot test a Cygwin build.

I have, however, lost track of what the objective of these patches is.
Is the threaded version significantly faster, and these patches are
worth it?

-- Hannes

--
To unsubscribe from this list: send the line "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: The fetch command should "always" honor remote..fetch

2014-04-07 Thread Junio C Hamano
Lewis Diamond  writes:

> 'git fetch foo develop' would result in:
> fatal: Couldn't find remote ref test2 //Not OK, (case 1)

I have no idea where the "test2" comes from, as it does not appear
anywhere in the above write-up, and it could be a bug.

> 'git fetch foo master' would result in (FETCH_HEAD omitted):
> [new ref] refs/heads/master -> foo/master //OK, but missing another
> ref! (case 2)
> //It should also fetch refs/users/bob/heads/master -> foo/bob/master

This is an incorrect expectation.

The user who gave the command line said only "master", and did not
want to grab "users/bob/heads/master".  If the user wanted to get it
as well, the command line would have said so, e.g.

git fetch there master users/bob/heads/master

> If you remove this configuration line: fetch =
> +refs/heads/*:refs/remotes/foo/*
> Then you run 'git fetch foo master', this would result in:
>  * branch master -> FETCH_HEAD //Debatable whether this is OK or not,
> but it's definitely missing bob's master! (case 3)

Likewise.

The 'master' short-hand is designed not to match refs/users/any/thing.

--
To unsubscribe from this list: send the line "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 18/19] tree-diff: rework diff_tree() to generate diffs for multiparent cases as well

2014-04-07 Thread Junio C Hamano
Kirill Smelkov  writes:

>> > +  if (!DIFF_OPT_TST(opt, FIND_COPIES_HARDER)) {
>> > +  for (i = 0; i < nparent; ++i)
>> > +  if (tp[i].entry.mode & S_IFXMIN_NEQ)
>> > +  goto skip_emit_tp;
>> > +  }
>> > +
>> > +  p = emit_path(p, base, opt, nparent,
>> > +  /*t=*/NULL, tp, imin);
>> > +
>> > +  skip_emit_tp:
>> > +  /* ∀ xk=ximin  xk↓ */
>> > +  update_tp_entries(tp, nparent);
>> 
>> There are parents whose path sort earlier than what is in 't'
>> (i.e. they were lost in the result---we would want to show
>> removal).  What makes us jump to the skip label?
>> 
>> We are looking at path in 't', and some parents have paths that
>> sort earlier than that path.  We will not go to skip label if
>> any one of the parent's entry sorts after some other parent (or
>> the parent in question has ran out its entries), which means we
>> show the entry from the parents only when all the parents have
>> that same path, which is missing from 't'.
>> 
>> I am not sure if I am reading this correctly, though.
>> 
>> For the two-way diff, the above degenerates to "show all parent
>> entries that come before the first entry in 't'", which is correct.
>> For the combined diff, the current intersect_paths() makes sure that
>> each path appears in all the pair-wise diff between t and tp[],
>> which again means that the above logic match the current behaviour.
>
> Yes, correct (modulo we *will* go to skip label if any one of the
> parent's entry sorts after some other parent). By definition of combined
> diff we show a path only if it shows in every diff D(T,Pi), and if 
>
> 2.1) ∃j: pj > p[imin]  ->  "-p[imin]" ∉ D(T,Pj)  ->  D += ø;  ∀ 
> pi=p[imin]  pi↓
>
> some pj sorts after p[imin] that would mean that Pj does not have
> p[imin] and since t > p[imin] (which means T does not have p[imin]
> either) diff D(T,Pj) does not have p[imin]. And because of that we know
> the whole combined-diff will not have p[imin] as, by definition,
> combined diff is sets intersection and one of the sets does not have
> that path.
>
>   ( In usual words p[imin] is not changed between Pj..T - it was
> e.g. removed in Pj~, so merging parents to T does not bring any new
> information wrt path p[imin] and that is why we do not want to show
> p[imin] in combined-diff output - no new change about that path )
>
> So nothing to append to the output, and update minimum tree entries,
> preparing for the next step.

That's all in line with the current and traditional definition of
combined diff.

This is a tangent that is outside the scope of this current topic,
but I wonder if you found it disturbing that we treat the result 't'
that has a path and the result 't' that does not have a path with
respect to a parent that does not have the path in a somewhat
assymmetric way.

With a merge M between commits A and B, where they all have the same
path with different contents, we obviously show that path in the
combined diff format.  A merge N that records exactly the same tree
as M that merges the same commits A and B plus another commit C that
does not have that path still shows the combined diff, with one
extra column to express "everything in the result N has been added
with respect to C which did not have the path at all".

However, a merge O between the same commits A and B, where A and B
have a path and O loses it, shows the path in the combined format.
A merge P among the same A, B and an extra parent C that does not
have that path ceases to show it (this is the assymmetry).

It is a natural extension of "Do not show the path when the result
matches one of the parent" rule, and in this case the result P takes
contents, "the path does not exist", from one parent "C", so it is
internally consistent, and I originally designed it that way on
purpose, but somehow it feels a bit strange.

--
To unsubscribe from this list: send the line "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 18/19] tree-diff: rework diff_tree() to generate diffs for multiparent cases as well

2014-04-07 Thread Junio C Hamano
Kirill Smelkov  writes:

> The following
> ...
> maybe looks a bit simpler, but calls tree_entry_pathcmp twice more times.
>
> Besides for important nparent=1 case we were not calling
> tree_entry_pathcmp at all and here we'll call it once, which would slow
> execution down a bit, as base_name_compare shows measurable enough in profile.
> To avoid that we'll need to add 'if (i==imin) continue' and this won't
> be so simple then. And for general nparent case, as I've said, we'll be
> calling tree_entry_pathcmp twice more times...
>
> Because of all that I'd suggest to go with my original version.

OK.

> ... After some break on the topic,
> with a fresh eye I see a lot of confusion goes from the notation I've
> chosen initially (because of how I was reasoning about it on paper, when
> it was in flux) - i.e. xi for x[imin] and also using i as looping
> variable. And also because xi was already used for x[imin] I've used
> another letter 'k' denoting all other x'es, which leads to confusion...
>
>
> I propose we do the following renaming to clarify things:
>
> A/a ->  T/t (to match resulting tree t name in the code)
> X/x ->  P/p (to match parents trees tp in the code)
> i   ->  imin(so that i would be free for other tasks)
>
> then the above (with a prologue) would look like
>
>  8< 
>  *   T P1   Pn
>  *   - --
>  *  |t|   |p1| |pn|
>  *  |-|   |--| ... |--|  imin = argmin(p1...pn)
>  *  | |   |  | |  |
>  *  |-|   |--| |--|
>  *  |.|   |. | |. |
>  *   . ..
>  *   . ..
>  *
>  * at any time there could be 3 cases:
>  *
>  *  1)  t < p[imin];
>  *  2)  t > p[imin];
>  *  3)  t = p[imin].
>  *
>  * Schematic deduction of what every case means, and what to do, follows:
>  *
>  * 1)  t < p[imin]  ->  ∀j t ∉ Pj  ->  "+t" ∈ D(T,Pj)  ->  D += "+t";  t↓
>  *
>  * 2)  t > p[imin]
>  *
>  * 2.1) ∃j: pj > p[imin]  ->  "-p[imin]" ∉ D(T,Pj)  ->  D += ø;  ∀ 
> pi=p[imin]  pi↓
>  * 2.2) ∀i  pi = p[imin]  ->  pi ∉ T  ->  "-pi" ∈ D(T,Pi)  ->  D += 
> "-p[imin]";  ∀i pi↓
>  *
>  * 3)  t = p[imin]
>  *
>  * 3.1) ∃j: pj > p[imin]  ->  "+t" ∈ D(T,Pj)  ->  only pi=p[imin] remains 
> to investigate
>  * 3.2) pi = p[imin]  ->  investigate δ(t,pi)
>  *  |
>  *  |
>  *  v
>  *
>  * 3.1+3.2) looking at δ(t,pi) ∀i: pi=p[imin] - if all != ø  ->
>  *
>  *   ⎧δ(t,pi)  - if pi=p[imin]
>  *  ->  D += ⎨
>  *   ⎩"+t" - if pi>p[imin]
>  *
>  *
>  * in any case t↓  ∀ pi=p[imin]  pi↓
> ...
> now xk is gone and i matches p[i] (= pi) etc so variable names correlate
> to algorithm description better.
>
> Does that maybe clarify things?

That sounds more consistent (modulo perhaps s/argmin/min/ at the
beginning?).

> P.S. Sorry for maybe some crept-in mistakes - I've tried to verify it
> thoroughly, but am too sleepy to be completely sure. On the other hand I
> think and hope the patch should be ok.

Thanks and do not be sorry for "mistakes"---we have the review
process exactly for catching them.
--
To unsubscribe from this list: send the line "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] pack-objects: do not reuse packfiles without --delta-base-offset

2014-04-07 Thread Junio C Hamano
Jeff King  writes:

> On Fri, Apr 04, 2014 at 03:28:48PM -0700, Junio C Hamano wrote:
> ...
>> OK, together with the fact that only ancient versions of fetcher
>> would trigger this "do not reuse" codepath, I agree that we should
>> go the simplest route this patch takes.
>
> By the way, we may want to revisit this if we grow more features that do
> not allow straight byte-for-byte reuse. 

True.

> I am thinking specifically if we
> grow a packv4-like representation for an object, and we plan to convert
> on-the-fly to existing packv2 clients. But I think the sensible steps
> for that are:
>
>   1. If we have v4 on disk and are outputting v2, add this case to the
>  "can_reuse" function I just added. I.e., start out correct, and
>  turn off the optimization.
>
>   2. Experiment with on-the-fly conversion. It may be that the
>  conversion is so expensive that the reuse optimization gets lost in
>  the noise. Or maybe we can reclaim most of the advantage of the
>  reuse code path, and it is worth going object-by-object and
>  converting. But we won't know until we can measure.

Yeah; I think these are sensible steps in the future direction.

Thanks.

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


Re: [PATCH] ls-files: do not trust stat info if lstat() fails

2014-04-07 Thread Junio C Hamano
Duy Nguyen  writes:

>>> Or even better to show an error message when the error code is
>>> unexpected? The unkown tag '!' says "there are problems" but if it
>>> shows up sort of permanently, '!' won't help much, I think.
>>
>> I am OK with that approach, but then one question remains: should we
>> say it is deleted, modified, both, or neither?
>
> The question is moot if the user does not ignore stderr because they
> should just ignore those error-reported entries. If they do
> 2>/dev/null, I think we should err on the safe side and say modified.
> We only say deleted if lstat() returns ENOENT or ENOTDIR like in your
> patch.

Doesn't the same reasoning behind "when we do not know for sure that
a path is not modified, it would be safe if we said the path may be
modified" also tell us that it is safer to say a path may be lost if
we cannot tell?

One likely case where we cannot tell if it is modified would be when
we cannot read the path (perhaps the parent directory accidentally
lost its x-bit).  Saying "it may be modified" would be one way to
have the user take notice, for an interactive user.  A script that
runs ls-files may be using the paths to drive "git add", "tar cf -",
etc. and emitting such an unreadable path is one way to make these
downstream commands signal that something fishy is going on by
erroring out.

So, I am not sure if we should be silent on an unexpected error when
we are asked to report deletes when we would be vocal when we are
asked to report modifications.
--
To unsubscribe from this list: send the line "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 v9 11/11] Documentation: add documentation for 'git interpret-trailers'

2014-04-07 Thread Junio C Hamano
Christian Couder  writes:

> On Sat, Apr 5, 2014 at 12:42 AM, Junio C Hamano  wrote:
>> Junio C Hamano  writes:
>>
>>> Christian Couder  writes:
>>> "The following features are planned but not yet implemented:
>>> - add more tests related to commands
>>> - add examples in documentation
>>> - integration with "git commit""
>>
>> I was planning to merge the series to 'next', but perhaps we should
>> wait at least for the first two items (I do not think the third one
>> is necessary to block the series).
>
> I will send soon a new version of the series with more tests and fixes.
> It will also contains a patch that adds an empty line before the
> trailers in the output if there is not already one.

Ah, yes, that one was mentioned in the reviews, I remember.

> After that I plan to work on adding examples to the documentation.

OK, thanks.

> First accepting both ':' and '=' means one can see the "git
> interpret-trailers" as acting on trailers only. Not just on trailers
> from the intput message and option parameters from the command line.

Sorry, you lost me.  What does "acting on trailers only" really
mean?  Do you mean the command should/can be run without any command
line options, pick up the existing "Signed-off-by:" and friends in
its input and emit its output, somehow taking these existing ones as
its instruction regarding how to transform the input to its output?

> And second there is also a practical advantage, as the user can
> copy-paste trailers directly from other messages into the command line
> to pass them as arguments to "git interpret-trailers" without the need
> to replace the ':' with '='. Even if this command is not often used
> directly by users, it might simplify scripts using it.
>
> Third there is a technical advantage which is that the code that
> parses arguments from the command line can be the same as the code
> that parses trailers from the input message.

I do not see these two as valid arguments to make the command line
more complex to the end users---who now need to know that only this
command treats its command line in a funny way, accepting a colon in
place of an equal sign.

A different way to sell a colon, e.g.

Consider the instruction sed takes on its command line.
(e.g. "sed 's/frotz/nitfol/' http://vger.kernel.org/majordomo-info.html


Re: What's cooking in git.git (Apr 2014, #01; Fri, 4)

2014-04-07 Thread Junio C Hamano
Johannes Sixt  writes:

> Am 04.04.2014 22:58, schrieb Junio C Hamano:
>> * sz/mingw-index-pack-threaded (2014-03-19) 1 commit
>>  - Enable index-pack threading in msysgit.
>> 
>>  What is the status of this topic?  A failure report exists
>>  ($gmane/245170), and I am aware of Duy's $gmane/245034 but that was
>>  where the discussion stalled.  Is everybody waiting for everybody
>>  else to get the discussion unstuck?
>
> I still have to cross-check Duy's patch. I'll hopefully get to it in the
> next days and report back.

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


Re: [PATCH 04/22] rollback_lock_file(): set fd to -1

2014-04-07 Thread Junio C Hamano
Michael Haggerty  writes:

> The first use of a lock_file object necessarily passes through
> lock_file().  The only precondition for that function is that the
> on_list field is zero, which is satisfied by a xcalloc()ed object.
>
> Subsequent uses of a lock_file object must *not* zero the object.
> lock_file objects are added to the lock_file_list and never removed.  So
> zeroing a lock_file object would discard the rest of the linked list.
> But subsequent uses must also pass through lock_file(), which sees that
> on_list is set, and assumes that the object is in a self-consistent
> state as left by commit_lock_file() or rollback_lock_file().
>
> At least that's how it is supposed to work.  But lock_file objects are
> in fact not cleaned up correctly in all circumstances.  The next version
> of this patch series will work to fix that.

Thanks; I see the next round already posted to the list.
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[PATCH] git-multimail: update to version 1.0.0

2014-04-07 Thread Michael Haggerty
This commit contains the squashed changes from the upstream
git-multimail repository since the last code drop.  Highlights:

* Fix encoding of non-ASCII email addresses in email headers.

* Fix backwards-compatibility bugs for older Python 2.x versions.

* Fix a backwards-compatibility bug for Git 1.7.1.

* Add an option commitDiffOpts to customize logs for revisions.

* Pass "-oi" to sendmail by default to prevent premature
  termination
  on a line containing only ".".

* Stagger email "Date:" values in an attempt to help mail clients
  thread the emails in the right order.

* If a mailing list setting is missing, just skip sending the
  corresponding email (with a warning) instead of failing.

* Add a X-Git-Host header that can be used for email filtering.

* Allow the sender's fully-qualified domain name to be configured.

* Minor documentation improvements.

* Add a CHANGES file.

Contributions-by: Raphaël Hertzog 
Contributions-by: Eric Berberich 
Contributions-by: Michiel Holtkamp 
Contributions-by: Malte Swart 
Signed-off-by: Michael Haggerty 
---
Junio, how would you like other people's contributions to be recorded
within the Git project?  I have listed them above as
"Contributions-by".  All of these people have signed off on their
contributions (recorded in my GitHub repo).  So should I also/instead
add "Signed-off-by" for those people?

 contrib/hooks/multimail/CHANGES  |  33 +
 contrib/hooks/multimail/README   |  46 ---
 contrib/hooks/multimail/README.Git   |   4 +-
 contrib/hooks/multimail/git_multimail.py | 218 ++-
 contrib/hooks/multimail/post-receive |   4 +-
 5 files changed, 249 insertions(+), 56 deletions(-)
 create mode 100644 contrib/hooks/multimail/CHANGES

diff --git a/contrib/hooks/multimail/CHANGES b/contrib/hooks/multimail/CHANGES
new file mode 100644
index 000..3603d56
--- /dev/null
+++ b/contrib/hooks/multimail/CHANGES
@@ -0,0 +1,33 @@
+Release 1.0.0
+=
+
+* Fix encoding of non-ASCII email addresses in email headers.
+
+* Fix backwards-compatibility bugs for older Python 2.x versions.
+
+* Fix a backwards-compatibility bug for Git 1.7.1.
+
+* Add an option commitDiffOpts to customize logs for revisions.
+
+* Pass "-oi" to sendmail by default to prevent premature termination
+  on a line containing only ".".
+
+* Stagger email "Date:" values in an attempt to help mail clients
+  thread the emails in the right order.
+
+* If a mailing list setting is missing, just skip sending the
+  corresponding email (with a warning) instead of failing.
+
+* Add a X-Git-Host header that can be used for email filtering.
+
+* Allow the sender's fully-qualified domain name to be configured.
+
+* Minor documentation improvements.
+
+* Add this CHANGES file.
+
+
+Release 0.9.0
+=
+
+* Initial release.
diff --git a/contrib/hooks/multimail/README b/contrib/hooks/multimail/README
index 9904396..477d65f 100644
--- a/contrib/hooks/multimail/README
+++ b/contrib/hooks/multimail/README
@@ -91,9 +91,10 @@ Requirements
   been tested; if you do so, please report your results.)
 
 * To send emails using the default configuration, a standard sendmail
-  program must be located at '/usr/sbin/sendmail' and configured
-  correctly to send emails.  If this is not the case, see the
-  multimailhook.mailer configuration variable below for how to
+  program must be located at '/usr/sbin/sendmail' or
+  '/usr/lib/sendmail' and must be configured correctly to send emails.
+  If this is not the case, set multimailhook.sendmailCommand, or see
+  the multimailhook.mailer configuration variable below for how to
   configure git-multimail to send emails via an SMTP server.
 
 
@@ -169,7 +170,7 @@ multimailhook.repoName
 for gitolite repositories, or otherwise to derive this value from
 the repository path name.
 
-multimailhook.mailinglist
+multimailhook.mailingList
 
 The list of email addresses to which notification emails should be
 sent, as RFC 2822 email addresses separated by commas.  This
@@ -184,26 +185,29 @@ multimailhook.refchangeList
 reference changes should be sent, as RFC 2822 email addresses
 separated by commas.  This configuration option can be
 multivalued.  The default is the value in
-multimailhook.mailinglist.  Set this value to the empty string to
-prevent reference change emails from being sent.
+multimailhook.mailingList.  Set this value to the empty string to
+prevent reference change emails from being sent even if
+multimailhook.mailingList is set.
 
 multimailhook.announceList
 
 The list of email addresses to which emails about new annotated
 tags should be sent, as RFC 2822 email addresses separated by
 commas.  This configuration option can be multivalued.  The
-default is the value in multimailhook.refchangelist or
-multimailhook.mailinglist.  Set this value to the empty string to
-prevent annotated tag announcement emails from being se

[PATCH v3 24/27] ref_transaction_commit(): simplify code using temporary variables

2014-04-07 Thread Michael Haggerty
Use temporary variables in the for-loop blocks to simplify expressions
in the rest of the loop.

Signed-off-by: Michael Haggerty 
---
 refs.c | 21 +
 1 file changed, 13 insertions(+), 8 deletions(-)

diff --git a/refs.c b/refs.c
index 2ff195f..33c34df 100644
--- a/refs.c
+++ b/refs.c
@@ -3435,10 +3435,12 @@ int ref_transaction_commit(struct ref_transaction 
*transaction,
 
/* Acquire all locks while verifying old values */
for (i = 0; i < n; i++) {
-   locks[i] = update_ref_lock(updates[i]->refname,
-  (updates[i]->have_old ?
-   updates[i]->old_sha1 : NULL),
-  updates[i]->flags,
+   struct ref_update *update = updates[i];
+
+   locks[i] = update_ref_lock(update->refname,
+  (update->have_old ?
+   update->old_sha1 : NULL),
+  update->flags,
   &types[i], onerr);
if (!locks[i]) {
ret = 1;
@@ -3447,16 +3449,19 @@ int ref_transaction_commit(struct ref_transaction 
*transaction,
}
 
/* Perform updates first so live commits remain referenced */
-   for (i = 0; i < n; i++)
-   if (!is_null_sha1(updates[i]->new_sha1)) {
+   for (i = 0; i < n; i++) {
+   struct ref_update *update = updates[i];
+
+   if (!is_null_sha1(update->new_sha1)) {
ret = update_ref_write(msg,
-  updates[i]->refname,
-  updates[i]->new_sha1,
+  update->refname,
+  update->new_sha1,
   locks[i], onerr);
locks[i] = NULL; /* freed by update_ref_write */
if (ret)
goto cleanup;
}
+   }
 
/* Perform deletes now that updates are safely completed */
for (i = 0; i < n; i++)
-- 
1.9.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


[PATCH v3 10/27] update-ref --stdin: improve error messages for invalid values

2014-04-07 Thread Michael Haggerty
If an invalid value is passed to "update-ref --stdin" as  or
, include the command and the name of the reference at the
beginning of the error message.  Update the tests accordingly.

Signed-off-by: Michael Haggerty 
---
 builtin/update-ref.c  | 24 +---
 t/t1400-update-ref.sh |  8 
 2 files changed, 17 insertions(+), 15 deletions(-)

diff --git a/builtin/update-ref.c b/builtin/update-ref.c
index 0dc2061..13a884a 100644
--- a/builtin/update-ref.c
+++ b/builtin/update-ref.c
@@ -35,20 +35,22 @@ static struct ref_update *update_alloc(void)
return update;
 }
 
-static void update_store_new_sha1(struct ref_update *update,
+static void update_store_new_sha1(const char *command,
+ struct ref_update *update,
  const char *newvalue)
 {
if (*newvalue && get_sha1(newvalue, update->new_sha1))
-   die("invalid new value for ref %s: %s",
-   update->ref_name, newvalue);
+   die("%s %s: invalid new value: %s",
+   command, update->ref_name, newvalue);
 }
 
-static void update_store_old_sha1(struct ref_update *update,
+static void update_store_old_sha1(const char *command,
+ struct ref_update *update,
  const char *oldvalue)
 {
if (*oldvalue && get_sha1(oldvalue, update->old_sha1))
-   die("invalid old value for ref %s: %s",
-   update->ref_name, oldvalue);
+   die("%s %s: invalid old value: %s",
+   command, update->ref_name, oldvalue);
 
/* We have an old value if non-empty, or if empty without -z */
update->have_old = *oldvalue || line_termination;
@@ -165,12 +167,12 @@ static const char *parse_cmd_update(struct strbuf *input, 
const char *next)
die("update line missing ");
 
if (!parse_next_arg(input, &next, &newvalue))
-   update_store_new_sha1(update, newvalue.buf);
+   update_store_new_sha1("update", update, newvalue.buf);
else
die("update %s missing ", update->ref_name);
 
if (!parse_next_arg(input, &next, &oldvalue)) {
-   update_store_old_sha1(update, oldvalue.buf);
+   update_store_old_sha1("update", update, oldvalue.buf);
if (*next != line_termination)
die("update %s has extra input: %s", update->ref_name, 
next);
} else if (!line_termination)
@@ -191,7 +193,7 @@ static const char *parse_cmd_create(struct strbuf *input, 
const char *next)
die("create line missing ");
 
if (!parse_next_arg(input, &next, &newvalue))
-   update_store_new_sha1(update, newvalue.buf);
+   update_store_new_sha1("create", update, newvalue.buf);
else
die("create %s missing ", update->ref_name);
 
@@ -216,7 +218,7 @@ static const char *parse_cmd_delete(struct strbuf *input, 
const char *next)
die("delete line missing ");
 
if (!parse_next_arg(input, &next, &oldvalue)) {
-   update_store_old_sha1(update, oldvalue.buf);
+   update_store_old_sha1("delete", update, oldvalue.buf);
if (update->have_old && is_null_sha1(update->old_sha1))
die("delete %s given zero old value", update->ref_name);
} else if (!line_termination)
@@ -240,7 +242,7 @@ static const char *parse_cmd_verify(struct strbuf *input, 
const char *next)
die("verify line missing ");
 
if (!parse_next_arg(input, &next, &value)) {
-   update_store_old_sha1(update, value.buf);
+   update_store_old_sha1("verify", update, value.buf);
hashcpy(update->new_sha1, update->old_sha1);
} else if (!line_termination)
die("verify %s missing [] NUL", update->ref_name);
diff --git a/t/t1400-update-ref.sh b/t/t1400-update-ref.sh
index 00862bc..f6c6e96 100755
--- a/t/t1400-update-ref.sh
+++ b/t/t1400-update-ref.sh
@@ -518,14 +518,14 @@ test_expect_success 'stdin update ref fails with wrong 
old value' '
 test_expect_success 'stdin update ref fails with bad old value' '
echo "update $c $m does-not-exist" >stdin &&
test_must_fail git update-ref --stdin err &&
-   grep "fatal: invalid old value for ref $c: does-not-exist" err &&
+   grep "fatal: update $c: invalid old value: does-not-exist" err &&
test_must_fail git rev-parse --verify -q $c
 '
 
 test_expect_success 'stdin create ref fails with bad new value' '
echo "create $c does-not-exist" >stdin &&
test_must_fail git update-ref --stdin err &&
-   grep "fatal: invalid new value for ref $c: does-not-exist" err &&
+   grep "fatal: create $c: invalid new value: does-not-exist" err &&
test_must_fail git rev-parse --verify -q $c
 '
 
@@ -840,14 +840,14 @@ test_expect_success 'stdin -z updat

[PATCH v3 26/27] struct ref_update: add a type field

2014-04-07 Thread Michael Haggerty
It used to be that ref_transaction_commit() allocated a temporary
array to hold the types of references while it is working.  Instead,
add a type field to ref_update that ref_transaction_commit() can use
as its scratch space.

Signed-off-by: Michael Haggerty 
---
 refs.c | 8 +++-
 1 file changed, 3 insertions(+), 5 deletions(-)

diff --git a/refs.c b/refs.c
index 6fe4bfe8..c058f30 100644
--- a/refs.c
+++ b/refs.c
@@ -3279,6 +3279,7 @@ struct ref_update {
int flags; /* REF_NODEREF? */
int have_old; /* 1 if old_sha1 is valid, 0 otherwise */
struct ref_lock *lock;
+   int type;
const char refname[FLEX_ARRAY];
 };
 
@@ -3413,7 +3414,6 @@ int ref_transaction_commit(struct ref_transaction 
*transaction,
 {
int ret = 0, delnum = 0, i;
struct ref_update **updates;
-   int *types;
const char **delnames;
int n = transaction->nr;
 
@@ -3422,7 +3422,6 @@ int ref_transaction_commit(struct ref_transaction 
*transaction,
 
/* Allocate work space */
updates = xmalloc(sizeof(*updates) * n);
-   types = xmalloc(sizeof(*types) * n);
delnames = xmalloc(sizeof(*delnames) * n);
 
/* Copy, sort, and reject duplicate refs */
@@ -3440,7 +3439,7 @@ int ref_transaction_commit(struct ref_transaction 
*transaction,
   (update->have_old ?
update->old_sha1 : NULL),
   update->flags,
-  &types[i], onerr);
+  &update->type, onerr);
if (!update->lock) {
ret = 1;
goto cleanup;
@@ -3468,7 +3467,7 @@ int ref_transaction_commit(struct ref_transaction 
*transaction,
 
if (update->lock) {
delnames[delnum++] = update->lock->ref_name;
-   ret |= delete_ref_loose(update->lock, types[i]);
+   ret |= delete_ref_loose(update->lock, update->type);
}
}
 
@@ -3482,7 +3481,6 @@ cleanup:
if (updates[i]->lock)
unlock_ref(updates[i]->lock);
free(updates);
-   free(types);
free(delnames);
ref_transaction_free(transaction);
return ret;
-- 
1.9.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


[PATCH v3 27/27] ref_transaction_commit(): work with transaction->updates in place

2014-04-07 Thread Michael Haggerty
Now that we free the transaction when we are done, there is no need to
make a copy of transaction->updates before working with it.

Signed-off-by: Michael Haggerty 
---
 refs.c | 5 +
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/refs.c b/refs.c
index c058f30..728a761 100644
--- a/refs.c
+++ b/refs.c
@@ -3413,19 +3413,17 @@ int ref_transaction_commit(struct ref_transaction 
*transaction,
   const char *msg, enum action_on_err onerr)
 {
int ret = 0, delnum = 0, i;
-   struct ref_update **updates;
const char **delnames;
int n = transaction->nr;
+   struct ref_update **updates = transaction->updates;
 
if (!n)
return 0;
 
/* Allocate work space */
-   updates = xmalloc(sizeof(*updates) * n);
delnames = xmalloc(sizeof(*delnames) * n);
 
/* Copy, sort, and reject duplicate refs */
-   memcpy(updates, transaction->updates, sizeof(*updates) * n);
qsort(updates, n, sizeof(*updates), ref_update_compare);
ret = ref_update_reject_duplicates(updates, n, onerr);
if (ret)
@@ -3480,7 +3478,6 @@ cleanup:
for (i = 0; i < n; i++)
if (updates[i]->lock)
unlock_ref(updates[i]->lock);
-   free(updates);
free(delnames);
ref_transaction_free(transaction);
return ret;
-- 
1.9.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


[PATCH v3 14/27] update-ref.c: extract a new function, parse_next_sha1()

2014-04-07 Thread Michael Haggerty
Replace three functions, update_store_new_sha1(),
update_store_old_sha1(), and parse_next_arg(), with a single function,
parse_next_sha1().  The new function takes care of a whole argument,
including checking whether it is there, converting it to an SHA-1, and
emitting errors on EOF or for invalid values.  The return value
indicates whether the argument was present or absent, which requires
a bit of intelligence because absent values are represented
differently depending on whether "-z" was used.

The new interface means that the calling functions, parse_cmd_*(),
don't have to interpret the result differently based on the
line_termination mode that is in effect.  It also means that
parse_cmd_create() can distinguish unambiguously between an empty new
value and a zeros new value, which fixes a failure in t1400.

Signed-off-by: Michael Haggerty 
---
 builtin/update-ref.c  | 160 +++---
 t/t1400-update-ref.sh |   2 +-
 2 files changed, 99 insertions(+), 63 deletions(-)

diff --git a/builtin/update-ref.c b/builtin/update-ref.c
index a9eb5fe..c61120f 100644
--- a/builtin/update-ref.c
+++ b/builtin/update-ref.c
@@ -35,27 +35,6 @@ static struct ref_update *update_alloc(void)
return update;
 }
 
-static void update_store_new_sha1(const char *command,
- struct ref_update *update,
- const char *newvalue)
-{
-   if (*newvalue && get_sha1(newvalue, update->new_sha1))
-   die("%s %s: invalid : %s",
-   command, update->ref_name, newvalue);
-}
-
-static void update_store_old_sha1(const char *command,
- struct ref_update *update,
- const char *oldvalue)
-{
-   if (*oldvalue && get_sha1(oldvalue, update->old_sha1))
-   die("%s %s: invalid : %s",
-   command, update->ref_name, oldvalue);
-
-   /* We have an old value if non-empty, or if empty without -z */
-   update->have_old = *oldvalue || line_termination;
-}
-
 /*
  * Parse one whitespace- or NUL-terminated, possibly C-quoted argument
  * and append the result to arg.  Return a pointer to the terminator.
@@ -112,35 +91,94 @@ static char *parse_refname(struct strbuf *input, const 
char **next)
 }
 
 /*
- * Parse a SP/NUL separator followed by the next SP- or NUL-terminated
- * argument, if any.  If there is an argument, write it to arg, set
- * *next to point at the character terminating the argument, and
+ * The value being parsed is  (as opposed to ; the
+ * difference affects which error messages are generated):
+ */
+#define PARSE_SHA1_OLD 0x01
+
+/*
+ * For backwards compatibility, accept an empty string for update's
+ *  in binary mode to be equivalent to specifying zeros.
+ */
+#define PARSE_SHA1_ALLOW_EMPTY 0x02
+
+/*
+ * Parse an argument separator followed by the next argument, if any.
+ * If there is an argument, convert it to a SHA-1, write it to sha1,
+ * set *next to point at the character terminating the argument, and
  * return 0.  If there is no argument at all (not even the empty
- * string), return a non-zero result and leave *next unchanged.
+ * string), return 1 and leave *next unchanged.  If the value is
+ * provided but cannot be converted to a SHA-1, die.  flags can
+ * include PARSE_SHA1_OLD and/or PARSE_SHA1_ALLOW_EMPTY.
  */
-static int parse_next_arg(struct strbuf *input, const char **next,
- struct strbuf *arg)
+static int parse_next_sha1(struct strbuf *input, const char **next,
+  unsigned char *sha1,
+  const char *command, const char *refname,
+  int flags)
 {
-   strbuf_reset(arg);
+   struct strbuf arg = STRBUF_INIT;
+   int ret = 0;
+
+   if (*next == input->buf + input->len)
+   goto eof;
+
if (line_termination) {
/* Without -z, consume SP and use next argument */
if (!**next || **next == line_termination)
-   return -1;
+   return 1;
if (**next != ' ')
-   die("expected SP but got: %s", *next);
+   die("%s %s: expected SP but got: %s",
+   command, refname, *next);
(*next)++;
-   *next = parse_arg(*next, arg);
+   *next = parse_arg(*next, &arg);
+   if (arg.len) {
+   if (get_sha1(arg.buf, sha1))
+   goto invalid;
+   } else {
+   /* Without -z, an empty value means all zeros: */
+   hashclr(sha1);
+   }
} else {
/* With -z, read the next NUL-terminated line */
if (**next)
-   die("expected NUL but got: %s", *next);
+   die("%s %s: expected NUL but got: %s",
+  

[PATCH v3 20/27] update-ref --stdin: reimplement using reference transactions

2014-04-07 Thread Michael Haggerty
This change is mostly clerical: the parse_cmd_*() functions need to
use local variables rather than a struct ref_update to collect the
arguments needed for each update, and then call ref_transaction_*() to
queue the change rather than building up the list of changes at the
caller side.

Signed-off-by: Michael Haggerty 
---
 builtin/update-ref.c | 142 +++
 1 file changed, 75 insertions(+), 67 deletions(-)

diff --git a/builtin/update-ref.c b/builtin/update-ref.c
index 423c5c3..405267f 100644
--- a/builtin/update-ref.c
+++ b/builtin/update-ref.c
@@ -12,29 +12,11 @@ static const char * const git_update_ref_usage[] = {
NULL
 };
 
-static int updates_alloc;
-static int updates_count;
-static struct ref_update **updates;
+static struct ref_transaction *transaction;
 
 static char line_termination = '\n';
 static int update_flags;
 
-static struct ref_update *update_alloc(void)
-{
-   struct ref_update *update;
-
-   /* Allocate and zero-init a struct ref_update */
-   update = xcalloc(1, sizeof(*update));
-   ALLOC_GROW(updates, updates_count + 1, updates_alloc);
-   updates[updates_count++] = update;
-
-   /* Store and reset accumulated options */
-   update->flags = update_flags;
-   update_flags = 0;
-
-   return update;
-}
-
 /*
  * Parse one whitespace- or NUL-terminated, possibly C-quoted argument
  * and append the result to arg.  Return a pointer to the terminator.
@@ -196,97 +178,119 @@ static int parse_next_sha1(struct strbuf *input, const 
char **next,
 
 static const char *parse_cmd_update(struct strbuf *input, const char *next)
 {
-   struct ref_update *update;
-
-   update = update_alloc();
+   char *refname;
+   unsigned char new_sha1[20];
+   unsigned char old_sha1[20];
+   int have_old;
 
-   update->ref_name = parse_refname(input, &next);
-   if (!update->ref_name)
+   refname = parse_refname(input, &next);
+   if (!refname)
die("update: missing ");
 
-   if (parse_next_sha1(input, &next, update->new_sha1,
-   "update", update->ref_name,
+   if (parse_next_sha1(input, &next, new_sha1, "update", refname,
PARSE_SHA1_ALLOW_EMPTY))
-   die("update %s: missing ", update->ref_name);
+   die("update %s: missing ", refname);
 
-   update->have_old = !parse_next_sha1(input, &next, update->old_sha1,
-   "update", update->ref_name,
-   PARSE_SHA1_OLD);
+   have_old = !parse_next_sha1(input, &next, old_sha1, "update", refname,
+   PARSE_SHA1_OLD);
 
if (*next != line_termination)
-   die("update %s: extra input: %s", update->ref_name, next);
+   die("update %s: extra input: %s", refname, next);
+
+   ref_transaction_update(transaction, refname, new_sha1, old_sha1,
+  update_flags, have_old);
+
+   update_flags = 0;
+   free(refname);
 
return next;
 }
 
 static const char *parse_cmd_create(struct strbuf *input, const char *next)
 {
-   struct ref_update *update;
-
-   update = update_alloc();
+   char *refname;
+   unsigned char new_sha1[20];
 
-   update->ref_name = parse_refname(input, &next);
-   if (!update->ref_name)
+   refname = parse_refname(input, &next);
+   if (!refname)
die("create: missing ");
 
-   if (parse_next_sha1(input, &next, update->new_sha1,
-   "create", update->ref_name, 0))
-   die("create %s: missing ", update->ref_name);
+   if (parse_next_sha1(input, &next, new_sha1, "create", refname, 0))
+   die("create %s: missing ", refname);
 
-   if (is_null_sha1(update->new_sha1))
-   die("create %s: zero ", update->ref_name);
+   if (is_null_sha1(new_sha1))
+   die("create %s: zero ", refname);
 
if (*next != line_termination)
-   die("create %s: extra input: %s", update->ref_name, next);
+   die("create %s: extra input: %s", refname, next);
+
+   ref_transaction_create(transaction, refname, new_sha1, update_flags);
+
+   update_flags = 0;
+   free(refname);
 
return next;
 }
 
 static const char *parse_cmd_delete(struct strbuf *input, const char *next)
 {
-   struct ref_update *update;
+   char *refname;
+   unsigned char old_sha1[20];
+   int have_old;
 
-   update = update_alloc();
-
-   update->ref_name = parse_refname(input, &next);
-   if (!update->ref_name)
+   refname = parse_refname(input, &next);
+   if (!refname)
die("delete: missing ");
 
-   if (parse_next_sha1(input, &next, update->old_sha1,
-   "delete", update->ref_name, PARSE_SHA1_OLD)) {
-   update->have_old = 0;
+   

[PATCH v3 17/27] update-ref --stdin: improve the error message for unexpected EOF

2014-04-07 Thread Michael Haggerty
Distinguish this error from the error that an argument is missing for
another reason.  Update the tests accordingly.

Signed-off-by: Michael Haggerty 
---
 builtin/update-ref.c  |  4 ++--
 t/t1400-update-ref.sh | 12 ++--
 2 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/builtin/update-ref.c b/builtin/update-ref.c
index 6f3b909..0d5f1d0 100644
--- a/builtin/update-ref.c
+++ b/builtin/update-ref.c
@@ -178,8 +178,8 @@ static int parse_next_sha1(struct strbuf *input, const char 
**next,
 
  eof:
die(flags & PARSE_SHA1_OLD ?
-   "%s %s missing " :
-   "%s %s missing ",
+   "%s %s: unexpected end of input when reading " :
+   "%s %s: unexpected end of input when reading ",
command, refname);
 }
 
diff --git a/t/t1400-update-ref.sh b/t/t1400-update-ref.sh
index 6b21e45..1db0689 100755
--- a/t/t1400-update-ref.sh
+++ b/t/t1400-update-ref.sh
@@ -709,7 +709,7 @@ test_expect_success 'stdin -z fails create with bad ref 
name' '
 test_expect_success 'stdin -z fails create with no new value' '
printf $F "create $a" >stdin &&
test_must_fail git update-ref -z --stdin err &&
-   grep "fatal: create $a missing " err
+   grep "fatal: create $a: unexpected end of input when reading 
" err
 '
 
 test_expect_success 'stdin -z fails create with too many arguments' '
@@ -727,7 +727,7 @@ test_expect_success 'stdin -z fails update with no ref' '
 test_expect_success 'stdin -z fails update with too few args' '
printf $F "update $a" "$m" >stdin &&
test_must_fail git update-ref -z --stdin err &&
-   grep "fatal: update $a missing " err
+   grep "fatal: update $a: unexpected end of input when reading 
" err
 '
 
 test_expect_success 'stdin -z fails update with bad ref name' '
@@ -747,13 +747,13 @@ test_expect_success 'stdin -z emits warning with empty 
new value' '
 test_expect_success 'stdin -z fails update with no new value' '
printf $F "update $a" >stdin &&
test_must_fail git update-ref -z --stdin err &&
-   grep "fatal: update $a missing " err
+   grep "fatal: update $a: unexpected end of input when reading 
" err
 '
 
 test_expect_success 'stdin -z fails update with no old value' '
printf $F "update $a" "$m" >stdin &&
test_must_fail git update-ref -z --stdin err &&
-   grep "fatal: update $a missing " err
+   grep "fatal: update $a: unexpected end of input when reading 
" err
 '
 
 test_expect_success 'stdin -z fails update with too many arguments' '
@@ -777,7 +777,7 @@ test_expect_success 'stdin -z fails delete with bad ref 
name' '
 test_expect_success 'stdin -z fails delete with no old value' '
printf $F "delete $a" >stdin &&
test_must_fail git update-ref -z --stdin err &&
-   grep "fatal: delete $a missing " err
+   grep "fatal: delete $a: unexpected end of input when reading 
" err
 '
 
 test_expect_success 'stdin -z fails delete with too many arguments' '
@@ -795,7 +795,7 @@ test_expect_success 'stdin -z fails verify with too many 
arguments' '
 test_expect_success 'stdin -z fails verify with no old value' '
printf $F "verify $a" >stdin &&
test_must_fail git update-ref -z --stdin err &&
-   grep "fatal: verify $a missing " err
+   grep "fatal: verify $a: unexpected end of input when reading 
" err
 '
 
 test_expect_success 'stdin -z fails option with unknown name' '
-- 
1.9.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


[PATCH v3 12/27] update-ref --stdin: simplify error messages for missing oldvalues

2014-04-07 Thread Michael Haggerty
Instead of, for example,

fatal: update refs/heads/master missing [] NUL

emit

fatal: update refs/heads/master missing 

Update the tests accordingly.

Signed-off-by: Michael Haggerty 
---
 builtin/update-ref.c  | 6 +++---
 t/t1400-update-ref.sh | 6 +++---
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/builtin/update-ref.c b/builtin/update-ref.c
index e4c0854..a9eb5fe 100644
--- a/builtin/update-ref.c
+++ b/builtin/update-ref.c
@@ -176,7 +176,7 @@ static const char *parse_cmd_update(struct strbuf *input, 
const char *next)
if (*next != line_termination)
die("update %s has extra input: %s", update->ref_name, 
next);
} else if (!line_termination)
-   die("update %s missing [] NUL", update->ref_name);
+   die("update %s missing ", update->ref_name);
 
return next;
 }
@@ -222,7 +222,7 @@ static const char *parse_cmd_delete(struct strbuf *input, 
const char *next)
if (update->have_old && is_null_sha1(update->old_sha1))
die("delete %s given zero ", 
update->ref_name);
} else if (!line_termination)
-   die("delete %s missing [] NUL", update->ref_name);
+   die("delete %s missing ", update->ref_name);
 
if (*next != line_termination)
die("delete %s has extra input: %s", update->ref_name, next);
@@ -245,7 +245,7 @@ static const char *parse_cmd_verify(struct strbuf *input, 
const char *next)
update_store_old_sha1("verify", update, value.buf);
hashcpy(update->new_sha1, update->old_sha1);
} else if (!line_termination)
-   die("verify %s missing [] NUL", update->ref_name);
+   die("verify %s missing ", update->ref_name);
 
if (*next != line_termination)
die("verify %s has extra input: %s", update->ref_name, next);
diff --git a/t/t1400-update-ref.sh b/t/t1400-update-ref.sh
index ef61fe3..a2015d0 100755
--- a/t/t1400-update-ref.sh
+++ b/t/t1400-update-ref.sh
@@ -739,7 +739,7 @@ test_expect_success 'stdin -z fails update with no new 
value' '
 test_expect_success 'stdin -z fails update with no old value' '
printf $F "update $a" "$m" >stdin &&
test_must_fail git update-ref -z --stdin err &&
-   grep "fatal: update $a missing \\[\\] NUL" err
+   grep "fatal: update $a missing " err
 '
 
 test_expect_success 'stdin -z fails update with too many arguments' '
@@ -763,7 +763,7 @@ test_expect_success 'stdin -z fails delete with bad ref 
name' '
 test_expect_success 'stdin -z fails delete with no old value' '
printf $F "delete $a" >stdin &&
test_must_fail git update-ref -z --stdin err &&
-   grep "fatal: delete $a missing \\[\\] NUL" err
+   grep "fatal: delete $a missing " err
 '
 
 test_expect_success 'stdin -z fails delete with too many arguments' '
@@ -781,7 +781,7 @@ test_expect_success 'stdin -z fails verify with too many 
arguments' '
 test_expect_success 'stdin -z fails verify with no old value' '
printf $F "verify $a" >stdin &&
test_must_fail git update-ref -z --stdin err &&
-   grep "fatal: verify $a missing \\[\\] NUL" err
+   grep "fatal: verify $a missing " err
 '
 
 test_expect_success 'stdin -z fails option with unknown name' '
-- 
1.9.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


[PATCH v3 19/27] refs: add a concept of a reference transaction

2014-04-07 Thread Michael Haggerty
Build out the API for dealing with a bunch of reference checks and
changes within a transaction.  Define an opaque ref_transaction type
that is managed entirely within refs.c.  Introduce functions for
beginning a transaction, adding updates to a transaction, and
committing/rolling back a transaction.

This API will soon replace update_refs().

Signed-off-by: Michael Haggerty 
---
 refs.c | 99 ++
 refs.h | 65 +++
 2 files changed, 164 insertions(+)

diff --git a/refs.c b/refs.c
index 1305eb1..f0b5764 100644
--- a/refs.c
+++ b/refs.c
@@ -3267,6 +3267,96 @@ static int update_ref_write(const char *action, const 
char *refname,
return 0;
 }
 
+/*
+ * Data structure for holding a reference transaction, which can
+ * consist of checks and updates to multiple references, carried out
+ * as atomically as possible.  This structure is opaque to callers.
+ */
+struct ref_transaction {
+   struct ref_update **updates;
+   size_t alloc;
+   size_t nr;
+};
+
+struct ref_transaction *ref_transaction_begin(void)
+{
+   return xcalloc(1, sizeof(struct ref_transaction));
+}
+
+static void ref_transaction_free(struct ref_transaction *transaction)
+{
+   int i;
+
+   for (i = 0; i < transaction->nr; i++) {
+   struct ref_update *update = transaction->updates[i];
+
+   free((char *)update->ref_name);
+   free(update);
+   }
+
+   free(transaction->updates);
+   free(transaction);
+}
+
+void ref_transaction_rollback(struct ref_transaction *transaction)
+{
+   ref_transaction_free(transaction);
+}
+
+static struct ref_update *add_update(struct ref_transaction *transaction,
+const char *refname)
+{
+   struct ref_update *update = xcalloc(1, sizeof(*update));
+
+   update->ref_name = xstrdup(refname);
+   ALLOC_GROW(transaction->updates, transaction->nr + 1, 
transaction->alloc);
+   transaction->updates[transaction->nr++] = update;
+   return update;
+}
+
+void ref_transaction_update(struct ref_transaction *transaction,
+   const char *refname,
+   unsigned char *new_sha1, unsigned char *old_sha1,
+   int flags, int have_old)
+{
+   struct ref_update *update = add_update(transaction, refname);
+
+   hashcpy(update->new_sha1, new_sha1);
+   update->flags = flags;
+   update->have_old = have_old;
+   if (have_old)
+   hashcpy(update->old_sha1, old_sha1);
+}
+
+void ref_transaction_create(struct ref_transaction *transaction,
+   const char *refname,
+   unsigned char *new_sha1,
+   int flags)
+{
+   struct ref_update *update = add_update(transaction, refname);
+
+   assert(!is_null_sha1(new_sha1));
+   hashcpy(update->new_sha1, new_sha1);
+   hashclr(update->old_sha1);
+   update->flags = flags;
+   update->have_old = 1;
+}
+
+void ref_transaction_delete(struct ref_transaction *transaction,
+   const char *refname,
+   unsigned char *old_sha1,
+   int flags, int have_old)
+{
+   struct ref_update *update = add_update(transaction, refname);
+
+   update->flags = flags;
+   update->have_old = have_old;
+   if (have_old) {
+   assert(!is_null_sha1(old_sha1));
+   hashcpy(update->old_sha1, old_sha1);
+   }
+}
+
 int update_ref(const char *action, const char *refname,
   const unsigned char *sha1, const unsigned char *oldval,
   int flags, enum action_on_err onerr)
@@ -3378,6 +3468,15 @@ cleanup:
return ret;
 }
 
+int ref_transaction_commit(struct ref_transaction *transaction,
+  const char *msg, enum action_on_err onerr)
+{
+   int ret = update_refs(msg, transaction->updates, transaction->nr,
+ onerr);
+   ref_transaction_free(transaction);
+   return ret;
+}
+
 char *shorten_unambiguous_ref(const char *refname, int strict)
 {
int i;
diff --git a/refs.h b/refs.h
index 08e60ac..0518dd5 100644
--- a/refs.h
+++ b/refs.h
@@ -24,6 +24,8 @@ struct ref_update {
int have_old; /* 1 if old_sha1 is valid, 0 otherwise */
 };
 
+struct ref_transaction;
+
 /*
  * Bit values set in the flags argument passed to each_ref_fn():
  */
@@ -220,6 +222,69 @@ enum action_on_err {
UPDATE_REFS_QUIET_ON_ERR
 };
 
+/*
+ * Begin a reference transaction.  The reference transaction must
+ * eventually be commited using ref_transaction_commit() or rolled
+ * back using ref_transaction_rollback().
+ */
+struct ref_transaction *ref_transaction_begin(void);
+
+/*
+ * Roll back a ref_transaction and free all associated data.
+ */
+void ref_transaction_rollback(struct ref_transaction *transaction);
+
+
+/*

[PATCH v3 13/27] t1400: test that stdin -z update treats empty as zeros

2014-04-07 Thread Michael Haggerty
This is the (slightly inconsistent) status quo; make sure it doesn't
change by accident.

Signed-off-by: Michael Haggerty 
---
 t/t1400-update-ref.sh | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/t/t1400-update-ref.sh b/t/t1400-update-ref.sh
index a2015d0..208f56e 100755
--- a/t/t1400-update-ref.sh
+++ b/t/t1400-update-ref.sh
@@ -730,6 +730,13 @@ test_expect_success 'stdin -z fails update with bad ref 
name' '
grep "fatal: invalid ref format: ~a" err
 '
 
+test_expect_success 'stdin -z treats empty new value as zeros' '
+   git update-ref $a $m &&
+   printf $F "update $a" "" "" >stdin &&
+   git update-ref -z --stdin stdin &&
test_must_fail git update-ref -z --stdin err &&
-- 
1.9.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


[PATCH v3 22/27] struct ref_update: rename field "ref_name" to "refname"

2014-04-07 Thread Michael Haggerty
This is consistent with the usual nomenclature.

Signed-off-by: Michael Haggerty 
---
 refs.c | 18 +-
 refs.h |  2 +-
 2 files changed, 10 insertions(+), 10 deletions(-)

diff --git a/refs.c b/refs.c
index 6984ff0..b6778aa 100644
--- a/refs.c
+++ b/refs.c
@@ -3274,7 +3274,7 @@ static int update_ref_write(const char *action, const 
char *refname,
  * value or to zero to ensure the ref does not exist before update.
  */
 struct ref_update {
-   const char *ref_name;
+   const char *refname;
unsigned char new_sha1[20];
unsigned char old_sha1[20];
int flags; /* REF_NODEREF? */
@@ -3304,7 +3304,7 @@ static void ref_transaction_free(struct ref_transaction 
*transaction)
for (i = 0; i < transaction->nr; i++) {
struct ref_update *update = transaction->updates[i];
 
-   free((char *)update->ref_name);
+   free((char *)update->refname);
free(update);
}
 
@@ -3322,7 +3322,7 @@ static struct ref_update *add_update(struct 
ref_transaction *transaction,
 {
struct ref_update *update = xcalloc(1, sizeof(*update));
 
-   update->ref_name = xstrdup(refname);
+   update->refname = xstrdup(refname);
ALLOC_GROW(transaction->updates, transaction->nr + 1, 
transaction->alloc);
transaction->updates[transaction->nr++] = update;
return update;
@@ -3386,7 +3386,7 @@ static int ref_update_compare(const void *r1, const void 
*r2)
 {
const struct ref_update * const *u1 = r1;
const struct ref_update * const *u2 = r2;
-   return strcmp((*u1)->ref_name, (*u2)->ref_name);
+   return strcmp((*u1)->refname, (*u2)->refname);
 }
 
 static int ref_update_reject_duplicates(struct ref_update **updates, int n,
@@ -3394,14 +3394,14 @@ static int ref_update_reject_duplicates(struct 
ref_update **updates, int n,
 {
int i;
for (i = 1; i < n; i++)
-   if (!strcmp(updates[i - 1]->ref_name, updates[i]->ref_name)) {
+   if (!strcmp(updates[i - 1]->refname, updates[i]->refname)) {
const char *str =
"Multiple updates for ref '%s' not allowed.";
switch (onerr) {
case UPDATE_REFS_MSG_ON_ERR:
-   error(str, updates[i]->ref_name); break;
+   error(str, updates[i]->refname); break;
case UPDATE_REFS_DIE_ON_ERR:
-   die(str, updates[i]->ref_name); break;
+   die(str, updates[i]->refname); break;
case UPDATE_REFS_QUIET_ON_ERR:
break;
}
@@ -3438,7 +3438,7 @@ int ref_transaction_commit(struct ref_transaction 
*transaction,
 
/* Acquire all locks while verifying old values */
for (i = 0; i < n; i++) {
-   locks[i] = update_ref_lock(updates[i]->ref_name,
+   locks[i] = update_ref_lock(updates[i]->refname,
   (updates[i]->have_old ?
updates[i]->old_sha1 : NULL),
   updates[i]->flags,
@@ -3453,7 +3453,7 @@ int ref_transaction_commit(struct ref_transaction 
*transaction,
for (i = 0; i < n; i++)
if (!is_null_sha1(updates[i]->new_sha1)) {
ret = update_ref_write(msg,
-  updates[i]->ref_name,
+  updates[i]->refname,
   updates[i]->new_sha1,
   locks[i], onerr);
locks[i] = NULL; /* freed by update_ref_write */
diff --git a/refs.h b/refs.h
index cb799a3..0f08def 100644
--- a/refs.h
+++ b/refs.h
@@ -154,7 +154,7 @@ extern void unlock_ref(struct ref_lock *lock);
 extern int write_ref_sha1(struct ref_lock *lock, const unsigned char *sha1, 
const char *msg);
 
 /** Setup reflog before using. **/
-int log_ref_setup(const char *ref_name, char *logfile, int bufsize);
+int log_ref_setup(const char *refname, char *logfile, int bufsize);
 
 /** Reads log for the value of ref during at_time. **/
 extern int read_ref_at(const char *refname, unsigned long at_time, int cnt,
-- 
1.9.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


[PATCH v3 21/27] refs: remove API function update_refs()

2014-04-07 Thread Michael Haggerty
It has been superseded by reference transactions.  This also means
that struct ref_update can become private.

Signed-off-by: Michael Haggerty 
---
 refs.c | 33 -
 refs.h | 20 
 2 files changed, 20 insertions(+), 33 deletions(-)

diff --git a/refs.c b/refs.c
index f0b5764..6984ff0 100644
--- a/refs.c
+++ b/refs.c
@@ -3267,6 +3267,20 @@ static int update_ref_write(const char *action, const 
char *refname,
return 0;
 }
 
+/**
+ * Information needed for a single ref update.  Set new_sha1 to the
+ * new value or to zero to delete the ref.  To check the old value
+ * while locking the ref, set have_old to 1 and set old_sha1 to the
+ * value or to zero to ensure the ref does not exist before update.
+ */
+struct ref_update {
+   const char *ref_name;
+   unsigned char new_sha1[20];
+   unsigned char old_sha1[20];
+   int flags; /* REF_NODEREF? */
+   int have_old; /* 1 if old_sha1 is valid, 0 otherwise */
+};
+
 /*
  * Data structure for holding a reference transaction, which can
  * consist of checks and updates to multiple references, carried out
@@ -3396,16 +3410,17 @@ static int ref_update_reject_duplicates(struct 
ref_update **updates, int n,
return 0;
 }
 
-int update_refs(const char *action, struct ref_update * const *updates_orig,
-   int n, enum action_on_err onerr)
+int ref_transaction_commit(struct ref_transaction *transaction,
+  const char *msg, enum action_on_err onerr)
 {
int ret = 0, delnum = 0, i;
struct ref_update **updates;
int *types;
struct ref_lock **locks;
const char **delnames;
+   int n = transaction->nr;
 
-   if (!updates_orig || !n)
+   if (!n)
return 0;
 
/* Allocate work space */
@@ -3415,7 +3430,7 @@ int update_refs(const char *action, struct ref_update * 
const *updates_orig,
delnames = xmalloc(sizeof(*delnames) * n);
 
/* Copy, sort, and reject duplicate refs */
-   memcpy(updates, updates_orig, sizeof(*updates) * n);
+   memcpy(updates, transaction->updates, sizeof(*updates) * n);
qsort(updates, n, sizeof(*updates), ref_update_compare);
ret = ref_update_reject_duplicates(updates, n, onerr);
if (ret)
@@ -3437,7 +3452,7 @@ int update_refs(const char *action, struct ref_update * 
const *updates_orig,
/* Perform updates first so live commits remain referenced */
for (i = 0; i < n; i++)
if (!is_null_sha1(updates[i]->new_sha1)) {
-   ret = update_ref_write(action,
+   ret = update_ref_write(msg,
   updates[i]->ref_name,
   updates[i]->new_sha1,
   locks[i], onerr);
@@ -3465,14 +3480,6 @@ cleanup:
free(types);
free(locks);
free(delnames);
-   return ret;
-}
-
-int ref_transaction_commit(struct ref_transaction *transaction,
-  const char *msg, enum action_on_err onerr)
-{
-   int ret = update_refs(msg, transaction->updates, transaction->nr,
- onerr);
ref_transaction_free(transaction);
return ret;
 }
diff --git a/refs.h b/refs.h
index 0518dd5..cb799a3 100644
--- a/refs.h
+++ b/refs.h
@@ -10,20 +10,6 @@ struct ref_lock {
int force_write;
 };
 
-/**
- * Information needed for a single ref update.  Set new_sha1 to the
- * new value or to zero to delete the ref.  To check the old value
- * while locking the ref, set have_old to 1 and set old_sha1 to the
- * value or to zero to ensure the ref does not exist before update.
- */
-struct ref_update {
-   const char *ref_name;
-   unsigned char new_sha1[20];
-   unsigned char old_sha1[20];
-   int flags; /* REF_NODEREF? */
-   int have_old; /* 1 if old_sha1 is valid, 0 otherwise */
-};
-
 struct ref_transaction;
 
 /*
@@ -290,12 +276,6 @@ int update_ref(const char *action, const char *refname,
const unsigned char *sha1, const unsigned char *oldval,
int flags, enum action_on_err onerr);
 
-/**
- * Lock all refs and then perform all modifications.
- */
-int update_refs(const char *action, struct ref_update * const *updates,
-   int n, enum action_on_err onerr);
-
 extern int parse_hide_refs_config(const char *var, const char *value, const 
char *);
 extern int ref_is_hidden(const char *);
 
-- 
1.9.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


[PATCH v3 16/27] t1400: test one mistake at a time

2014-04-07 Thread Michael Haggerty
This case wants to test passing a bad refname to the "update" command.
But it also passes too few arguments to "update", which muddles the
situation: which error should be diagnosed?  So split this test into
two:

* One that passes too few arguments to update

* One that passes all three arguments to "update", but with a bad
  refname.

Signed-off-by: Michael Haggerty 
---
 t/t1400-update-ref.sh | 8 +++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/t/t1400-update-ref.sh b/t/t1400-update-ref.sh
index 2d61cce..6b21e45 100755
--- a/t/t1400-update-ref.sh
+++ b/t/t1400-update-ref.sh
@@ -724,8 +724,14 @@ test_expect_success 'stdin -z fails update with no ref' '
grep "fatal: update line missing " err
 '
 
+test_expect_success 'stdin -z fails update with too few args' '
+   printf $F "update $a" "$m" >stdin &&
+   test_must_fail git update-ref -z --stdin err &&
+   grep "fatal: update $a missing " err
+'
+
 test_expect_success 'stdin -z fails update with bad ref name' '
-   printf $F "update ~a" "$m" >stdin &&
+   printf $F "update ~a" "$m" "" >stdin &&
test_must_fail git update-ref -z --stdin err &&
grep "fatal: invalid ref format: ~a" err
 '
-- 
1.9.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


[PATCH v3 11/27] update-ref --stdin: make error messages more consistent

2014-04-07 Thread Michael Haggerty
The old error messages emitted for invalid input sometimes said
""/"" and sometimes said "old value"/"new value".
Convert them all to the former.  Update the tests accordingly.

Signed-off-by: Michael Haggerty 
---
 builtin/update-ref.c  |  8 
 t/t1400-update-ref.sh | 14 +++---
 2 files changed, 11 insertions(+), 11 deletions(-)

diff --git a/builtin/update-ref.c b/builtin/update-ref.c
index 13a884a..e4c0854 100644
--- a/builtin/update-ref.c
+++ b/builtin/update-ref.c
@@ -40,7 +40,7 @@ static void update_store_new_sha1(const char *command,
  const char *newvalue)
 {
if (*newvalue && get_sha1(newvalue, update->new_sha1))
-   die("%s %s: invalid new value: %s",
+   die("%s %s: invalid : %s",
command, update->ref_name, newvalue);
 }
 
@@ -49,7 +49,7 @@ static void update_store_old_sha1(const char *command,
  const char *oldvalue)
 {
if (*oldvalue && get_sha1(oldvalue, update->old_sha1))
-   die("%s %s: invalid old value: %s",
+   die("%s %s: invalid : %s",
command, update->ref_name, oldvalue);
 
/* We have an old value if non-empty, or if empty without -z */
@@ -198,7 +198,7 @@ static const char *parse_cmd_create(struct strbuf *input, 
const char *next)
die("create %s missing ", update->ref_name);
 
if (is_null_sha1(update->new_sha1))
-   die("create %s given zero new value", update->ref_name);
+   die("create %s given zero ", update->ref_name);
 
if (*next != line_termination)
die("create %s has extra input: %s", update->ref_name, next);
@@ -220,7 +220,7 @@ static const char *parse_cmd_delete(struct strbuf *input, 
const char *next)
if (!parse_next_arg(input, &next, &oldvalue)) {
update_store_old_sha1("delete", update, oldvalue.buf);
if (update->have_old && is_null_sha1(update->old_sha1))
-   die("delete %s given zero old value", update->ref_name);
+   die("delete %s given zero ", 
update->ref_name);
} else if (!line_termination)
die("delete %s missing [] NUL", update->ref_name);
 
diff --git a/t/t1400-update-ref.sh b/t/t1400-update-ref.sh
index f6c6e96..ef61fe3 100755
--- a/t/t1400-update-ref.sh
+++ b/t/t1400-update-ref.sh
@@ -518,21 +518,21 @@ test_expect_success 'stdin update ref fails with wrong 
old value' '
 test_expect_success 'stdin update ref fails with bad old value' '
echo "update $c $m does-not-exist" >stdin &&
test_must_fail git update-ref --stdin err &&
-   grep "fatal: update $c: invalid old value: does-not-exist" err &&
+   grep "fatal: update $c: invalid : does-not-exist" err &&
test_must_fail git rev-parse --verify -q $c
 '
 
 test_expect_success 'stdin create ref fails with bad new value' '
echo "create $c does-not-exist" >stdin &&
test_must_fail git update-ref --stdin err &&
-   grep "fatal: create $c: invalid new value: does-not-exist" err &&
+   grep "fatal: create $c: invalid : does-not-exist" err &&
test_must_fail git rev-parse --verify -q $c
 '
 
 test_expect_success 'stdin create ref fails with zero new value' '
echo "create $c " >stdin &&
test_must_fail git update-ref --stdin err &&
-   grep "fatal: create $c given zero new value" err &&
+   grep "fatal: create $c given zero " err &&
test_must_fail git rev-parse --verify -q $c
 '
 
@@ -556,7 +556,7 @@ test_expect_success 'stdin delete ref fails with wrong old 
value' '
 test_expect_success 'stdin delete ref fails with zero old value' '
echo "delete $a " >stdin &&
test_must_fail git update-ref --stdin err &&
-   grep "fatal: delete $a given zero old value" err &&
+   grep "fatal: delete $a given zero " err &&
git rev-parse $m >expect &&
git rev-parse $a >actual &&
test_cmp expect actual
@@ -840,14 +840,14 @@ test_expect_success 'stdin -z update ref fails with wrong 
old value' '
 test_expect_success 'stdin -z update ref fails with bad old value' '
printf $F "update $c" "$m" "does-not-exist" >stdin &&
test_must_fail git update-ref -z --stdin err &&
-   grep "fatal: update $c: invalid old value: does-not-exist" err &&
+   grep "fatal: update $c: invalid : does-not-exist" err &&
test_must_fail git rev-parse --verify -q $c
 '
 
 test_expect_success 'stdin -z create ref fails with bad new value' '
printf $F "create $c" "does-not-exist" >stdin &&
test_must_fail git update-ref -z --stdin err &&
-   grep "fatal: create $c: invalid new value: does-not-exist" err &&
+   grep "fatal: create $c: invalid : does-not-exist" err &&
test_must_fail git rev-parse --verify -q $c
 '
 
@@ -878,7 +878,7 @@ test_expect_success 'stdin -z delete ref fails with wrong 
old value' '
 test_expect_

[PATCH v3 23/27] struct ref_update: store refname as a FLEX_ARRAY

2014-04-07 Thread Michael Haggerty
Signed-off-by: Michael Haggerty 
---
 refs.c | 15 ++-
 1 file changed, 6 insertions(+), 9 deletions(-)

diff --git a/refs.c b/refs.c
index b6778aa..2ff195f 100644
--- a/refs.c
+++ b/refs.c
@@ -3274,11 +3274,11 @@ static int update_ref_write(const char *action, const 
char *refname,
  * value or to zero to ensure the ref does not exist before update.
  */
 struct ref_update {
-   const char *refname;
unsigned char new_sha1[20];
unsigned char old_sha1[20];
int flags; /* REF_NODEREF? */
int have_old; /* 1 if old_sha1 is valid, 0 otherwise */
+   const char refname[FLEX_ARRAY];
 };
 
 /*
@@ -3301,12 +3301,8 @@ static void ref_transaction_free(struct ref_transaction 
*transaction)
 {
int i;
 
-   for (i = 0; i < transaction->nr; i++) {
-   struct ref_update *update = transaction->updates[i];
-
-   free((char *)update->refname);
-   free(update);
-   }
+   for (i = 0; i < transaction->nr; i++)
+   free(transaction->updates[i]);
 
free(transaction->updates);
free(transaction);
@@ -3320,9 +3316,10 @@ void ref_transaction_rollback(struct ref_transaction 
*transaction)
 static struct ref_update *add_update(struct ref_transaction *transaction,
 const char *refname)
 {
-   struct ref_update *update = xcalloc(1, sizeof(*update));
+   size_t len = strlen(refname);
+   struct ref_update *update = xcalloc(1, sizeof(*update) + len + 1);
 
-   update->refname = xstrdup(refname);
+   strcpy((char *)update->refname, refname);
ALLOC_GROW(transaction->updates, transaction->nr + 1, 
transaction->alloc);
transaction->updates[transaction->nr++] = update;
return update;
-- 
1.9.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


[PATCH v3 18/27] update-ref --stdin: harmonize error messages

2014-04-07 Thread Michael Haggerty
Make (most of) the error messages for invalid input have the same
format [1]:

$COMMAND [SP $REFNAME]: $MESSAGE

Update the tests accordingly.

[1] A few error messages are left with their old form, because
$COMMAND and $REFNAME aren't passed all the way down the call
stack.  Maybe those sites should be changed some day, too.

Signed-off-by: Michael Haggerty 
---
 builtin/update-ref.c  | 24 
 t/t1400-update-ref.sh | 32 
 2 files changed, 28 insertions(+), 28 deletions(-)

diff --git a/builtin/update-ref.c b/builtin/update-ref.c
index 0d5f1d0..423c5c3 100644
--- a/builtin/update-ref.c
+++ b/builtin/update-ref.c
@@ -202,19 +202,19 @@ static const char *parse_cmd_update(struct strbuf *input, 
const char *next)
 
update->ref_name = parse_refname(input, &next);
if (!update->ref_name)
-   die("update line missing ");
+   die("update: missing ");
 
if (parse_next_sha1(input, &next, update->new_sha1,
"update", update->ref_name,
PARSE_SHA1_ALLOW_EMPTY))
-   die("update %s missing ", update->ref_name);
+   die("update %s: missing ", update->ref_name);
 
update->have_old = !parse_next_sha1(input, &next, update->old_sha1,
"update", update->ref_name,
PARSE_SHA1_OLD);
 
if (*next != line_termination)
-   die("update %s has extra input: %s", update->ref_name, next);
+   die("update %s: extra input: %s", update->ref_name, next);
 
return next;
 }
@@ -227,17 +227,17 @@ static const char *parse_cmd_create(struct strbuf *input, 
const char *next)
 
update->ref_name = parse_refname(input, &next);
if (!update->ref_name)
-   die("create line missing ");
+   die("create: missing ");
 
if (parse_next_sha1(input, &next, update->new_sha1,
"create", update->ref_name, 0))
-   die("create %s missing ", update->ref_name);
+   die("create %s: missing ", update->ref_name);
 
if (is_null_sha1(update->new_sha1))
-   die("create %s given zero ", update->ref_name);
+   die("create %s: zero ", update->ref_name);
 
if (*next != line_termination)
-   die("create %s has extra input: %s", update->ref_name, next);
+   die("create %s: extra input: %s", update->ref_name, next);
 
return next;
 }
@@ -250,19 +250,19 @@ static const char *parse_cmd_delete(struct strbuf *input, 
const char *next)
 
update->ref_name = parse_refname(input, &next);
if (!update->ref_name)
-   die("delete line missing ");
+   die("delete: missing ");
 
if (parse_next_sha1(input, &next, update->old_sha1,
"delete", update->ref_name, PARSE_SHA1_OLD)) {
update->have_old = 0;
} else {
if (is_null_sha1(update->old_sha1))
-   die("delete %s given zero ", 
update->ref_name);
+   die("delete %s: zero ", update->ref_name);
update->have_old = 1;
}
 
if (*next != line_termination)
-   die("delete %s has extra input: %s", update->ref_name, next);
+   die("delete %s: extra input: %s", update->ref_name, next);
 
return next;
 }
@@ -275,7 +275,7 @@ static const char *parse_cmd_verify(struct strbuf *input, 
const char *next)
 
update->ref_name = parse_refname(input, &next);
if (!update->ref_name)
-   die("verify line missing ");
+   die("verify: missing ");
 
if (parse_next_sha1(input, &next, update->old_sha1,
"verify", update->ref_name, PARSE_SHA1_OLD)) {
@@ -286,7 +286,7 @@ static const char *parse_cmd_verify(struct strbuf *input, 
const char *next)
}
 
if (*next != line_termination)
-   die("verify %s has extra input: %s", update->ref_name, next);
+   die("verify %s: extra input: %s", update->ref_name, next);
 
return next;
 }
diff --git a/t/t1400-update-ref.sh b/t/t1400-update-ref.sh
index 1db0689..48ccc4d 100755
--- a/t/t1400-update-ref.sh
+++ b/t/t1400-update-ref.sh
@@ -371,7 +371,7 @@ test_expect_success 'stdin fails on junk after quoted 
argument' '
 test_expect_success 'stdin fails create with no ref' '
echo "create " >stdin &&
test_must_fail git update-ref --stdin err &&
-   grep "fatal: create line missing " err
+   grep "fatal: create: missing " err
 '
 
 test_expect_success 'stdin fails create with bad ref name' '
@@ -383,19 +383,19 @@ test_expect_success 'stdin fails create with bad ref 
name' '
 test_expect_success 'stdin fails create with no new value' '
echo "create $a" >stdin &&
test_must_fail git updat

[PATCH v3 15/27] update-ref --stdin -z: deprecate interpreting the empty string as zeros

2014-04-07 Thread Michael Haggerty
In the original version of this command, for the single case of the
"update" command's , the empty string was interpreted as
being equivalent to 40 "0"s.  This shorthand is unnecessary (binary
input will usually be generated programmatically anyway), and it
complicates the parser and the documentation.

So gently deprecate this usage: remove its description from the
documentation and emit a warning if it is found.  But for reasons of
backwards compatibility, continue to accept it.

Helped-by: Brad King 
Signed-off-by: Michael Haggerty 
---
 Documentation/git-update-ref.txt | 18 --
 builtin/update-ref.c |  2 ++
 t/t1400-update-ref.sh|  5 +++--
 3 files changed, 17 insertions(+), 8 deletions(-)

diff --git a/Documentation/git-update-ref.txt b/Documentation/git-update-ref.txt
index 0a0a551..c8f5ae5 100644
--- a/Documentation/git-update-ref.txt
+++ b/Documentation/git-update-ref.txt
@@ -68,7 +68,12 @@ performs all modifications together.  Specify commands of 
the form:
option SP  LF
 
 Quote fields containing whitespace as if they were strings in C source
-code.  Alternatively, use `-z` to specify commands without quoting:
+code; i.e., surrounded by double-quotes and with backslash escapes.
+Use 40 "0" characters or the empty string to specify a zero value.  To
+specify a missing value, omit the value and its preceding SP entirely.
+
+Alternatively, use `-z` to specify in NUL-terminated format, without
+quoting:
 
update SP  NUL  NUL [] NUL
create SP  NUL  NUL
@@ -76,8 +81,12 @@ code.  Alternatively, use `-z` to specify commands without 
quoting:
verify SP  NUL [] NUL
option SP  NUL
 
-Lines of any other format or a repeated  produce an error.
-Command meanings are:
+In this format, use 40 "0" to specify a zero value, and use the empty
+string to specify a missing value.
+
+In either format, values can be specified in any form that Git
+recognizes as an object name.  Commands in any other format or a
+repeated  produce an error.  Command meanings are:
 
 update::
Set  to  after verifying , if given.
@@ -102,9 +111,6 @@ option::
The only valid option is `no-deref` to avoid dereferencing
a symbolic ref.
 
-Use 40 "0" or the empty string to specify a zero value, except that
-with `-z` an empty  is considered missing.
-
 If all s can be locked with matching s
 simultaneously, all modifications are performed.  Otherwise, no
 modifications are performed.  Note that while each individual
diff --git a/builtin/update-ref.c b/builtin/update-ref.c
index c61120f..6f3b909 100644
--- a/builtin/update-ref.c
+++ b/builtin/update-ref.c
@@ -154,6 +154,8 @@ static int parse_next_sha1(struct strbuf *input, const char 
**next,
goto invalid;
} else if (flags & PARSE_SHA1_ALLOW_EMPTY) {
/* With -z, treat an empty value as all zeros: */
+   warning("%s %s: missing , treating as zero",
+   command, refname);
hashclr(sha1);
} else {
/*
diff --git a/t/t1400-update-ref.sh b/t/t1400-update-ref.sh
index 15f5bfd..2d61cce 100755
--- a/t/t1400-update-ref.sh
+++ b/t/t1400-update-ref.sh
@@ -730,10 +730,11 @@ test_expect_success 'stdin -z fails update with bad ref 
name' '
grep "fatal: invalid ref format: ~a" err
 '
 
-test_expect_success 'stdin -z treats empty new value as zeros' '
+test_expect_success 'stdin -z emits warning with empty new value' '
git update-ref $a $m &&
printf $F "update $a" "" "" >stdin &&
-   git update-ref -z --stdin err &&
+   grep "warning: update $a: missing , treating as zero" err &&
test_must_fail git rev-parse --verify -q $a
 '
 
-- 
1.9.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


[PATCH v3 25/27] struct ref_update: add a lock field

2014-04-07 Thread Michael Haggerty
Now that we manage ref_update objects internally, we can use them to
hold some of the scratch space we need when actually carrying out the
updates.  Store the (struct ref_lock *) there.

Signed-off-by: Michael Haggerty 
---
 refs.c | 36 +++-
 1 file changed, 19 insertions(+), 17 deletions(-)

diff --git a/refs.c b/refs.c
index 33c34df..6fe4bfe8 100644
--- a/refs.c
+++ b/refs.c
@@ -3278,6 +3278,7 @@ struct ref_update {
unsigned char old_sha1[20];
int flags; /* REF_NODEREF? */
int have_old; /* 1 if old_sha1 is valid, 0 otherwise */
+   struct ref_lock *lock;
const char refname[FLEX_ARRAY];
 };
 
@@ -3413,7 +3414,6 @@ int ref_transaction_commit(struct ref_transaction 
*transaction,
int ret = 0, delnum = 0, i;
struct ref_update **updates;
int *types;
-   struct ref_lock **locks;
const char **delnames;
int n = transaction->nr;
 
@@ -3423,7 +3423,6 @@ int ref_transaction_commit(struct ref_transaction 
*transaction,
/* Allocate work space */
updates = xmalloc(sizeof(*updates) * n);
types = xmalloc(sizeof(*types) * n);
-   locks = xcalloc(n, sizeof(*locks));
delnames = xmalloc(sizeof(*delnames) * n);
 
/* Copy, sort, and reject duplicate refs */
@@ -3437,12 +3436,12 @@ int ref_transaction_commit(struct ref_transaction 
*transaction,
for (i = 0; i < n; i++) {
struct ref_update *update = updates[i];
 
-   locks[i] = update_ref_lock(update->refname,
-  (update->have_old ?
-   update->old_sha1 : NULL),
-  update->flags,
-  &types[i], onerr);
-   if (!locks[i]) {
+   update->lock = update_ref_lock(update->refname,
+  (update->have_old ?
+   update->old_sha1 : NULL),
+  update->flags,
+  &types[i], onerr);
+   if (!update->lock) {
ret = 1;
goto cleanup;
}
@@ -3456,19 +3455,23 @@ int ref_transaction_commit(struct ref_transaction 
*transaction,
ret = update_ref_write(msg,
   update->refname,
   update->new_sha1,
-  locks[i], onerr);
-   locks[i] = NULL; /* freed by update_ref_write */
+  update->lock, onerr);
+   update->lock = NULL; /* freed by update_ref_write */
if (ret)
goto cleanup;
}
}
 
/* Perform deletes now that updates are safely completed */
-   for (i = 0; i < n; i++)
-   if (locks[i]) {
-   delnames[delnum++] = locks[i]->ref_name;
-   ret |= delete_ref_loose(locks[i], types[i]);
+   for (i = 0; i < n; i++) {
+   struct ref_update *update = updates[i];
+
+   if (update->lock) {
+   delnames[delnum++] = update->lock->ref_name;
+   ret |= delete_ref_loose(update->lock, types[i]);
}
+   }
+
ret |= repack_without_refs(delnames, delnum);
for (i = 0; i < delnum; i++)
unlink_or_warn(git_path("logs/%s", delnames[i]));
@@ -3476,11 +3479,10 @@ int ref_transaction_commit(struct ref_transaction 
*transaction,
 
 cleanup:
for (i = 0; i < n; i++)
-   if (locks[i])
-   unlock_ref(locks[i]);
+   if (updates[i]->lock)
+   unlock_ref(updates[i]->lock);
free(updates);
free(types);
-   free(locks);
free(delnames);
ref_transaction_free(transaction);
return ret;
-- 
1.9.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


[PATCH v3 09/27] update-ref.c: extract a new function, parse_refname()

2014-04-07 Thread Michael Haggerty
There is no reason to obscure the fact that parse_first_arg() always
parses refnames.  Form the new function by combining parse_first_arg()
and update_store_ref_name().

Signed-off-by: Michael Haggerty 
---
 builtin/update-ref.c | 90 
 1 file changed, 41 insertions(+), 49 deletions(-)

diff --git a/builtin/update-ref.c b/builtin/update-ref.c
index 51adf2d..0dc2061 100644
--- a/builtin/update-ref.c
+++ b/builtin/update-ref.c
@@ -35,14 +35,6 @@ static struct ref_update *update_alloc(void)
return update;
 }
 
-static void update_store_ref_name(struct ref_update *update,
- const char *ref_name)
-{
-   if (check_refname_format(ref_name, REFNAME_ALLOW_ONELEVEL))
-   die("invalid ref format: %s", ref_name);
-   update->ref_name = xstrdup(ref_name);
-}
-
 static void update_store_new_sha1(struct ref_update *update,
  const char *newvalue)
 {
@@ -86,23 +78,35 @@ static const char *parse_arg(const char *next, struct 
strbuf *arg)
 }
 
 /*
- * Parse the argument immediately after "command SP".  If not -z, then
- * handle C-quoting.  Write the argument to arg.  Set *next to point
- * at the character that terminates the argument.  Die if C-quoting is
- * malformed.
+ * Parse the reference name immediately after "command SP".  If not
+ * -z, then handle C-quoting.  Return a pointer to a newly allocated
+ * string containing the name of the reference, or NULL if there was
+ * an error.  Update *next to point at the character that terminates
+ * the argument.  Die if C-quoting is malformed or the reference name
+ * is invalid.
  */
-static void parse_first_arg(struct strbuf *input, const char **next,
-   struct strbuf *arg)
+static char *parse_refname(struct strbuf *input, const char **next)
 {
-   strbuf_reset(arg);
+   struct strbuf ref = STRBUF_INIT;
+
if (line_termination) {
/* Without -z, use the next argument */
-   *next = parse_arg(*next, arg);
+   *next = parse_arg(*next, &ref);
} else {
/* With -z, use everything up to the next NUL */
-   strbuf_addstr(arg, *next);
-   *next += arg->len;
+   strbuf_addstr(&ref, *next);
+   *next += ref.len;
+   }
+
+   if (!ref.len) {
+   strbuf_release(&ref);
+   return NULL;
}
+
+   if (check_refname_format(ref.buf, REFNAME_ALLOW_ONELEVEL))
+   die("invalid ref format: %s", ref.buf);
+
+   return strbuf_detach(&ref, NULL);
 }
 
 /*
@@ -150,111 +154,99 @@ static int parse_next_arg(struct strbuf *input, const 
char **next,
 
 static const char *parse_cmd_update(struct strbuf *input, const char *next)
 {
-   struct strbuf ref = STRBUF_INIT;
struct strbuf newvalue = STRBUF_INIT;
struct strbuf oldvalue = STRBUF_INIT;
struct ref_update *update;
 
update = update_alloc();
 
-   parse_first_arg(input, &next, &ref);
-   if (ref.buf[0])
-   update_store_ref_name(update, ref.buf);
-   else
+   update->ref_name = parse_refname(input, &next);
+   if (!update->ref_name)
die("update line missing ");
 
if (!parse_next_arg(input, &next, &newvalue))
update_store_new_sha1(update, newvalue.buf);
else
-   die("update %s missing ", ref.buf);
+   die("update %s missing ", update->ref_name);
 
if (!parse_next_arg(input, &next, &oldvalue)) {
update_store_old_sha1(update, oldvalue.buf);
if (*next != line_termination)
-   die("update %s has extra input: %s", ref.buf, next);
+   die("update %s has extra input: %s", update->ref_name, 
next);
} else if (!line_termination)
-   die("update %s missing [] NUL", ref.buf);
+   die("update %s missing [] NUL", update->ref_name);
 
return next;
 }
 
 static const char *parse_cmd_create(struct strbuf *input, const char *next)
 {
-   struct strbuf ref = STRBUF_INIT;
struct strbuf newvalue = STRBUF_INIT;
struct ref_update *update;
 
update = update_alloc();
 
-   parse_first_arg(input, &next, &ref);
-   if (ref.buf[0])
-   update_store_ref_name(update, ref.buf);
-   else
+   update->ref_name = parse_refname(input, &next);
+   if (!update->ref_name)
die("create line missing ");
 
if (!parse_next_arg(input, &next, &newvalue))
update_store_new_sha1(update, newvalue.buf);
else
-   die("create %s missing ", ref.buf);
+   die("create %s missing ", update->ref_name);
 
if (is_null_sha1(update->new_sha1))
-   die("create %s given zero new value", ref.buf);
+   die("create %s given zero new value", update->ref_

[PATCH v3 05/27] refs.h: rename the action_on_err constants

2014-04-07 Thread Michael Haggerty
Given that these constants are only being used when updating
references, it is inappropriate to give them such generic names as
"DIE_ON_ERR".  So prefix their names with "UPDATE_REFS_".

Signed-off-by: Michael Haggerty 
---
 builtin/checkout.c |  2 +-
 builtin/clone.c|  9 +
 builtin/merge.c|  6 +++---
 builtin/notes.c|  6 +++---
 builtin/reset.c|  6 --
 builtin/update-ref.c   |  5 +++--
 contrib/examples/builtin-fetch--tool.c |  3 ++-
 notes-cache.c  |  2 +-
 notes-utils.c  |  3 ++-
 refs.c | 18 +-
 refs.h |  9 +++--
 11 files changed, 40 insertions(+), 29 deletions(-)

diff --git a/builtin/checkout.c b/builtin/checkout.c
index 1b86d9c..6bf2318 100644
--- a/builtin/checkout.c
+++ b/builtin/checkout.c
@@ -624,7 +624,7 @@ static void update_refs_for_switch(const struct 
checkout_opts *opts,
/* Nothing to do. */
} else if (opts->force_detach || !new->path) {  /* No longer on any 
branch. */
update_ref(msg.buf, "HEAD", new->commit->object.sha1, NULL,
-  REF_NODEREF, DIE_ON_ERR);
+  REF_NODEREF, UPDATE_REFS_DIE_ON_ERR);
if (!opts->quiet) {
if (old->path && advice_detached_head)
detach_advice(new->name);
diff --git a/builtin/clone.c b/builtin/clone.c
index 9b3c04d..b12989d 100644
--- a/builtin/clone.c
+++ b/builtin/clone.c
@@ -521,7 +521,7 @@ static void write_followtags(const struct ref *refs, const 
char *msg)
if (!has_sha1_file(ref->old_sha1))
continue;
update_ref(msg, ref->name, ref->old_sha1,
-  NULL, 0, DIE_ON_ERR);
+  NULL, 0, UPDATE_REFS_DIE_ON_ERR);
}
 }
 
@@ -589,14 +589,15 @@ static void update_head(const struct ref *our, const 
struct ref *remote,
create_symref("HEAD", our->name, NULL);
if (!option_bare) {
const char *head = skip_prefix(our->name, 
"refs/heads/");
-   update_ref(msg, "HEAD", our->old_sha1, NULL, 0, 
DIE_ON_ERR);
+   update_ref(msg, "HEAD", our->old_sha1, NULL, 0,
+  UPDATE_REFS_DIE_ON_ERR);
install_branch_config(0, head, option_origin, 
our->name);
}
} else if (our) {
struct commit *c = lookup_commit_reference(our->old_sha1);
/* --branch specifies a non-branch (i.e. tags), detach HEAD */
update_ref(msg, "HEAD", c->object.sha1,
-  NULL, REF_NODEREF, DIE_ON_ERR);
+  NULL, REF_NODEREF, UPDATE_REFS_DIE_ON_ERR);
} else if (remote) {
/*
 * We know remote HEAD points to a non-branch, or
@@ -604,7 +605,7 @@ static void update_head(const struct ref *our, const struct 
ref *remote,
 * Detach HEAD in all these cases.
 */
update_ref(msg, "HEAD", remote->old_sha1,
-  NULL, REF_NODEREF, DIE_ON_ERR);
+  NULL, REF_NODEREF, UPDATE_REFS_DIE_ON_ERR);
}
 }
 
diff --git a/builtin/merge.c b/builtin/merge.c
index e15d0e1..7d1d83e 100644
--- a/builtin/merge.c
+++ b/builtin/merge.c
@@ -398,7 +398,7 @@ static void finish(struct commit *head_commit,
const char *argv_gc_auto[] = { "gc", "--auto", NULL };
update_ref(reflog_message.buf, "HEAD",
new_head, head, 0,
-   DIE_ON_ERR);
+   UPDATE_REFS_DIE_ON_ERR);
/*
 * We ignore errors in 'gc --auto', since the
 * user should see them.
@@ -1222,7 +1222,7 @@ int cmd_merge(int argc, const char **argv, const char 
*prefix)
die(_("%s - not something we can merge"), argv[0]);
read_empty(remote_head->object.sha1, 0);
update_ref("initial pull", "HEAD", remote_head->object.sha1,
-  NULL, 0, DIE_ON_ERR);
+  NULL, 0, UPDATE_REFS_DIE_ON_ERR);
goto done;
} else {
struct strbuf merge_names = STRBUF_INIT;
@@ -1339,7 +1339,7 @@ int cmd_merge(int argc, const char **argv, const char 
*prefix)
}
 
update_ref("updating ORIG_HEAD", "ORIG_HEAD", head_commit->object.sha1,
-  NULL, 0, DIE_ON_ERR);
+  NULL, 0, UPDATE_REFS_DIE_ON_ERR);
 
if (remoteheads && !common)
; /* No common ancestors found. We need a real merge. */
diff --git

[PATCH v3 01/27] t1400: fix name and expected result of one test

2014-04-07 Thread Michael Haggerty
The test

stdin -z create ref fails with zero new value

actually passes an empty new value, not a zero new value.  So rename
the test s/zero/empty/, and change the expected error from

fatal: create $c given zero new value

to

fatal: create $c missing 

Of course, this makes the test fail now, because although "git
update-ref" tries to distinguish between these two errors, it does not
succeed in this situation.  Fixing it is more than a one-liner, so
mark the test test_expect_failure for now.  The failure will be fixed
later in this patch series.

Signed-off-by: Michael Haggerty 
---
 t/t1400-update-ref.sh | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/t/t1400-update-ref.sh b/t/t1400-update-ref.sh
index 6ffd82f..fa927d2 100755
--- a/t/t1400-update-ref.sh
+++ b/t/t1400-update-ref.sh
@@ -827,10 +827,10 @@ test_expect_success 'stdin -z create ref fails with bad 
new value' '
test_must_fail git rev-parse --verify -q $c
 '
 
-test_expect_success 'stdin -z create ref fails with zero new value' '
+test_expect_failure 'stdin -z create ref fails with empty new value' '
printf $F "create $c" "" >stdin &&
test_must_fail git update-ref -z --stdin err &&
-   grep "fatal: create $c given zero new value" err &&
+   grep "fatal: create $c missing " err &&
test_must_fail git rev-parse --verify -q $c
 '
 
-- 
1.9.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


[PATCH v3 02/27] t1400: provide more usual input to the command

2014-04-07 Thread Michael Haggerty
The old version was passing (among other things)

update SP refs/heads/c NUL NUL 0{40} NUL

to "git update-ref -z --stdin" to test whether the old-value check for
c is working.  But the  is empty, which is a bit off the
beaten track.

So, to be sure that we are testing what we want to test, provide an
actual  on the "update" line.

Signed-off-by: Michael Haggerty 
---
 t/t1400-update-ref.sh | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/t/t1400-update-ref.sh b/t/t1400-update-ref.sh
index fa927d2..29391c6 100755
--- a/t/t1400-update-ref.sh
+++ b/t/t1400-update-ref.sh
@@ -912,7 +912,7 @@ test_expect_success 'stdin -z update refs works with 
identity updates' '
 
 test_expect_success 'stdin -z update refs fails with wrong old value' '
git update-ref $c $m &&
-   printf $F "update $a" "$m" "$m" "update $b" "$m" "$m" "update $c" "" 
"$Z" >stdin &&
+   printf $F "update $a" "$m" "$m" "update $b" "$m" "$m" "update $c" "$m" 
"$Z" >stdin &&
test_must_fail git update-ref -z --stdin err &&
grep "fatal: Cannot lock the ref '"'"'$c'"'"'" err &&
git rev-parse $m >expect &&
-- 
1.9.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


[PATCH v3 04/27] t1400: add some more tests involving quoted arguments

2014-04-07 Thread Michael Haggerty
Previously there were no good tests of C-quoted arguments.

Signed-off-by: Michael Haggerty 
---
 t/t1400-update-ref.sh | 26 +-
 1 file changed, 25 insertions(+), 1 deletion(-)

diff --git a/t/t1400-update-ref.sh b/t/t1400-update-ref.sh
index 774f8c5..00862bc 100755
--- a/t/t1400-update-ref.sh
+++ b/t/t1400-update-ref.sh
@@ -350,12 +350,18 @@ test_expect_success 'stdin fails on unknown command' '
grep "fatal: unknown command: unknown $a" err
 '
 
-test_expect_success 'stdin fails on badly quoted input' '
+test_expect_success 'stdin fails on unbalanced quotes' '
echo "create $a \"master" >stdin &&
test_must_fail git update-ref --stdin err &&
grep "fatal: badly quoted argument: \\\"master" err
 '
 
+test_expect_success 'stdin fails on invalid escape' '
+   echo "create $a \"ma\zter\"" >stdin &&
+   test_must_fail git update-ref --stdin err &&
+   grep "fatal: badly quoted argument: \\\"mazter\\\"" err
+'
+
 test_expect_success 'stdin fails on junk after quoted argument' '
echo "create \"$a\"master" >stdin &&
test_must_fail git update-ref --stdin err &&
@@ -458,6 +464,24 @@ test_expect_success 'stdin create ref works' '
test_cmp expect actual
 '
 
+test_expect_success 'stdin succeeds with quoted argument' '
+   git update-ref -d $a &&
+   echo "create $a \"$m\"" >stdin &&
+   git update-ref --stdin expect &&
+   git rev-parse $a >actual &&
+   test_cmp expect actual
+'
+
+test_expect_success 'stdin succeeds with escaped character' '
+   git update-ref -d $a &&
+   echo "create $a \"ma\\163ter\"" >stdin &&
+   git update-ref --stdin expect &&
+   git rev-parse $a >actual &&
+   test_cmp expect actual
+'
+
 test_expect_success 'stdin update ref creates with zero old value' '
echo "update $b $m $Z" >stdin &&
git update-ref --stdin http://vger.kernel.org/majordomo-info.html


[PATCH v3 08/27] parse_cmd_verify(): copy old_sha1 instead of evaluating twice

2014-04-07 Thread Michael Haggerty
Aside from avoiding a tiny bit of work, this makes it transparently
obvious that old_sha1 and new_sha1 are identical.  It is arguably a
bit silly to have to set new_sha1 in order to verify old_sha1, but
that is a problem for another day.

Signed-off-by: Michael Haggerty 
---
 builtin/update-ref.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/builtin/update-ref.c b/builtin/update-ref.c
index 5f197fe..51adf2d 100644
--- a/builtin/update-ref.c
+++ b/builtin/update-ref.c
@@ -249,7 +249,7 @@ static const char *parse_cmd_verify(struct strbuf *input, 
const char *next)
 
if (!parse_next_arg(input, &next, &value)) {
update_store_old_sha1(update, value.buf);
-   update_store_new_sha1(update, value.buf);
+   hashcpy(update->new_sha1, update->old_sha1);
} else if (!line_termination)
die("verify %s missing [] NUL", ref.buf);
 
-- 
1.9.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


[PATCH v3 07/27] update-ref --stdin: read the whole input at once

2014-04-07 Thread Michael Haggerty
Read the whole input into a strbuf at once, and then parse it from
there.  This might also be a tad faster, but that is not the point.
The point is to decouple the parsing code from the input source (the
old parsing code had to read new data even in the middle of commands).
Add docstrings for the parsing functions.

Signed-off-by: Michael Haggerty 
---
 builtin/update-ref.c | 170 ---
 1 file changed, 108 insertions(+), 62 deletions(-)

diff --git a/builtin/update-ref.c b/builtin/update-ref.c
index a8a68e8..5f197fe 100644
--- a/builtin/update-ref.c
+++ b/builtin/update-ref.c
@@ -85,44 +85,70 @@ static const char *parse_arg(const char *next, struct 
strbuf *arg)
return next;
 }
 
-static const char *parse_first_arg(const char *next, struct strbuf *arg)
+/*
+ * Parse the argument immediately after "command SP".  If not -z, then
+ * handle C-quoting.  Write the argument to arg.  Set *next to point
+ * at the character that terminates the argument.  Die if C-quoting is
+ * malformed.
+ */
+static void parse_first_arg(struct strbuf *input, const char **next,
+   struct strbuf *arg)
 {
-   /* Parse argument immediately after "command SP" */
strbuf_reset(arg);
if (line_termination) {
/* Without -z, use the next argument */
-   next = parse_arg(next, arg);
+   *next = parse_arg(*next, arg);
} else {
-   /* With -z, use rest of first NUL-terminated line */
-   strbuf_addstr(arg, next);
-   next = next + arg->len;
+   /* With -z, use everything up to the next NUL */
+   strbuf_addstr(arg, *next);
+   *next += arg->len;
}
-   return next;
 }
 
-static const char *parse_next_arg(const char *next, struct strbuf *arg)
+/*
+ * Parse a SP/NUL separator followed by the next SP- or NUL-terminated
+ * argument, if any.  If there is an argument, write it to arg, set
+ * *next to point at the character terminating the argument, and
+ * return 0.  If there is no argument at all (not even the empty
+ * string), return a non-zero result and leave *next unchanged.
+ */
+static int parse_next_arg(struct strbuf *input, const char **next,
+ struct strbuf *arg)
 {
-   /* Parse next SP-terminated or NUL-terminated argument, if any */
strbuf_reset(arg);
if (line_termination) {
/* Without -z, consume SP and use next argument */
-   if (!*next)
-   return NULL;
-   if (*next != ' ')
-   die("expected SP but got: %s", next);
-   next = parse_arg(next + 1, arg);
+   if (!**next || **next == line_termination)
+   return -1;
+   if (**next != ' ')
+   die("expected SP but got: %s", *next);
+   (*next)++;
+   *next = parse_arg(*next, arg);
} else {
/* With -z, read the next NUL-terminated line */
-   if (*next)
-   die("expected NUL but got: %s", next);
-   if (strbuf_getline(arg, stdin, '\0') == EOF)
-   return NULL;
-   next = arg->buf + arg->len;
+   if (**next)
+   die("expected NUL but got: %s", *next);
+   (*next)++;
+   if (*next == input->buf + input->len)
+   return -1;
+   strbuf_addstr(arg, *next);
+   *next += arg->len;
}
-   return next;
+   return 0;
 }
 
-static void parse_cmd_update(const char *next)
+
+/*
+ * The following five parse_cmd_*() functions parse the corresponding
+ * command.  In each case, next points at the character following the
+ * command name and the following space.  They each return a pointer
+ * to the character terminating the command, and die with an
+ * explanatory message if there are any parsing problems.  All of
+ * these functions handle either text or binary format input,
+ * depending on how line_termination is set.
+ */
+
+static const char *parse_cmd_update(struct strbuf *input, const char *next)
 {
struct strbuf ref = STRBUF_INIT;
struct strbuf newvalue = STRBUF_INIT;
@@ -131,26 +157,28 @@ static void parse_cmd_update(const char *next)
 
update = update_alloc();
 
-   if ((next = parse_first_arg(next, &ref)) != NULL && ref.buf[0])
+   parse_first_arg(input, &next, &ref);
+   if (ref.buf[0])
update_store_ref_name(update, ref.buf);
else
die("update line missing ");
 
-   if ((next = parse_next_arg(next, &newvalue)) != NULL)
+   if (!parse_next_arg(input, &next, &newvalue))
update_store_new_sha1(update, newvalue.buf);
else
die("update %s missing ", ref.buf);
 
-   if ((next = parse_next_arg(next, &oldvalue)) != N

[PATCH v3 03/27] parse_arg(): really test that argument is properly terminated

2014-04-07 Thread Michael Haggerty
The old parse_arg(), when fed an argument

"refs/heads/a"master

parsed 'refs/heads/a' off of the front of the argument and considered
itself successful.  It was only when parse_next_arg() tried to parse
the *next* argument that a problem was noticed.  But in fact, the
definition of the input format requires arguments to be terminated by
SP or NUL, so *this* argument is already erroneous and parse_arg()
should diagnose the problem.

So teach parse_arg() to verify that C-quoted arguments are terminated
correctly.  If not, emit a more specific error message.

There is no corresponding error case of a non-C-quoted argument that
is not terminated correctly, because the end of a non-quoted argument
is *by definition* a space or NUL, so there is no way to insert other
junk between the "end" of the argument and the argument terminator.

Adjust the tests to expect the new error message.  Add a docstring to
the function, incorporating the comments that were formerly within the
function plus some added information.

Signed-off-by: Michael Haggerty 
---
 builtin/update-ref.c  | 20 +++-
 t/t1400-update-ref.sh |  4 ++--
 2 files changed, 17 insertions(+), 7 deletions(-)

diff --git a/builtin/update-ref.c b/builtin/update-ref.c
index 1292cfe..02b5f95 100644
--- a/builtin/update-ref.c
+++ b/builtin/update-ref.c
@@ -62,16 +62,26 @@ static void update_store_old_sha1(struct ref_update *update,
update->have_old = *oldvalue || line_termination;
 }
 
+/*
+ * Parse one whitespace- or NUL-terminated, possibly C-quoted argument
+ * and append the result to arg.  Return a pointer to the terminator.
+ * Die if there is an error in how the argument is C-quoted.  This
+ * function is only used if not -z.
+ */
 static const char *parse_arg(const char *next, struct strbuf *arg)
 {
-   /* Parse SP-terminated, possibly C-quoted argument */
-   if (*next != '"')
+   if (*next == '"') {
+   const char *orig = next;
+
+   if (unquote_c_style(arg, next, &next))
+   die("badly quoted argument: %s", orig);
+   if (*next && !isspace(*next))
+   die("unexpected character after quoted argument: %s", 
orig);
+   } else {
while (*next && !isspace(*next))
strbuf_addch(arg, *next++);
-   else if (unquote_c_style(arg, next, &next))
-   die("badly quoted argument: %s", next);
+   }
 
-   /* Return position after the argument */
return next;
 }
 
diff --git a/t/t1400-update-ref.sh b/t/t1400-update-ref.sh
index 29391c6..774f8c5 100755
--- a/t/t1400-update-ref.sh
+++ b/t/t1400-update-ref.sh
@@ -356,10 +356,10 @@ test_expect_success 'stdin fails on badly quoted input' '
grep "fatal: badly quoted argument: \\\"master" err
 '
 
-test_expect_success 'stdin fails on arguments not separated by space' '
+test_expect_success 'stdin fails on junk after quoted argument' '
echo "create \"$a\"master" >stdin &&
test_must_fail git update-ref --stdin err &&
-   grep "fatal: expected SP but got: master" err
+   grep "fatal: unexpected character after quoted argument: 
\\\"$a\\\"master" err
 '
 
 test_expect_success 'stdin fails create with no ref' '
-- 
1.9.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


[PATCH v3 00/27] Clean up update-refs --stdin and implement ref_transaction

2014-04-07 Thread Michael Haggerty
Here is v3.  It is also available on GitHub [1].

Thanks to Junio and Brad for their comments about v2.  I think I have
addressed all of your comments (except for Junio's regrets that the
series didn't include a transactional receive-pack).

See the mailing list threads about v1 [2] and v2 [3] and the
longer-term goals of this campaign [4].

Changes since v2:

* Rebased to current master (there were no conflicts)

* Don't allow ref_transation_create() with new_sha1 set to zeros.

* Don't allow ref_transation_delete() with old_sha1 set to zeros.

* Fixed subject lines to use lower-case after the colon.

* Expanded a few commit messages, fixed a comment, and removed some
  "squash" detritus in a commit message.

Cheers,
Michael

[1] https://github.com/mhagger/git, branch ref-transactions
[2] http://thread.gmane.org/gmane.comp.version-control.git/243731
[3] http://thread.gmane.org/gmane.comp.version-control.git/244857
[4] http://article.gmane.org/gmane.comp.version-control.git/243726

Michael Haggerty (27):
  t1400: fix name and expected result of one test
  t1400: provide more usual input to the command
  parse_arg(): really test that argument is properly terminated
  t1400: add some more tests involving quoted arguments
  refs.h: rename the action_on_err constants
  update_refs(): fix constness
  update-ref --stdin: read the whole input at once
  parse_cmd_verify(): copy old_sha1 instead of evaluating 
twice
  update-ref.c: extract a new function, parse_refname()
  update-ref --stdin: improve error messages for invalid values
  update-ref --stdin: make error messages more consistent
  update-ref --stdin: simplify error messages for missing oldvalues
  t1400: test that stdin -z update treats empty  as zeros
  update-ref.c: extract a new function, parse_next_sha1()
  update-ref --stdin -z: deprecate interpreting the empty string as
zeros
  t1400: test one mistake at a time
  update-ref --stdin: improve the error message for unexpected EOF
  update-ref --stdin: harmonize error messages
  refs: add a concept of a reference transaction
  update-ref --stdin: reimplement using reference transactions
  refs: remove API function update_refs()
  struct ref_update: rename field "ref_name" to "refname"
  struct ref_update: store refname as a FLEX_ARRAY
  ref_transaction_commit(): simplify code using temporary variables
  struct ref_update: add a lock field
  struct ref_update: add a type field
  ref_transaction_commit(): work with transaction->updates in place

 Documentation/git-update-ref.txt   |  18 +-
 builtin/checkout.c |   2 +-
 builtin/clone.c|   9 +-
 builtin/merge.c|   6 +-
 builtin/notes.c|   6 +-
 builtin/reset.c|   6 +-
 builtin/update-ref.c   | 425 -
 contrib/examples/builtin-fetch--tool.c |   3 +-
 notes-cache.c  |   2 +-
 notes-utils.c  |   3 +-
 refs.c | 195 +++
 refs.h |  94 ++--
 t/t1400-update-ref.sh  | 100 +---
 13 files changed, 585 insertions(+), 284 deletions(-)

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


[PATCH v3 06/27] update_refs(): fix constness

2014-04-07 Thread Michael Haggerty
The old signature of update_refs() required a
(const struct ref_update **) for its updates_orig argument.  The
"const" is presumably there to promise that the function will not
modify the contents of the structures.

But this declaration does not permit the function to be called with a
(struct ref_update **), which is perfectly legitimate.  C's type
system is not powerful enough to express what we'd like.  So remove
the first "const" from the declaration.

On the other hand, the function *can* promise not to modify the
pointers within the array that is passed to it without inconveniencing
its callers.  So add a "const" that has that effect, making the final
declaration
(struct ref_update * const *).

Signed-off-by: Michael Haggerty 
---
 builtin/update-ref.c | 2 +-
 refs.c   | 2 +-
 refs.h   | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/builtin/update-ref.c b/builtin/update-ref.c
index f6345e5..a8a68e8 100644
--- a/builtin/update-ref.c
+++ b/builtin/update-ref.c
@@ -14,7 +14,7 @@ static const char * const git_update_ref_usage[] = {
 
 static int updates_alloc;
 static int updates_count;
-static const struct ref_update **updates;
+static struct ref_update **updates;
 
 static char line_termination = '\n';
 static int update_flags;
diff --git a/refs.c b/refs.c
index 196984e..1305eb1 100644
--- a/refs.c
+++ b/refs.c
@@ -3306,7 +3306,7 @@ static int ref_update_reject_duplicates(struct ref_update 
**updates, int n,
return 0;
 }
 
-int update_refs(const char *action, const struct ref_update **updates_orig,
+int update_refs(const char *action, struct ref_update * const *updates_orig,
int n, enum action_on_err onerr)
 {
int ret = 0, delnum = 0, i;
diff --git a/refs.h b/refs.h
index a713b34..08e60ac 100644
--- a/refs.h
+++ b/refs.h
@@ -228,7 +228,7 @@ int update_ref(const char *action, const char *refname,
 /**
  * Lock all refs and then perform all modifications.
  */
-int update_refs(const char *action, const struct ref_update **updates,
+int update_refs(const char *action, struct ref_update * const *updates,
int n, enum action_on_err onerr);
 
 extern int parse_hide_refs_config(const char *var, const char *value, const 
char *);
-- 
1.9.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


[PATCH] git-p4: explicitly specify that HEAD is a revision

2014-04-07 Thread Vlad Dogaru
'git p4 rebase' fails with the following message if there is a file
named HEAD in the current directory:

fatal: ambiguous argument 'HEAD': both revision and filename
Use '--' to separate paths from revisions, like this:
'git  [...] -- [...]'

Take the suggestion above and explicitly state that HEAD should be
treated as a revision.

Signed-off-by: Vlad Dogaru 
---
 git-p4.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/git-p4.py b/git-p4.py
index cdfa2df..8d11b25 100755
--- a/git-p4.py
+++ b/git-p4.py
@@ -3086,7 +3086,7 @@ class P4Rebase(Command):
 print "Rebasing the current branch onto %s" % upstream
 oldHead = read_pipe("git rev-parse HEAD").strip()
 system("git rebase %s" % upstream)
-system("git diff-tree --stat --summary -M %s HEAD" % oldHead)
+system("git diff-tree --stat --summary -M %s HEAD --" % oldHead)
 return True
 
 class P4Clone(P4Sync):
-- 
1.8.5.2


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


Re: [PATCH v2 18/25] lockfile: avoid transitory invalid states

2014-04-07 Thread Michael Haggerty
On 04/07/2014 02:12 PM, Johannes Sixt wrote:
> Am 4/7/2014 13:13, schrieb Michael Haggerty:
>> On 04/07/2014 08:16 AM, Johannes Sixt wrote:
>>> Am 4/7/2014 1:34, schrieb Michael Haggerty:
 So, instead of encoding part of the lock_file state in the filename
 field, add a new bit "LOCK_FLAGS_LOCKFILE_ACTIVE" to flags, and use
 this bit to distinguish between a lock_file object that is active
 vs. one that is inactive.  Be careful to set this bit only when
 filename really contains the name of a file that should be deleted on
 cleanup.
>>>
>>> Since this flag is primarily for communication between the main code and a
>>> signal handler, the only safe way is to define the flag as volatile
>>> sig_atomic_t, not to make it a bit of a larger type!
>>
>> Thanks for the feedback.  You are obviously right, and I will fix it.
>>
>> But I have a feeling that this line of thought is going to lead to the
>> signal handler's not being able to do anything.  How far can we afford
>> to pursue strict correctness?  ...
>>
>> The signal handler currently reads
>>
>> lock_file_list
>> lock_file::next
>> lock_file::fd
>> lock_file::owner
>> lock_file::filename
>> *lock_file::filename
>>
>> and writes lock_file_list.  Among other things it calls close(),
>> unlink(), vsnprintf(), and fprintf() (the last two via warning()).
>>
>> But most of these actions are undefined under the C99 standard:
> 
> Good point. But not all is lost because some of the functions are
> well-defined under POSIX, particularly close() and unlink(). (*printf are
> not, though.)
> 
>> I don't have time to rewrite *all* of Git right now, so how can we get
>> reasonable safety and portability within a feasible amount of work?
> 
> It shouldn't be *that* bad. We can make all members volatile, except
> filename (because we wouldn't be able to strcpy(lk->filename, ...) without
> a type cast).
> 
> How far *do* you want to go? I'm certainly not opposed to field-test your
> current changeset (plus and adjustment to use sig_atomic_t) -- overall it
> is an improvement. And then we will see how it works.

For now I think I'd just like to get the biggest problems fixed without
making anything worse.  Given that there might be a GSoC student working
in this neighborhood, he/she might be able to take up the baton.

I changed the patch series to use a new "volatile sig_atomic_t active"
field rather than a bit in a "flags" field.  I'll wait a short time to
see if there is more feedback before pushing it to the list; meanwhile
you can find it here if you have time to look at it and/or test it:

http://github.com/mhagger/git, branch "lock-correctness"

Michael


-- 
Michael Haggerty
mhag...@alum.mit.edu
http://softwareswirl.blogspot.com/
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v2 18/25] lockfile: avoid transitory invalid states

2014-04-07 Thread Johannes Sixt
Am 4/7/2014 13:13, schrieb Michael Haggerty:
> On 04/07/2014 08:16 AM, Johannes Sixt wrote:
>> Am 4/7/2014 1:34, schrieb Michael Haggerty:
>>> So, instead of encoding part of the lock_file state in the filename
>>> field, add a new bit "LOCK_FLAGS_LOCKFILE_ACTIVE" to flags, and use
>>> this bit to distinguish between a lock_file object that is active
>>> vs. one that is inactive.  Be careful to set this bit only when
>>> filename really contains the name of a file that should be deleted on
>>> cleanup.
>>
>> Since this flag is primarily for communication between the main code and a
>> signal handler, the only safe way is to define the flag as volatile
>> sig_atomic_t, not to make it a bit of a larger type!
> 
> Thanks for the feedback.  You are obviously right, and I will fix it.
> 
> But I have a feeling that this line of thought is going to lead to the
> signal handler's not being able to do anything.  How far can we afford
> to pursue strict correctness?  ...
> 
> The signal handler currently reads
> 
> lock_file_list
> lock_file::next
> lock_file::fd
> lock_file::owner
> lock_file::filename
> *lock_file::filename
> 
> and writes lock_file_list.  Among other things it calls close(),
> unlink(), vsnprintf(), and fprintf() (the last two via warning()).
> 
> But most of these actions are undefined under the C99 standard:

Good point. But not all is lost because some of the functions are
well-defined under POSIX, particularly close() and unlink(). (*printf are
not, though.)

> I don't have time to rewrite *all* of Git right now, so how can we get
> reasonable safety and portability within a feasible amount of work?

It shouldn't be *that* bad. We can make all members volatile, except
filename (because we wouldn't be able to strcpy(lk->filename, ...) without
a type cast).

How far *do* you want to go? I'm certainly not opposed to field-test your
current changeset (plus and adjustment to use sig_atomic_t) -- overall it
is an improvement. And then we will see how it works.

Just as food for thought: A compiler barrier should be sufficient to
inhibit that the compiler reorders code across accesses of the volatile
flag. Like in the main code:

strcpy(lk->filename, ...);
BARRIER();
lk->is_active = 1;  /* volatile sig_atomic_t */

and in the signal handler:

if (!lk->is_active)
return;
BARRIER();
unlink(lk->filename);

with some suitable definition of BARRIER(). I don't think that we need an
explicit memory barrier (in practice) because that should be implied by
the context switch leading to the signal handler.

-- Hannes
--
To unsubscribe from this list: send the line "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 18/25] lockfile: avoid transitory invalid states

2014-04-07 Thread Michael Haggerty
On 04/07/2014 08:16 AM, Johannes Sixt wrote:
> Am 4/7/2014 1:34, schrieb Michael Haggerty:
>> Because remove_lock_file() can be called any time by the signal
>> handler, it is important that any lock_file objects that are in the
>> lock_file_list are always in a valid state.  And since lock_file
>> objects are often reused (but are never removed from lock_file_list),
>> that means we have to be careful whenever mutating a lock_file object
>> to always keep it in a well-defined state.
>> ...
>> So, instead of encoding part of the lock_file state in the filename
>> field, add a new bit "LOCK_FLAGS_LOCKFILE_ACTIVE" to flags, and use
>> this bit to distinguish between a lock_file object that is active
>> vs. one that is inactive.  Be careful to set this bit only when
>> filename really contains the name of a file that should be deleted on
>> cleanup.
> 
> Since this flag is primarily for communication between the main code and a
> signal handler, the only safe way is to define the flag as volatile
> sig_atomic_t, not to make it a bit of a larger type!

Thanks for the feedback.  You are obviously right, and I will fix it.

But I have a feeling that this line of thought is going to lead to the
signal handler's not being able to do anything.  How far can we afford
to pursue strict correctness?  We have

struct lock_file {
struct lock_file *next;
int fd;
pid_t owner;
char on_list;
char filename[PATH_MAX];
};

static struct lock_file *lock_file_list;

The signal handler currently reads

lock_file_list
lock_file::next
lock_file::fd
lock_file::owner
lock_file::filename
*lock_file::filename

and writes lock_file_list.  Among other things it calls close(),
unlink(), vsnprintf(), and fprintf() (the last two via warning()).

But most of these actions are undefined under the C99 standard:

> If the signal occurs other than as the result of calling the abort
> or raise function, the behavior is undefined if the signal handler
> refers to any object with static storage duration other than by
> assigning a value to an object declared as volatile sig_atomic_t, or
> the signal handler calls any function in the standard library other
> than the abort function, the _Exit function, or the signal function
> with the first argument equal to the signal number corresponding to
> the signal that caused the invocation of the handler.

I don't have time to rewrite *all* of Git right now, so how can we get
reasonable safety and portability within a feasible amount of work?

Michael

-- 
Michael Haggerty
mhag...@alum.mit.edu
http://softwareswirl.blogspot.com/
--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


Re: [PATCH v9 11/11] Documentation: add documentation for 'git interpret-trailers'

2014-04-07 Thread Christian Couder
On Sat, Apr 5, 2014 at 12:42 AM, Junio C Hamano  wrote:
> Junio C Hamano  writes:
>
>> Christian Couder  writes:
>> "The following features are planned but not yet implemented:
>> - add more tests related to commands
>> - add examples in documentation
>> - integration with "git commit""
>
> I was planning to merge the series to 'next', but perhaps we should
> wait at least for the first two items (I do not think the third one
> is necessary to block the series).

I will send soon a new version of the series with more tests and fixes.
It will also contains a patch that adds an empty line before the
trailers in the output if there is not already one.
After that I plan to work on adding examples to the documentation.

>>> Why support both '=' and ':'?  Using just one would make it easier to
>>> grep through scripts to see who is adding signoffs.
>>
>> That was already discussed previously.
>
> I do recall it was discussed previously, but given that a new reader
> posed the same question, I am not sure if the end result in this
> patch under discussion sufficiently answers the question in a
> satisfactory way.
>
>> The reason is that people are used to "token=value" for command line
>> arguments, but trailers appears in the result as "token: value", so it
>> is better for the user if we support both.
>
> While I do understand the part before ", so" on the second line, I
> do not see why that leads to the conclusion at all.
>
> Yes, because it is a well-established convention to separate option
> name with its parameter with '=', accepting "--option=parameter"
> makes sense.  That may result in a string "Option: parameter" added
> to the output from the command.  I am not sure why that output has
> anything to do with how the command line should be specified.

First accepting both ':' and '=' means one can see the "git
interpret-trailers" as acting on trailers only. Not just on trailers
from the intput message and option parameters from the command line.
But from trailers both from the input message and being passed as
arguments.
In my opinion it is good if it can be seen this way, as it may
simplifies the user's mental model of how the command works.

And second there is also a practical advantage, as the user can
copy-paste trailers directly from other messages into the command line
to pass them as arguments to "git interpret-trailers" without the need
to replace the ':' with '='. Even if this command is not often used
directly by users, it might simplify scripts using it.

Third there is a technical advantage which is that the code that
parses arguments from the command line can be the same as the code
that parses trailers from the input message.

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


Re: [PATCH 07/22] lock_file(): always add lock_file object to lock_file_list

2014-04-07 Thread Jeff King
On Sun, Apr 06, 2014 at 11:54:59PM +0200, Michael Haggerty wrote:

> > I didn't reproduce it experimentally, though.  We should be able to just
> > 
> > lk->owner = 0;
> > 
> > before the initial strcpy to fix it, I would think.
> 
> I think that using the owner field to avoid this problem is a bit
> indirect, so I will soon submit a fix that involves adding a flag to
> lock_file objects indicating whether the filename field currently
> contains the name of a file that needs to be deleted.

Yeah, I agree that the current code is a bit subtle. I was planning to
address this during the tempfile cleanup project (either in GSoC, if it
gets a slot, or just doing it myself). But I don't mind if you want to
do something in the interim.

-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