Git development
 help / color / mirror / Atom feed
* [PATCH 1/7] perl/Git.pm: test portably if a path is absolute
From: Gustavo L. de M. Chaves @ 2013-01-30 17:22 UTC (permalink / raw)
  To: git; +Cc: Gustavo L. de M. Chaves
In-Reply-To: <1359566583-19654-1-git-send-email-gnustavo@cpan.org>

From: "Gustavo L. de M. Chaves" <gnustavo@cpan.org>

The code was testing if a path was absolute by checking if its first
character was a '/'. This does not work on Windows.

The portable way to do it is to use File::Spec::file_name_is_absolute.

Signed-off-by: Gustavo L. de M. Chaves <gnustavo@cpan.org>
---
 perl/Git.pm | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/perl/Git.pm b/perl/Git.pm
index 931047c..658b602 100644
--- a/perl/Git.pm
+++ b/perl/Git.pm
@@ -185,7 +185,7 @@ sub repository {
 		};
 
 		if ($dir) {
-			$dir =~ m#^/# or $dir = $opts{Directory} . '/' . $dir;
+			$dir = $opts{Directory} . '/' . $dir unless File::Spec->file_name_is_absolute($dir);
 			$opts{Repository} = abs_path($dir);
 
 			# If --git-dir went ok, this shouldn't die either.
-- 
1.7.12.464.g83379df.dirty

^ permalink raw reply related

* [PATCH 7/7] perl/Git.pm: rename 'ActiveState' to 'Windows'
From: Gustavo L. de M. Chaves @ 2013-01-30 17:23 UTC (permalink / raw)
  To: git; +Cc: Gustavo L. de M. Chaves
In-Reply-To: <1359566583-19654-1-git-send-email-gnustavo@cpan.org>

From: "Gustavo L. de M. Chaves" <gnustavo@cpan.org>

Windows specific code was mentioning ActiveState Perl specifically,
but that code works with Strawberry Perl too.

Hence, we rename every instance of 'ActivePerl' to 'Windows' to convey
the more general idea.

Signed-off-by: Gustavo L. de M. Chaves <gnustavo@cpan.org>
---
 perl/Git.pm | 17 ++++++++---------
 1 file changed, 8 insertions(+), 9 deletions(-)

diff --git a/perl/Git.pm b/perl/Git.pm
index fdef024..e03b82f 100644
--- a/perl/Git.pm
+++ b/perl/Git.pm
@@ -1297,11 +1297,10 @@ sub _command_common_pipe {
 
 	my $fh;
 	if ($^O eq 'MSWin32') {
-		# ActiveState Perl
 		#defined $opts{STDERR} and
-		#	warn 'ignoring STDERR option - running w/ ActiveState';
+		#	warn 'ignoring STDERR option - running on Windows;
 		$direction eq '-|' or
-			die 'input pipe for ActiveState not implemented';
+			die 'input pipe for Windows not implemented';
 
 		# Set up repo environment
 		local $ENV{GIT_DIR}       = $self->repo_path() if defined $self && $self->repo_path();
@@ -1315,13 +1314,13 @@ sub _command_common_pipe {
 			chdir $self->wc_subdir() if $self->wc_subdir();
 		}
 
-		# the strange construction with *ACPIPE is just to
+		# the strange construction with *WINPIPE is just to
 		# explain the tie below that we want to bind to
 		# a handle class, not scalar. It is not known if
-		# it is something specific to ActiveState Perl or
+		# it is something specific to Perl on Windows or
 		# just a Perl quirk.
-		tie (*ACPIPE, 'Git::activestate_pipe', $cmd, @args);
-		$fh = *ACPIPE;
+		tie (*WINPIPE, 'Git::windows_pipe', $cmd, @args);
+		$fh = *WINPIPE;
 
 		chdir $cwd;
 	} else {
@@ -1391,9 +1390,9 @@ sub DESTROY {
 }
 
 
-# Pipe implementation for ActiveState Perl.
+# Pipe implementation for Perl on Windows.
 
-package Git::activestate_pipe;
+package Git::windows_pipe;
 use strict;
 
 sub TIEHANDLE {
-- 
1.7.12.464.g83379df.dirty

^ permalink raw reply related

* Re: [PATCH v3 00/11] unify appending of sob
From: Junio C Hamano @ 2013-01-30 17:37 UTC (permalink / raw)
  To: Brandon Casey, Jonathan Nieder; +Cc: git, pclouds
In-Reply-To: <7v7gmxzwkj.fsf@alter.siamese.dyndns.org>

Junio C Hamano <gitster@pobox.com> writes:

> Jonathan Nieder <jrnieder@gmail.com> writes:
>
>> Brandon Casey wrote:
>>
>>> Round 3.
>>
>> Thanks for a pleasant read.  My only remaining observations are
>> cosmetic, except for a portability question in Duy's test script, a
>> small behavior change when the commit message ends with an
>> RFC2822-style header with no trailing newline and the possibility of
>> tightening the pattern in sequencer.c to match the strictness of
>> format-patch (which could easily wait for a later patch).
>
> Thanks for a quick review.  I agree that this series is getting very
> close with your help.

Unless Brandon and/or Jonathan wants to have another chance to
excise warts from the recorded history by rerolling the entire
series one more time, I think what we have queued is in a good
enough shape to merge to 'next' and any further improvement and fix
can be done incrementally.

OK?  Or "stop, I want to reroll"?

I'll wait for a day or two.

^ permalink raw reply

* Re: [feature request] git add completion should exclude staged content
From: Manlio Perillo @ 2013-01-30 18:24 UTC (permalink / raw)
  To: Marc Khouzam
  Cc: 'Junio C Hamano', 'Michael J Gruber',
	'wookietreiber', 'git@vger.kernel.org'
In-Reply-To: <E59706EF8DB1D147B15BECA3322E4BDC097A7E@eusaamb103.ericsson.se>

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Il 30/01/2013 15:06, Marc Khouzam ha scritto:
> [...]
>> I will try to update the patch, with your latest suggestions (avoid
>> tricky POSIX shell syntax, and CDPATH issue - if I remember 
>> correctly),
>> and with an update for the t/t9902-completion.sh test (that I 
>> completely
>> missed).
> 
> Hi Manlio,
> 

Hi.

> I'm trying to update git-completion.tcsh to work properly with
> your nice new completion feature.  But I'm having trouble with 
> the missing '/' at the end of directories.
> 
> The new logic in git-completion.bash tells bash that 'filenames'
> completion is ongoing so bash will add a '/' after directories.
> Sadly, tcsh won't do that, so it would be simpler if
> git-completion.bash added the '/' itself.  I looked at the 
> git-completion.bash script changes and I noticed that for 
> bash version < 4, you have to add the '/' yourself.

The compatible version is not only required for Bash; you can use it for
other shells.

Try to redefine the __git_index_file_list_filter function to use the
version that adds a slash to directory names.


> I also noticed the following comment:
> 
>  # XXX if we append a slash to directory names when using
>  # `compopt -o filenames`, Bash will append another slash.
>  # This is pretty stupid, and this the reason why we have to
>  # define a compatible version for this function.
> 
> So I gather you would rather add a '/' all the time to deal
> with older bash version transparently.  This would be great
> for tcsh also.  I'm trying to figure out
> when bash mis-behaves when you add the '/' all the time?
> When I try it (I have bash 4.1.5(1)-release) I didn't run
> into the double slash problem you mention in the comment.
> 

I'm using the same version: 4.1.5(1), on Debian stable.

> I'm hoping we can straighten this out and have
> git-completion.bash add the '/' all the time.
> 
> Could you explain when the problem happens?
> 

Bash 4.1.5(1) always adds an additional slash for directories.
I have tested it right now: change the filter function to use the
compatible version:

__git_index_file_list_filter ()
{
	# Default to Bash >= 4.x
	__git_index_file_list_filter_compat
}


Then running `git add <TAB>` inside the git repository, I get this file
completion list:

$ git add <TAB>
contrib//


> Thanks
> 


Thanks to you

Manlio
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.10 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iEYEARECAAYFAlEJZUMACgkQscQJ24LbaUQUGACgkMG/bZrJKBzlZ8toEQwmggQX
m9kAn2ATJbSp87kOkoCCc00eHmh71r3y
=D9iu
-----END PGP SIGNATURE-----

^ permalink raw reply

* What's cooking in git.git (Jan 2013, #11; Wed, 30)
From: Junio C Hamano @ 2013-01-30 18:33 UTC (permalink / raw)
  To: git

Here are the topics that have been cooking.  Commits prefixed with
'-' are only in 'pu' (proposed updates) while commits prefixed with
'+' are in 'next'.

As usual, this cycle is expected to last for 8 to 10 weeks, with a
preview -rc0 sometime in the middle of next month.

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]

* ab/gitweb-use-same-scheme (2013-01-28) 1 commit
 - gitweb: refer to picon/gravatar images over the same scheme

 Avoid mixed contents on a page coming via http and https when
 gitweb is hosted on a https server.

 Will merge to 'next'.


* jk/python-styles (2013-01-29) 1 commit
 - CodingGuidelines: add Python coding guidelines

 Expecting a reroll.
 $gmane/215007.


* mn/send-email-authinfo (2013-01-29) 1 commit
 - git-send-email: add ~/.authinfo parsing

 Expecting a reroll.
 $gmane/215004, $gmane/215024.


* nd/edit-branch-desc-while-detached (2013-01-30) 1 commit
  (merged to 'next' on 2013-01-30 at 69307d6)
 + branch: no detached HEAD check when editing another branch's description
 (this branch is used by nd/branch-error-cases.)

 Attempt to "branch --edit-description" an existing branch, while
 being on a detached HEAD, errored out.

 Will merge to 'master'.

--------------------------------------------------
[Graduated to "master"]

* bc/fix-array-syntax-for-3.0-in-completion-bash (2013-01-18) 1 commit
  (merged to 'next' on 2013-01-25 at d113c1a)
 + git-completion.bash: replace zsh notation that breaks bash 3.X

 Fix use of an array notation that older versions of bash do not
 understand.


* dl/am-hg-locale (2013-01-18) 1 commit
  (merged to 'next' on 2013-01-25 at 3419019)
 + am: invoke perl's strftime in C locale

 Datestamp recorded in "Hg" format patch was reformatted incorrectly
 to an e-mail looking date using locale dependant strftime, causing
 patch application to fail.


* jc/help (2013-01-18) 1 commit
  (merged to 'next' on 2013-01-25 at b2b087e)
 + help: include <common-cmds.h> only in one file

 A header file that has the definition of a static array was
 included in two places, wasting the space.


* nd/magic-pathspec-from-root (2013-01-21) 2 commits
  (merged to 'next' on 2013-01-25 at b056b57)
 + grep: avoid accepting ambiguous revision
 + Update :/abc ambiguity check

 When giving arguments without "--" disambiguation, object names
 that come  earlier on the command line must not be interpretable as
 pathspecs and pathspecs that come later on the command line must
 not be interpretable as object names.  Tweak the disambiguation
 rule so that ":/" (no other string before or after) is always
 interpreted as a pathspec, to avoid having to say "git cmd -- :/".


* rr/minimal-stat (2013-01-22) 1 commit
  (merged to 'next' on 2013-01-25 at 11c4453)
 + Enable minimal stat checking

 Some reimplementations of Git does not write all the stat info back
 to the index due to their implementation limitations (e.g. jgit
 running on Java).  A configuration option can tell Git to ignore
 changes to most of the stat fields and only pay attention to mtime
 and size, which these implementations can reliably update.  This
 avoids excessive revalidation of contents.


* tb/t0050-maint (2013-01-21) 3 commits
  (merged to 'next' on 2013-01-25 at 682b1e2)
 + t0050: Use TAB for indentation
 + t0050: honor CASE_INSENSITIVE_FS in add (with different case)
 + t0050: known breakage vanished in merge (case change)

 Update tests that were expecting to fail due to a bug that was
 fixed earlier.

--------------------------------------------------
[Stalled]

* dg/subtree-fixes (2013-01-08) 7 commits
 - contrib/subtree: mkdir the manual directory if needed
 - contrib/subtree: honor $(DESTDIR)
 - contrib/subtree: fix synopsis and command help
 - contrib/subtree: better error handling for "add"
 - contrib/subtree: add --unannotate option
 - contrib/subtree: use %B for split Subject/Body
 - t7900: remove test number comments

 contrib/subtree updates; there are a few more from T. Zheng that
 were posted separately, with an overlap.

 Expecting a reroll.


* mp/diff-algo-config (2013-01-16) 3 commits
 - diff: Introduce --diff-algorithm command line option
 - config: Introduce diff.algorithm variable
 - git-completion.bash: Autocomplete --minimal and --histogram for git-diff

 Add diff.algorithm configuration so that the user does not type
 "diff --histogram".

 Looking better; may want tests to protect it from future breakages,
 but otherwise it looks ready for 'next'.

 Expecting a follow-up to add tests.


* mb/gitweb-highlight-link-target (2012-12-20) 1 commit
 - Highlight the link target line in Gitweb using CSS

 Expecting a reroll.
 $gmane/211935


* jl/submodule-deinit (2012-12-04) 1 commit
 - submodule: add 'deinit' command

 There was no Porcelain way to say "I no longer am interested in
 this submodule", once you express your interest in a submodule with
 "submodule init".  "submodule deinit" is the way to do so.

 Expecting a reroll.
 $gmane/212884


* jk/lua-hackery (2012-10-07) 6 commits
 - pretty: fix up one-off format_commit_message calls
 - Minimum compilation fixup
 - Makefile: make "lua" a bit more configurable
 - add a "lua" pretty format
 - add basic lua infrastructure
 - pretty: make some commit-parsing helpers more public

 Interesting exercise. When we do this for real, we probably would want
 to wrap a commit to make it more like an "object" with methods like
 "parents", etc.


* rc/maint-complete-git-p4 (2012-09-24) 1 commit
 - Teach git-completion about git p4

 Comment from Pete will need to be addressed ($gmane/206172).


* jc/maint-name-rev (2012-09-17) 7 commits
 - describe --contains: use "name-rev --algorithm=weight"
 - name-rev --algorithm=weight: tests and documentation
 - name-rev --algorithm=weight: cache the computed weight in notes
 - name-rev --algorithm=weight: trivial optimization
 - name-rev: --algorithm option
 - name_rev: clarify the logic to assign a new tip-name to a commit
 - name-rev: lose unnecessary typedef

 "git name-rev" names the given revision based on a ref that can be
 reached in the smallest number of steps from the rev, but that is
 not useful when the caller wants to know which tag is the oldest one
 that contains the rev.  This teaches a new mode to the command that
 uses the oldest ref among those which contain the rev.

 I am not sure if this is worth it; for one thing, even with the help
 from notes-cache, it seems to make the "describe --contains" even
 slower. Also the command will be unusably slow for a user who does
 not have a write access (hence unable to create or update the
 notes-cache).

 Stalled mostly due to lack of responses.


* jc/xprm-generation (2012-09-14) 1 commit
 - test-generation: compute generation numbers and clock skews

 A toy to analyze how bad the clock skews are in histories of real
 world projects.

 Stalled mostly due to lack of responses.


* jc/add-delete-default (2012-08-13) 1 commit
 - git add: notice removal of tracked paths by default

 "git add dir/" updated modified files and added new files, but does
 not notice removed files, which may be "Huh?" to some users.  They
 can of course use "git add -A dir/", but why should they?

 Resurrected from graveyard, as I thought it was a worthwhile thing
 to do in the longer term.

 Stalled mostly due to lack of responses.


* mb/remote-default-nn-origin (2012-07-11) 6 commits
 - Teach get_default_remote to respect remote.default.
 - Test that plain "git fetch" uses remote.default when on a detached HEAD.
 - Teach clone to set remote.default.
 - Teach "git remote" about remote.default.
 - Teach remote.c about the remote.default configuration setting.
 - Rename remote.c's default_remote_name static variables.

 When the user does not specify what remote to interact with, we
 often attempt to use 'origin'.  This can now be customized via a
 configuration variable.

 Expecting a reroll.
 $gmane/210151

 "The first remote becomes the default" bit is better done as a
 separate step.


* nd/parse-pathspec (2013-01-11) 20 commits
 . Convert more init_pathspec() to parse_pathspec()
 . Convert add_files_to_cache to take struct pathspec
 . Convert {read,fill}_directory to take struct pathspec
 . Convert refresh_index to take struct pathspec
 . Convert report_path_error to take struct pathspec
 . checkout: convert read_tree_some to take struct pathspec
 . Convert unmerge_cache to take struct pathspec
 . Convert read_cache_preload() to take struct pathspec
 . add: convert to use parse_pathspec
 . archive: convert to use parse_pathspec
 . ls-files: convert to use parse_pathspec
 . rm: convert to use parse_pathspec
 . checkout: convert to use parse_pathspec
 . rerere: convert to use parse_pathspec
 . status: convert to use parse_pathspec
 . commit: convert to use parse_pathspec
 . clean: convert to use parse_pathspec
 . Export parse_pathspec() and convert some get_pathspec() calls
 . Add parse_pathspec() that converts cmdline args to struct pathspec
 . pathspec: save the non-wildcard length part

 Uses the parsed pathspec structure in more places where we used to
 use the raw "array of strings" pathspec.

 Ejected from 'pu' for now; will take a look at the rerolled one
 later ($gmane/213340).

--------------------------------------------------
[Cooking]

* mp/complete-paths (2013-01-11) 1 commit
  (merged to 'next' on 2013-01-30 at 70e4f1a)
 + git-completion.bash: add support for path completion

 The completion script used to let the default completer to suggest
 pathnames, which gave too many irrelevant choices (e.g. "git add"
 would not want to add an unmodified path).  Teach it to use a more
 git-aware logic to enumerate only relevant ones.

 This is logically the right thing to do, and we would really love
 to see people who have been involved in completion code to review
 and comment on the implementation.

 Will cook in 'next' to see if anybody screams.


* bc/git-p4-for-python-2.4 (2013-01-26) 2 commits
  (merged to 'next' on 2013-01-30 at 5d81ed2)
 + git-p4.py: support Python 2.4
 + git-p4.py: support Python 2.5

 With small updates to remove dependency on newer features of
 Python, keep git-p4 usable with older Python.

 Will merge to 'master'.


* jk/gc-auto-after-fetch (2013-01-26) 1 commit
  (merged to 'next' on 2013-01-30 at 472d07b)
 + Merge branch 'jk/maint-gc-auto-after-fetch' into jk/gc-auto-after-fetch
 (this branch uses jk/maint-gc-auto-after-fetch.)

 This is to resolve merge conflicts early for the same topic to
 recent codebase.

 Will merge to 'master'.


* jk/maint-gc-auto-after-fetch (2013-01-26) 2 commits
 + fetch-pack: avoid repeatedly re-scanning pack directory
 + fetch: run gc --auto after fetching
 (this branch is used by jk/gc-auto-after-fetch.)

 Help "fetch only" repositories that do not trigger "gc --auto"
 often enough.

 Will merge to 'master' via jk/gc-auto-after-fetch and later merge to 'maint'.


* jk/read-commit-buffer-data-after-free (2013-01-26) 3 commits
  (merged to 'next' on 2013-01-30 at c6d7e16)
 + logmsg_reencode: lazily load missing commit buffers
 + logmsg_reencode: never return NULL
 + commit: drop useless xstrdup of commit message

 Clarify the ownership rule for commit->buffer field, which some
 callers incorrectly accessed without making sure it is populated.

 Will merge to 'master'.


* pw/git-p4-on-cygwin (2013-01-26) 21 commits
  (merged to 'next' on 2013-01-30 at 958ae3a)
 + git p4: introduce gitConfigBool
 + git p4: avoid shell when calling git config
 + git p4: avoid shell when invoking git config --get-all
 + git p4: avoid shell when invoking git rev-list
 + git p4: avoid shell when mapping users
 + git p4: disable read-only attribute before deleting
 + git p4 test: use test_chmod for cygwin
 + git p4: cygwin p4 client does not mark read-only
 + git p4 test: avoid wildcard * in windows
 + git p4 test: use LineEnd unix in windows tests too
 + git p4 test: newline handling
 + git p4: scrub crlf for utf16 files on windows
 + git p4: remove unreachable windows \r\n conversion code
 + git p4 test: translate windows paths for cygwin
 + git p4 test: start p4d inside its db dir
 + git p4 test: use client_view in t9806
 + git p4 test: avoid loop in client_view
 + git p4 test: use client_view to build the initial client
 + git p4: generate better error message for bad depot path
 + git p4: remove unused imports
 + git p4: temp branch name should use / even on windows

 Improve "git p4" on Cygwin.

 Will merge to 'master'.


* ss/mergetools-tortoise (2013-01-26) 2 commits
 - mergetools: allow passing pathnames with SP in them to TortoiseGitMerge
 - mergetools: support TortoiseGitMerge

 Update mergetools to work better with newer merge helper tortoise ships.

 Will merge to 'next'.


* da/mergetool-docs (2013-01-30) 4 commits
 - doc: generate a list of valid merge tools
 - mergetool--lib: add functions for finding available tools
 - mergetool--lib: improve the help text in guess_merge_tool()
 - mergetool--lib: simplify command expressions
 (this branch uses jk/mergetool.)

 Build on top of the clean-up done by jk/mergetool and automatically
 generate the list of mergetool and difftool backends the build
 supports to be included in the documentation.

 This is looking ready for 'next'.


* nd/branch-error-cases (2013-01-30) 4 commits
 - branch: mark more strings for translation
 - Merge branch 'nd/edit-branch-desc-while-detached' into HEAD
 - branch: give a more helpful message on redundant arguments
 - branch: reject -D/-d without branch name
 (this branch uses nd/edit-branch-desc-while-detached.)

 Fix various error messages and conditions in "git branch", e.g. we
 advertised "branch -d/-D" to remove one or more branches but actually
 implemented removal of zero or more branches---request to remove no
 branches was not rejected.

 Will merge to 'next'.


* jc/push-reject-reasons (2013-01-24) 4 commits
  (merged to 'next' on 2013-01-28 at b60be93)
 + push: finishing touches to explain REJECT_ALREADY_EXISTS better
 + push: introduce REJECT_FETCH_FIRST and REJECT_NEEDS_FORCE
 + push: further simplify the logic to assign rejection reason
 + push: further clean up fields of "struct ref"

 Improve error and advice messages given locally when "git push"
 refuses when it cannot compute fast-forwardness by separating these
 cases from the normal "not a fast-forward; merge first and push
 again" case.

 Will merge to 'master'.


* as/test-cleanup (2013-01-24) 1 commit
  (merged to 'next' on 2013-01-28 at cc1147d)
 + t7102 (reset): don't hardcode SHA-1 in expected outputs

 Will merge to 'master'.


* jc/do-not-let-random-file-interfere-with-completion-tests (2013-01-24) 1 commit
  (merged to 'next' on 2013-01-28 at df27f53)
 + t9902: protect test from stray build artifacts

 Scripts to test bash completion was inherently flaky as it was
 affected by whatever random things the user may have on $PATH.

 Will merge to 'master'.


* jk/cvsimport-does-not-work-with-cvsps3 (2013-01-24) 1 commit
  (merged to 'next' on 2013-01-28 at fef4eb2)
 + git-cvsimport.txt: cvsps-2 is deprecated

 Warn people that other tools are more recommendable over
 cvsimport+cvsps2 combo when doing a one-shot import, and cvsimport
 will not work with cvsps3.

 Will merge to 'master'.


* jk/mergetool (2013-01-28) 8 commits
 - mergetools: simplify how we handle "vim" and "defaults"
 - mergetool--lib: don't call "exit" in setup_tool
 - mergetool--lib: improve show_tool_help() output
 - mergetools/vim: remove redundant diff command
 - git-difftool: use git-mergetool--lib for "--tool-help"
 - git-mergetool: don't hardcode 'mergetool' in show_tool_help
 - git-mergetool: remove redundant assignment
 - git-mergetool: move show_tool_help to mergetool--lib
 (this branch is used by da/mergetool-docs.)

 Cleans up mergetool/difftool combo.

 This is looking ready for 'next'.


* jn/do-not-drop-username-when-reading-from-etc-mailname (2013-01-25) 1 commit
  (merged to 'next' on 2013-01-28 at e0a8222)
 + ident: do not drop username when reading from /etc/mailname

 We used to stuff "user@" and then append what we read from
 /etc/mailname to come up with a default e-mail ident, but a bug
 lost the "user@" part.  This is to fix it.

 Will merge to 'master'.


* mm/add-u-A-sans-pathspec (2013-01-28) 1 commit
  (merged to 'next' on 2013-01-28 at fe762a6)
 + add: warn when -u or -A is used without pathspec

 Forbid "git add -u" and "git add -A" without pathspec run from a
 subdirectory, to train people to type "." (or ":/") to make the
 choice of default does not matter.

 Will merge to 'master'.


* jc/hidden-refs (2013-01-30) 8 commits
 - WIP: receive.allowupdatestohidden
 - fetch: fetch objects by their exact SHA-1 object names
 - upload-pack: optionally allow fetching from the tips of hidden refs
 - fetch: use struct ref to represent refs to be fetched
 - parse_fetch_refspec(): clarify the codeflow a bit
 - upload/receive-pack: allow hiding ref hierarchies
 - upload-pack: simplify request validation
 - upload-pack: share more code

 Allow the server side to unclutter the refs/ namespace it shows to
 the client.  Optionally allow requests for histories leading to the
 tips of hidden refs by updated clients.


* ta/doc-no-small-caps (2013-01-22) 10 commits
 - fixup! Change 'git' to 'Git' whenever the whole system is referred to #4
 - Change 'git' to 'Git' whenever the whole system is referred to #4
 - fixup! Change 'git' to 'Git' whenever the whole system is referred to #3
 - Change 'git' to 'Git' whenever the whole system is referred to #3
 - fixup! Change 'git' to 'Git' whenever the whole system is referred to #2
 - Change 'git' to 'Git' whenever the whole system is referred to #2
 - fixup! fixup! Change 'git' to 'Git' whenever the whole system is referred to #1
 - fixup! Change 'git' to 'Git' whenever the whole system is referred to #1
 - Change 'git' to 'Git' whenever the whole system is referred to #1
 - Documentation: avoid poor-man's small caps

 Update documentation to change "GIT" which was a poor-man's small
 caps to "Git" which was the intended spelling.  Also change "git"
 spelled in all-lowercase to "Git" when it refers to the system as
 the whole or the concept it embodies, as opposed to the command the
 end users would type.

 Will wait for a week or so (say, til end of January) for Thomas to
 collect fix-ups, squash the result into two patches and then merge
 to 'next'.


* jc/remove-treesame-parent-in-simplify-merges (2013-01-17) 1 commit
  (merged to 'next' on 2013-01-30 at b639b47)
 + simplify-merges: drop merge from irrelevant side branch

 The --simplify-merges logic did not cull irrelevant parents from a
 merge that is otherwise not interesting with respect to the paths
 we are following.

 This touches a fairly core part of the revision traversal
 infrastructure; even though I think this change is correct, please
 report immediately if you find any unintended side effect.

 Will merge to 'next'.


* jk/remote-helpers-in-python-3 (2013-01-28) 9 commits
  (merged to 'next' on 2013-01-28 at d898471)
 + git-remote-testpy: fix path hashing on Python 3
  (merged to 'next' on 2013-01-25 at acf9419)
 + git-remote-testpy: call print as a function
 + git-remote-testpy: don't do unbuffered text I/O
 + git-remote-testpy: hash bytes explicitly
 + svn-fe: allow svnrdump_sim.py to run with Python 3
 + git_remote_helpers: use 2to3 if building with Python 3
 + git_remote_helpers: force rebuild if python version changes
 + git_remote_helpers: fix input when running under Python 3
 + git_remote_helpers: allow building with Python 3

 Prepare remote-helper test written in Python to be run with Python3.

 Will merge to 'master'.


* jk/config-parsing-cleanup (2013-01-23) 8 commits
  (merged to 'next' on 2013-01-28 at 9bc9411)
 + reflog: use parse_config_key in config callback
 + help: use parse_config_key for man config
 + submodule: simplify memory handling in config parsing
 + submodule: use parse_config_key when parsing config
 + userdiff: drop parse_driver function
 + convert some config callbacks to parse_config_key
 + archive-tar: use parse_config_key when parsing config
 + config: add helper function for parsing key names

 Configuration parsing for tar.* configuration variables were
 broken. Introduce a new config-keyname parser API to make the
 callers much less error prone.

 Will merge to 'master'.


* jc/custom-comment-char (2013-01-16) 1 commit
  (merged to 'next' on 2013-01-25 at 91d8a5d)
 + Allow custom "comment char"

 An illustration to show codepaths that need to be touched to change
 the hint lines in the edited text to begin with something other
 than '#'.

 This is half my work and half by Ralf Thielow.  There may still be
 leftover '#' lurking around, though.  My "git grep" says C code
 should be already fine, but git-rebase--interactive.sh could be
 converted (it should not matter, as the file is not really a
 free-form text).

 Will merge to 'master'.


* nd/fetch-depth-is-broken (2013-01-11) 3 commits
  (merged to 'next' on 2013-01-15 at 70a5ca7)
 + fetch: elaborate --depth action
 + upload-pack: fix off-by-one depth calculation in shallow clone
 + fetch: add --unshallow for turning shallow repo into complete one

 "git fetch --depth" was broken in at least three ways.  The
 resulting history was deeper than specified by one commit, it was
 unclear how to wipe the shallowness of the repository with the
 command, and documentation was misleading.

 Will merge to 'master'.


* jc/no-git-config-in-clone (2013-01-11) 1 commit
  (merged to 'next' on 2013-01-15 at feeffe1)
 + clone: do not export and unexport GIT_CONFIG

 We stopped paying attention to $GIT_CONFIG environment that points
 at a single configuration file from any command other than "git config"
 quite a while ago, but "git clone" internally set, exported, and
 then unexported the variable during its operation unnecessarily.

 Will merge to 'master'.


* jc/push-2.0-default-to-simple (2013-01-16) 14 commits
  (merged to 'next' on 2013-01-16 at 23f5df2)
 + t5570: do not assume the "matching" push is the default
 + t5551: do not assume the "matching" push is the default
 + t5550: do not assume the "matching" push is the default
  (merged to 'next' on 2013-01-09 at 74c3498)
 + doc: push.default is no longer "matching"
 + push: switch default from "matching" to "simple"
 + t9401: do not assume the "matching" push is the default
 + t9400: do not assume the "matching" push is the default
 + t7406: do not assume the "matching" push is the default
 + t5531: do not assume the "matching" push is the default
 + t5519: do not assume the "matching" push is the default
 + t5517: do not assume the "matching" push is the default
 + t5516: do not assume the "matching" push is the default
 + t5505: do not assume the "matching" push is the default
 + t5404: do not assume the "matching" push is the default

 Will cook in 'next' until Git 2.0 ;-).


* bc/append-signed-off-by (2013-01-27) 11 commits
 - Unify appending signoff in format-patch, commit and sequencer
 - format-patch: update append_signoff prototype
 - t4014: more tests about appending s-o-b lines
 - sequencer.c: teach append_signoff to avoid adding a duplicate newline
 - sequencer.c: teach append_signoff how to detect duplicate s-o-b
 - sequencer.c: always separate "(cherry picked from" from commit body
 - sequencer.c: recognize "(cherry picked from ..." as part of s-o-b footer
 - t/t3511: add some tests of 'cherry-pick -s' functionality
 - t/test-lib-functions.sh: allow to specify the tag name to test_commit
 - commit, cherry-pick -s: remove broken support for multiline rfc2822 fields
 - sequencer.c: rework search for start of footer to improve clarity

 Rerolled.  With help from Jonathan, I think this is getting closer.

--------------------------------------------------
[Discarded]

* jk/update-install-for-p4 (2013-01-20) 1 commit
 . INSTALL: git-p4 doesn't support Python 3

 Made obsolete by bc/git-p4-for-python-2.4 topic.

^ permalink raw reply

* "sha1 information is lacking or useless" when rebasing with a submodule pointer conflict
From: Michael Sims @ 2013-01-30 18:43 UTC (permalink / raw)
  To: git

I'm seeing what might be a bug that was introduced in git 1.7.12 (also
observed in 1.8.1.2).  If not a bug, it's a changed behavior from
previous versions that I don't understand.

Here's the scenario:
* I have a remote repo containing a pointer to a submodule.
* Developer A and Developer B clone this repo, and both make a commit
to first the submodule, and then the parent repo, changing some files
and also the submodule pointer at the same time.
* Developer A pushes his changes to both the submodule and the parent
module to the shared remote
* Developer B either does a "git pull --rebase" or a "git fetch && git
rebase origin/master"

Results:
When applying Developer B's changes on top of origin/master, the
following messages are observed:
"fatal: sha1 information is lacking or useless (sub).
Repository lacks necessary blobs to fall back on 3-way merge.
Cannot fall back to three-way merge."

Furthermore, an immediate "git status" reports "all conflicts fixed",
does not report the submodule pointer as unmerged, and the changes to
the other files in the parent module made by Developer B are not
applied.

Expected Results:
Similar to how 1.7.12.1 behaves.  No mention of sha1 information or
blobs being lacking.  "git status" should report the submodule pointer
and any other changed files as being unmerged.  Conflicting changes
should not be lost.

I'm witnessing this behavior on OS X 10.8.2 with git versions 1.7.12,
1.7.12.1, and 1.8.1.2, installed via homebrew.  I do not see this
behavior in 1.7.11.5 or any of the 8 previous versions I've tried back
to 1.7.4.1.

Workaround:
Using an interactive rebase ("git fetch && git rebase -i
origin/master") with no changes made to the commit list seems to
sidestep this behavior.

Thanks in advance for any help with this.

Reproduce script:
Execute the following, then "cd local-b; git pull --rebase"

#!/bin/sh

set -e -v

BASEDIR=`pwd`

# Make bare remote repos
mkdir remotes
pushd remotes
git init --bare super.git
git init --bare sub.git
popd

# Initialize the submodule repo
git clone --no-hardlinks remotes/sub.git sub
pushd sub
echo subfile > subfile
git add subfile
git commit -m initial-submodule
git push origin master
popd
rm -Rf sub

# Clone into local-a and initialize supermodule repo
git clone --no-hardlinks remotes/super.git local-a
pushd local-a
git submodule add $BASEDIR/remotes/sub.git sub
echo file > file
git add sub file
git commit -m initial
git push origin master
popd

# Clone into local-b
git clone --no-hardlinks remotes/super.git local-b
pushd local-b
git submodule init && git submodule update
popd

# Make a change to supermodule file and submodule pointer from local-a
and push to remote
pushd local-a
cd sub
echo subfile changed from local-a > subfile
git add subfile
git commit -m subfile-changed-from-local-a
git push
cd ..
echo file changed from local-a > file
git add sub file
git commit -m change-from-local-a
git push
popd

# Make a conflicting change to both supermodule file and submodule
pointer from local-b
pushd local-b
cd sub
echo subfile changed from local-b > subfile
git add subfile
git commit -m subfile-changed-from-local-b
cd ..
echo file changed from local-b > file
git add sub file
git commit -m change-from-local-b
popd

^ permalink raw reply

* [PATCH v3 2/8] upload-pack: simplify request validation
From: Junio C Hamano @ 2013-01-30 18:45 UTC (permalink / raw)
  To: git; +Cc: Jeff King, Shawn Pearce
In-Reply-To: <1359571542-19852-1-git-send-email-gitster@pobox.com>

Long time ago, we used to punt on a large (read: asking for more
than 256 refs) fetch request and instead sent a full pack, because
we couldn't fit many refs on the command line of rev-list we run
internally to enumerate the objects to be sent.  To fix this,
565ebbf (upload-pack: tighten request validation., 2005-10-24),
added a check to count the number of refs in the request and matched
with the number of refs we advertised, and changed the invocation of
rev-list to pass "--all" to it, still keeping us under the command
line argument limit.

However, these days we feed the list of objects requested and the
list of objects the other end is known to have via standard input,
so there is no longer a valid reason to special case a full clone
request.  Remove the code associated with "create_full_pack" to
simplify the logic.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 upload-pack.c | 28 +++++++++++-----------------
 1 file changed, 11 insertions(+), 17 deletions(-)

diff --git a/upload-pack.c b/upload-pack.c
index 3dd220d..3a26a7b 100644
--- a/upload-pack.c
+++ b/upload-pack.c
@@ -28,7 +28,7 @@ static const char upload_pack_usage[] = "git upload-pack [--strict] [--timeout=<
 
 static unsigned long oldest_have;
 
-static int multi_ack, nr_our_refs;
+static int multi_ack;
 static int no_done;
 static int use_thin_pack, use_ofs_delta, use_include_tag;
 static int no_progress, daemon_mode;
@@ -139,7 +139,6 @@ static void create_pack_file(void)
 {
 	struct async rev_list;
 	struct child_process pack_objects;
-	int create_full_pack = (nr_our_refs == want_obj.nr && !have_obj.nr);
 	char data[8193], progress[128];
 	char abort_msg[] = "aborting due to possible repository "
 		"corruption on the remote side.";
@@ -151,9 +150,7 @@ static void create_pack_file(void)
 	argv[arg++] = "pack-objects";
 	if (!shallow_nr) {
 		argv[arg++] = "--revs";
-		if (create_full_pack)
-			argv[arg++] = "--all";
-		else if (use_thin_pack)
+		if (use_thin_pack)
 			argv[arg++] = "--thin";
 	}
 
@@ -185,15 +182,15 @@ static void create_pack_file(void)
 	}
 	else {
 		FILE *pipe_fd = xfdopen(pack_objects.in, "w");
-		if (!create_full_pack) {
-			int i;
-			for (i = 0; i < want_obj.nr; i++)
-				fprintf(pipe_fd, "%s\n", sha1_to_hex(want_obj.objects[i].item->sha1));
-			fprintf(pipe_fd, "--not\n");
-			for (i = 0; i < have_obj.nr; i++)
-				fprintf(pipe_fd, "%s\n", sha1_to_hex(have_obj.objects[i].item->sha1));
-		}
+		int i;
 
+		for (i = 0; i < want_obj.nr; i++)
+			fprintf(pipe_fd, "%s\n",
+				sha1_to_hex(want_obj.objects[i].item->sha1));
+		fprintf(pipe_fd, "--not\n");
+		for (i = 0; i < have_obj.nr; i++)
+			fprintf(pipe_fd, "%s\n",
+				sha1_to_hex(have_obj.objects[i].item->sha1));
 		fprintf(pipe_fd, "\n");
 		fflush(pipe_fd);
 		fclose(pipe_fd);
@@ -727,10 +724,7 @@ static int mark_our_ref(const char *refname, const unsigned char *sha1, int flag
 	struct object *o = lookup_unknown_object(sha1);
 	if (!o)
 		die("git upload-pack: cannot find object %s:", sha1_to_hex(sha1));
-	if (!(o->flags & OUR_REF)) {
-		o->flags |= OUR_REF;
-		nr_our_refs++;
-	}
+	o->flags |= OUR_REF;
 	return 0;
 }
 
-- 
1.8.1.2.589.ga9b91ac

^ permalink raw reply related

* [PATCH v3 0/8] Hiding refs
From: Junio C Hamano @ 2013-01-30 18:45 UTC (permalink / raw)
  To: git; +Cc: Jeff King, Shawn Pearce

The third round.

 - Multi-valued variable transfer.hiderefs lists prefixes of ref
   hierarchies to be hidden from the requests coming over the
   network.

 - A configuration optionally allows uploadpack to accept fetch
   requests for an object at the tip of a hidden ref.

Elsewhere, we discussed "delaying ref advertisement" (aka "expand
refs"), but it is an orthogonal feature and this "hiding refs
completely from advertisement" series does not attempt to address.

Patch #2 (simplify request validation), #4 (clarify the codeflow),
and #5 (use struct ref) are new.  The are all long overdue clean-ups
for these codepaths.

The last patch is an illustration why it wouldn't make sense to
optionally allow pushing into hidden refs, and not meant to be part
of the series proper.

For those who missed it, earlier rounds are at:

    http://thread.gmane.org/gmane.comp.version-control.git/213951
    http://thread.gmane.org/gmane.comp.version-control.git/214888

Junio C Hamano (8):
  upload-pack: share more code
  upload-pack: simplify request validation
  upload/receive-pack: allow hiding ref hierarchies
  parse_fetch_refspec(): clarify the codeflow a bit
  fetch: use struct ref to represent refs to be fetched
  upload-pack: optionally allow fetching from the tips of hidden refs
  fetch: fetch objects by their exact SHA-1 object names
  WIP: receive.allowupdatestohidden

 Documentation/config.txt |  23 +++++++++++
 builtin/fetch-pack.c     |  40 +++++++++++++++----
 builtin/receive-pack.c   |  31 +++++++++++++++
 cache.h                  |   3 +-
 fetch-pack.c             | 101 ++++++++++++++++++++++++++++++++---------------
 fetch-pack.h             |  11 +++---
 refs.c                   |  41 +++++++++++++++++++
 refs.h                   |   3 ++
 remote.c                 |  41 ++++++++++---------
 remote.h                 |   1 +
 t/t5512-ls-remote.sh     |   9 +++++
 t/t5516-fetch-push.sh    |  82 ++++++++++++++++++++++++++++++++++++++
 transport.c              |   9 +----
 upload-pack.c            |  86 ++++++++++++++++++++++++----------------
 14 files changed, 374 insertions(+), 107 deletions(-)

-- 
1.8.1.2.589.ga9b91ac

^ permalink raw reply

* [PATCH v3 1/8] upload-pack: share more code
From: Junio C Hamano @ 2013-01-30 18:45 UTC (permalink / raw)
  To: git; +Cc: Jeff King, Shawn Pearce
In-Reply-To: <1359571542-19852-1-git-send-email-gitster@pobox.com>

We mark the objects pointed at our refs with "OUR_REF" flag in two
functions (mark_our_ref() and send_ref()), but we can just use the
former as a helper for the latter.

Update the way mark_our_ref() prepares in-core object to use
lookup_unknown_object() to delay reading the actual object data,
just like we did in 435c833 (upload-pack: use peel_ref for ref
advertisements, 2012-10-04).

Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 upload-pack.c | 31 ++++++++++++++-----------------
 1 file changed, 14 insertions(+), 17 deletions(-)

diff --git a/upload-pack.c b/upload-pack.c
index 95d8313..3dd220d 100644
--- a/upload-pack.c
+++ b/upload-pack.c
@@ -722,15 +722,28 @@ static void receive_needs(void)
 	free(shallows.objects);
 }
 
+static int mark_our_ref(const char *refname, const unsigned char *sha1, int flag, void *cb_data)
+{
+	struct object *o = lookup_unknown_object(sha1);
+	if (!o)
+		die("git upload-pack: cannot find object %s:", sha1_to_hex(sha1));
+	if (!(o->flags & OUR_REF)) {
+		o->flags |= OUR_REF;
+		nr_our_refs++;
+	}
+	return 0;
+}
+
 static int send_ref(const char *refname, const unsigned char *sha1, int flag, void *cb_data)
 {
 	static const char *capabilities = "multi_ack thin-pack side-band"
 		" side-band-64k ofs-delta shallow no-progress"
 		" include-tag multi_ack_detailed";
-	struct object *o = lookup_unknown_object(sha1);
 	const char *refname_nons = strip_namespace(refname);
 	unsigned char peeled[20];
 
+	mark_our_ref(refname, sha1, flag, cb_data);
+
 	if (capabilities)
 		packet_write(1, "%s %s%c%s%s agent=%s\n",
 			     sha1_to_hex(sha1), refname_nons,
@@ -740,27 +753,11 @@ static int send_ref(const char *refname, const unsigned char *sha1, int flag, vo
 	else
 		packet_write(1, "%s %s\n", sha1_to_hex(sha1), refname_nons);
 	capabilities = NULL;
-	if (!(o->flags & OUR_REF)) {
-		o->flags |= OUR_REF;
-		nr_our_refs++;
-	}
 	if (!peel_ref(refname, peeled))
 		packet_write(1, "%s %s^{}\n", sha1_to_hex(peeled), refname_nons);
 	return 0;
 }
 
-static int mark_our_ref(const char *refname, const unsigned char *sha1, int flag, void *cb_data)
-{
-	struct object *o = parse_object(sha1);
-	if (!o)
-		die("git upload-pack: cannot find object %s:", sha1_to_hex(sha1));
-	if (!(o->flags & OUR_REF)) {
-		o->flags |= OUR_REF;
-		nr_our_refs++;
-	}
-	return 0;
-}
-
 static void upload_pack(void)
 {
 	if (advertise_refs || !stateless_rpc) {
-- 
1.8.1.2.589.ga9b91ac

^ permalink raw reply related

* [PATCH v3 3/8] upload/receive-pack: allow hiding ref hierarchies
From: Junio C Hamano @ 2013-01-30 18:45 UTC (permalink / raw)
  To: git; +Cc: Jeff King, Shawn Pearce
In-Reply-To: <1359571542-19852-1-git-send-email-gitster@pobox.com>

Teach upload-pack and receive-pack to omit some refs from their
initial advertisements by paying attention to the transfer.hiderefs
multi-valued configuration variable.  Any ref that is under the
hierarchies listed on the value of this variable is excluded from
responses to requests made by "ls-remote", "fetch", "clone", "push",
etc.

A typical use case may be

	[transfer]
		hiderefs = refs/pull

to hide the refs that are internally used by the hosting site and
should not be exposed over the network.

Because these hidden refs do not count as OUR_REF, an attempt to
fetch objects at the tip of them will be rejected, and because these
refs do not get advertised, "git push :" will not see local branches
that have the same name as them as "matching" ones to be sent.

An attempt to update/delete these hidden refs with an explicit
refspec, e.g. "git push origin :refs/pull/11/head", is rejected.

This is not a new restriction.  To the pusher, it would appear that
there is no such ref, so its push request will conclude with "Now
that I sent you all the data, it is time for you to update the refs.
I saw that the ref did not exist when I started pushing, and I want
the result to point at this commit".  The receiving end will apply
the compare-and-swap rule to this request and rejects the push with
"Well, your update request conflicts with somebody else; I see there
is such a ref.", which is the right thing to do. Otherwise a push to
a hidden ref will always be "the last one wins", which is not a good
default.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 Documentation/config.txt | 11 +++++++++++
 builtin/receive-pack.c   | 24 ++++++++++++++++++++++++
 refs.c                   | 41 +++++++++++++++++++++++++++++++++++++++++
 refs.h                   |  3 +++
 t/t5512-ls-remote.sh     |  9 +++++++++
 t/t5516-fetch-push.sh    | 24 ++++++++++++++++++++++++
 upload-pack.c            | 14 +++++++++++++-
 7 files changed, 125 insertions(+), 1 deletion(-)

diff --git a/Documentation/config.txt b/Documentation/config.txt
index ef45c99..f57c802 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -2057,6 +2057,17 @@ transfer.fsckObjects::
 	not set, the value of this variable is used instead.
 	Defaults to false.
 
+transfer.hiderefs::
+	String(s) `upload-pack` and `receive-pack` use to decide
+	which refs to omit from their initial advertisement.  Use
+	more than one transfer.hiderefs configuration variables to
+	specify multiple prefix strings. A ref that are under the
+	hierarchies listed on the value of this variable is excluded,
+	and is hidden from `git ls-remote`, `git fetch`, `git push :`,
+	etc.  An attempt to update or delete a hidden ref by `git push`
+	is rejected, and an attempt to fetch a hidden ref by `git fetch`
+	will fail.
+
 transfer.unpackLimit::
 	When `fetch.unpackLimit` or `receive.unpackLimit` are
 	not set, the value of this variable is used instead.
diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c
index ff781fe..a8248d9 100644
--- a/builtin/receive-pack.c
+++ b/builtin/receive-pack.c
@@ -59,6 +59,11 @@ static enum deny_action parse_deny_action(const char *var, const char *value)
 
 static int receive_pack_config(const char *var, const char *value, void *cb)
 {
+	int status = parse_hide_refs_config(var, value, cb);
+
+	if (status)
+		return status;
+
 	if (strcmp(var, "receive.denydeletes") == 0) {
 		deny_deletes = git_config_bool(var, value);
 		return 0;
@@ -119,6 +124,9 @@ static int receive_pack_config(const char *var, const char *value, void *cb)
 
 static void show_ref(const char *path, const unsigned char *sha1)
 {
+	if (ref_is_hidden(path))
+		return;
+
 	if (sent_capabilities)
 		packet_write(1, "%s %s\n", sha1_to_hex(sha1), path);
 	else
@@ -688,6 +696,20 @@ static int iterate_receive_command_list(void *cb_data, unsigned char sha1[20])
 	return -1; /* end of list */
 }
 
+static void reject_updates_to_hidden(struct command *commands)
+{
+	struct command *cmd;
+
+	for (cmd = commands; cmd; cmd = cmd->next) {
+		if (cmd->error_string || !ref_is_hidden(cmd->ref_name))
+			continue;
+		if (is_null_sha1(cmd->new_sha1))
+			cmd->error_string = "deny deleting a hidden ref";
+		else
+			cmd->error_string = "deny updating a hidden ref";
+	}
+}
+
 static void execute_commands(struct command *commands, const char *unpacker_error)
 {
 	struct command *cmd;
@@ -704,6 +726,8 @@ static void execute_commands(struct command *commands, const char *unpacker_erro
 				       0, &cmd))
 		set_connectivity_errors(commands);
 
+	reject_updates_to_hidden(commands);
+
 	if (run_receive_hook(commands, pre_receive_hook, 0)) {
 		for (cmd = commands; cmd; cmd = cmd->next) {
 			if (!cmd->error_string)
diff --git a/refs.c b/refs.c
index 541fec2..e3574ca 100644
--- a/refs.c
+++ b/refs.c
@@ -3,6 +3,7 @@
 #include "object.h"
 #include "tag.h"
 #include "dir.h"
+#include "string-list.h"
 
 /*
  * Make sure "ref" is something reasonable to have under ".git/refs/";
@@ -2556,3 +2557,43 @@ char *shorten_unambiguous_ref(const char *refname, int strict)
 	free(short_name);
 	return xstrdup(refname);
 }
+
+static struct string_list *hide_refs;
+
+int parse_hide_refs_config(const char *var, const char *value, void *unused)
+{
+	if (!strcmp("transfer.hiderefs", var)) {
+		char *ref;
+		int len;
+
+		if (!value)
+			return config_error_nonbool(var);
+		ref = xstrdup(value);
+		len = strlen(ref);
+		while (len && ref[len - 1] == '/')
+			ref[--len] = '\0';
+		if (!hide_refs) {
+			hide_refs = xcalloc(1, sizeof(*hide_refs));
+			hide_refs->strdup_strings = 1;
+		}
+		string_list_append(hide_refs, ref);
+	}
+	return 0;
+}
+
+int ref_is_hidden(const char *refname)
+{
+	struct string_list_item *item;
+
+	if (!hide_refs)
+		return 0;
+	for_each_string_list_item(item, hide_refs) {
+		int len;
+		if (prefixcmp(refname, item->string))
+			continue;
+		len = strlen(item->string);
+		if (!refname[len] || refname[len] == '/')
+			return 1;
+	}
+	return 0;
+}
diff --git a/refs.h b/refs.h
index d6c2fe2..50b233f 100644
--- a/refs.h
+++ b/refs.h
@@ -147,4 +147,7 @@ int update_ref(const char *action, const char *refname,
 		const unsigned char *sha1, const unsigned char *oldval,
 		int flags, enum action_on_err onerr);
 
+extern int parse_hide_refs_config(const char *var, const char *value, void *);
+extern int ref_is_hidden(const char *);
+
 #endif /* REFS_H */
diff --git a/t/t5512-ls-remote.sh b/t/t5512-ls-remote.sh
index d16e5d3..d0702ed 100755
--- a/t/t5512-ls-remote.sh
+++ b/t/t5512-ls-remote.sh
@@ -126,4 +126,13 @@ test_expect_success 'Report match with --exit-code' '
 	test_cmp expect actual
 '
 
+test_expect_success 'Hide some refs' '
+	test_config transfer.hiderefs refs/tags &&
+	git ls-remote . >actual &&
+	test_unconfig transfer.hiderefs &&
+	git ls-remote . |
+	sed -e "/	refs\/tags\//d" >expect &&
+	test_cmp expect actual
+'
+
 test_done
diff --git a/t/t5516-fetch-push.sh b/t/t5516-fetch-push.sh
index 6009372..852efb6 100755
--- a/t/t5516-fetch-push.sh
+++ b/t/t5516-fetch-push.sh
@@ -1037,4 +1037,28 @@ test_expect_success 'push --prune refspec' '
 	! check_push_result $the_first_commit tmp/foo tmp/bar
 '
 
+test_expect_success 'push to update a hidden ref' '
+	mk_test heads/master hidden/one hidden/two hidden/three &&
+	(
+		cd testrepo &&
+		git config transfer.hiderefs refs/hidden
+	) &&
+
+	# push to unhidden ref succeeds normally
+	git push testrepo master:refs/heads/master &&
+	check_push_result $the_commit heads/master &&
+
+	# push to update a hidden ref should fail
+	test_must_fail git push testrepo master:refs/hidden/one &&
+	check_push_result $the_first_commit hidden/one &&
+
+	# push to delete a hidden ref should fail
+	test_must_fail git push testrepo :refs/hidden/two &&
+	check_push_result $the_first_commit hidden/two &&
+
+	# idempotent push to update a hidden ref should fail
+	test_must_fail git push testrepo $the_first_commit:refs/hidden/three &&
+	check_push_result $the_first_commit hidden/three
+'
+
 test_done
diff --git a/upload-pack.c b/upload-pack.c
index 3a26a7b..6b10843 100644
--- a/upload-pack.c
+++ b/upload-pack.c
@@ -12,6 +12,7 @@
 #include "run-command.h"
 #include "sigchain.h"
 #include "version.h"
+#include "string-list.h"
 
 static const char upload_pack_usage[] = "git upload-pack [--strict] [--timeout=<n>] <dir>";
 
@@ -719,9 +720,13 @@ static void receive_needs(void)
 	free(shallows.objects);
 }
 
+/* return non-zero if the ref is hidden, otherwise 0 */
 static int mark_our_ref(const char *refname, const unsigned char *sha1, int flag, void *cb_data)
 {
 	struct object *o = lookup_unknown_object(sha1);
+
+	if (ref_is_hidden(refname))
+		return 1;
 	if (!o)
 		die("git upload-pack: cannot find object %s:", sha1_to_hex(sha1));
 	o->flags |= OUR_REF;
@@ -736,7 +741,8 @@ static int send_ref(const char *refname, const unsigned char *sha1, int flag, vo
 	const char *refname_nons = strip_namespace(refname);
 	unsigned char peeled[20];
 
-	mark_our_ref(refname, sha1, flag, cb_data);
+	if (mark_our_ref(refname, sha1, flag, cb_data))
+		return 0;
 
 	if (capabilities)
 		packet_write(1, "%s %s%c%s%s agent=%s\n",
@@ -773,6 +779,11 @@ static void upload_pack(void)
 	}
 }
 
+static int upload_pack_config(const char *var, const char *value, void *unused)
+{
+	return parse_hide_refs_config(var, value, unused);
+}
+
 int main(int argc, char **argv)
 {
 	char *dir;
@@ -824,6 +835,7 @@ int main(int argc, char **argv)
 		die("'%s' does not appear to be a git repository", dir);
 	if (is_repository_shallow())
 		die("attempt to fetch/clone from a shallow repository");
+	git_config(upload_pack_config, NULL);
 	if (getenv("GIT_DEBUG_SEND_PACK"))
 		debug_fd = atoi(getenv("GIT_DEBUG_SEND_PACK"));
 	upload_pack();
-- 
1.8.1.2.589.ga9b91ac

^ permalink raw reply related

* [PATCH v3 4/8] parse_fetch_refspec(): clarify the codeflow a bit
From: Junio C Hamano @ 2013-01-30 18:45 UTC (permalink / raw)
  To: git; +Cc: Jeff King, Shawn Pearce
In-Reply-To: <1359571542-19852-1-git-send-email-gitster@pobox.com>

Most parts of the cascaded if/else if/... checked an allowable
condition but some checked forbidden conditions.  This makes adding
new allowable conditions unnecessarily inconvenient.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 remote.c | 29 ++++++++++++-----------------
 1 file changed, 12 insertions(+), 17 deletions(-)

diff --git a/remote.c b/remote.c
index 4b1153f..1b7828d 100644
--- a/remote.c
+++ b/remote.c
@@ -538,7 +538,7 @@ static struct refspec *parse_refspec_internal(int nr_refspec, const char **refsp
 
 		/*
 		 * Before going on, special case ":" (or "+:") as a refspec
-		 * for matching refs.
+		 * for pushing matching refs.
 		 */
 		if (!fetch && rhs == lhs && rhs[1] == '\0') {
 			rs[i].matching = 1;
@@ -565,26 +565,21 @@ static struct refspec *parse_refspec_internal(int nr_refspec, const char **refsp
 		flags = REFNAME_ALLOW_ONELEVEL | (is_glob ? REFNAME_REFSPEC_PATTERN : 0);
 
 		if (fetch) {
-			/*
-			 * LHS
-			 * - empty is allowed; it means HEAD.
-			 * - otherwise it must be a valid looking ref.
-			 */
+			/* LHS */
 			if (!*rs[i].src)
-				; /* empty is ok */
-			else if (check_refname_format(rs[i].src, flags))
+				; /* empty is ok; it means "HEAD" */
+			else if (!check_refname_format(rs[i].src, flags))
+				; /* valid looking ref is ok */
+			else
 				goto invalid;
-			/*
-			 * RHS
-			 * - missing is ok, and is same as empty.
-			 * - empty is ok; it means not to store.
-			 * - otherwise it must be a valid looking ref.
-			 */
+			/* RHS */
 			if (!rs[i].dst)
-				; /* ok */
+				; /* missing is ok; it is the same as empty */
 			else if (!*rs[i].dst)
-				; /* ok */
-			else if (check_refname_format(rs[i].dst, flags))
+				; /* empty is ok; it means "do not store" */
+			else if (!check_refname_format(rs[i].dst, flags))
+				; /* valid looking ref is ok */
+			else
 				goto invalid;
 		} else {
 			/*
-- 
1.8.1.2.589.ga9b91ac

^ permalink raw reply related

* [PATCH v3 5/8] fetch: use struct ref to represent refs to be fetched
From: Junio C Hamano @ 2013-01-30 18:45 UTC (permalink / raw)
  To: git; +Cc: Jeff King, Shawn Pearce
In-Reply-To: <1359571542-19852-1-git-send-email-gitster@pobox.com>

Even though "git fetch" has full infrastructure to parse refspecs to
be fetched and match them against the list of refs to come up with
the final list of refs to be fetched, the list of refs that are
requested to be fetched were internally converted to a plain list of
strings at the transport layer and then passed to the underlying
fetch-pack driver.

Stop this conversion and instead pass around an array of refs.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 builtin/fetch-pack.c | 40 ++++++++++++++++++++------
 cache.h              |  3 +-
 fetch-pack.c         | 79 +++++++++++++++++++++++++++++++---------------------
 fetch-pack.h         | 11 ++++----
 transport.c          |  9 ++----
 5 files changed, 89 insertions(+), 53 deletions(-)

diff --git a/builtin/fetch-pack.c b/builtin/fetch-pack.c
index 940ae35..cc6bf8f 100644
--- a/builtin/fetch-pack.c
+++ b/builtin/fetch-pack.c
@@ -7,12 +7,31 @@ static const char fetch_pack_usage[] =
 "[--include-tag] [--upload-pack=<git-upload-pack>] [--depth=<n>] "
 "[--no-progress] [-v] [<host>:]<directory> [<refs>...]";
 
+static void add_sought_entry_mem(struct ref ***sought, int *nr, int *alloc,
+				 const char *name, int namelen)
+{
+	struct ref *ref = xcalloc(1, sizeof(*ref) + namelen + 1);
+
+	memcpy(ref->name, name, namelen);
+	ref->name[namelen] = '\0';
+	(*nr)++;
+	ALLOC_GROW(*sought, *nr, *alloc);
+	(*sought)[*nr - 1] = ref;
+}
+
+static void add_sought_entry(struct ref ***sought, int *nr, int *alloc,
+			     const char *string)
+{
+	add_sought_entry_mem(sought, nr, alloc, string, strlen(string));
+}
+
 int cmd_fetch_pack(int argc, const char **argv, const char *prefix)
 {
 	int i, ret;
 	struct ref *ref = NULL;
 	const char *dest = NULL;
-	struct string_list sought = STRING_LIST_INIT_DUP;
+	struct ref **sought;
+	int nr_sought = 0, alloc_sought = 0;
 	int fd[2];
 	char *pack_lockfile = NULL;
 	char **pack_lockfile_ptr = NULL;
@@ -94,7 +113,7 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix)
 	 * refs from the standard input:
 	 */
 	for (; i < argc; i++)
-		string_list_append(&sought, xstrdup(argv[i]));
+		add_sought_entry(&sought, &nr_sought, &alloc_sought, argv[i]);
 	if (args.stdin_refs) {
 		if (args.stateless_rpc) {
 			/* in stateless RPC mode we use pkt-line to read
@@ -107,14 +126,14 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix)
 					break;
 				if (line[n-1] == '\n')
 					n--;
-				string_list_append(&sought, xmemdupz(line, n));
+				add_sought_entry_mem(&sought, &nr_sought,  &alloc_sought, line, n);
 			}
 		}
 		else {
 			/* read from stdin one ref per line, until EOF */
 			struct strbuf line = STRBUF_INIT;
 			while (strbuf_getline(&line, stdin, '\n') != EOF)
-				string_list_append(&sought, strbuf_detach(&line, NULL));
+				add_sought_entry(&sought, &nr_sought, &alloc_sought, line.buf);
 			strbuf_release(&line);
 		}
 	}
@@ -131,7 +150,7 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix)
 	get_remote_heads(fd[0], &ref, 0, NULL);
 
 	ref = fetch_pack(&args, fd, conn, ref, dest,
-			 &sought, pack_lockfile_ptr);
+			 sought, nr_sought, pack_lockfile_ptr);
 	if (pack_lockfile) {
 		printf("lock %s\n", pack_lockfile);
 		fflush(stdout);
@@ -141,7 +160,7 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix)
 	if (finish_connect(conn))
 		return 1;
 
-	ret = !ref || sought.nr;
+	ret = !ref;
 
 	/*
 	 * If the heads to pull were given, we should have consumed
@@ -149,8 +168,13 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix)
 	 * remote no-such-ref' would silently succeed without issuing
 	 * an error.
 	 */
-	for (i = 0; i < sought.nr; i++)
-		error("no such remote ref %s", sought.items[i].string);
+	for (i = 0; i < nr_sought; i++) {
+		if (!sought[i] || sought[i]->matched)
+			continue;
+		error("no such remote ref %s", sought[i]->name);
+		ret = 1;
+	}
+
 	while (ref) {
 		printf("%s %s\n",
 		       sha1_to_hex(ref->old_sha1), ref->name);
diff --git a/cache.h b/cache.h
index c257953..03b3285 100644
--- a/cache.h
+++ b/cache.h
@@ -1013,7 +1013,8 @@ struct ref {
 		nonfastforward:1,
 		not_forwardable:1,
 		update:1,
-		deletion:1;
+		deletion:1,
+		matched:1;
 	enum {
 		REF_STATUS_NONE = 0,
 		REF_STATUS_OK,
diff --git a/fetch-pack.c b/fetch-pack.c
index f0acdf7..915c0b7 100644
--- a/fetch-pack.c
+++ b/fetch-pack.c
@@ -520,47 +520,37 @@ static void mark_recent_complete_commits(struct fetch_pack_args *args,
 	}
 }
 
-static int non_matching_ref(struct string_list_item *item, void *unused)
-{
-	if (item->util) {
-		item->util = NULL;
-		return 0;
-	}
-	else
-		return 1;
-}
-
 static void filter_refs(struct fetch_pack_args *args,
-			struct ref **refs, struct string_list *sought)
+			struct ref **refs,
+			struct ref **sought, int nr_sought)
 {
 	struct ref *newlist = NULL;
 	struct ref **newtail = &newlist;
 	struct ref *ref, *next;
-	int sought_pos;
+	int i;
 
-	sought_pos = 0;
+	i = 0;
 	for (ref = *refs; ref; ref = next) {
 		int keep = 0;
 		next = ref->next;
+
 		if (!memcmp(ref->name, "refs/", 5) &&
 		    check_refname_format(ref->name + 5, 0))
 			; /* trash */
 		else {
-			while (sought_pos < sought->nr) {
-				int cmp = strcmp(ref->name, sought->items[sought_pos].string);
+			while (i < nr_sought) {
+				int cmp = strcmp(ref->name, sought[i]->name);
 				if (cmp < 0)
 					break; /* definitely do not have it */
 				else if (cmp == 0) {
 					keep = 1; /* definitely have it */
-					sought->items[sought_pos++].util = "matched";
-					break;
+					sought[i]->matched = 1;
 				}
-				else
-					sought_pos++; /* might have it; keep looking */
+				i++;
 			}
 		}
 
-		if (! keep && args->fetch_all &&
+		if (!keep && args->fetch_all &&
 		    (!args->depth || prefixcmp(ref->name, "refs/tags/")))
 			keep = 1;
 
@@ -573,7 +563,6 @@ static void filter_refs(struct fetch_pack_args *args,
 		}
 	}
 
-	filter_string_list(sought, 0, non_matching_ref, NULL);
 	*refs = newlist;
 }
 
@@ -583,7 +572,8 @@ static void mark_alternate_complete(const struct ref *ref, void *unused)
 }
 
 static int everything_local(struct fetch_pack_args *args,
-			    struct ref **refs, struct string_list *sought)
+			    struct ref **refs,
+			    struct ref **sought, int nr_sought)
 {
 	struct ref *ref;
 	int retval;
@@ -634,7 +624,7 @@ static int everything_local(struct fetch_pack_args *args,
 		}
 	}
 
-	filter_refs(args, refs, sought);
+	filter_refs(args, refs, sought, nr_sought);
 
 	for (retval = 1, ref = *refs; ref ; ref = ref->next) {
 		const unsigned char *remote = ref->old_sha1;
@@ -764,10 +754,17 @@ static int get_pack(struct fetch_pack_args *args,
 	return 0;
 }
 
+static int cmp_ref_by_name(const void *a_, const void *b_)
+{
+	const struct ref *a = *((const struct ref **)a_);
+	const struct ref *b = *((const struct ref **)b_);
+	return strcmp(a->name, b->name);
+}
+
 static struct ref *do_fetch_pack(struct fetch_pack_args *args,
 				 int fd[2],
 				 const struct ref *orig_ref,
-				 struct string_list *sought,
+				 struct ref **sought, int nr_sought,
 				 char **pack_lockfile)
 {
 	struct ref *ref = copy_ref_list(orig_ref);
@@ -776,6 +773,7 @@ static struct ref *do_fetch_pack(struct fetch_pack_args *args,
 	int agent_len;
 
 	sort_ref_list(&ref, ref_compare_name);
+	qsort(sought, nr_sought, sizeof(*sought), cmp_ref_by_name);
 
 	if (is_repository_shallow() && !server_supports("shallow"))
 		die("Server does not support shallow clients");
@@ -824,7 +822,7 @@ static struct ref *do_fetch_pack(struct fetch_pack_args *args,
 				agent_len, agent_feature);
 	}
 
-	if (everything_local(args, &ref, sought)) {
+	if (everything_local(args, &ref, sought, nr_sought)) {
 		packet_flush(fd[1]);
 		goto all_done;
 	}
@@ -887,11 +885,32 @@ static void fetch_pack_setup(void)
 	did_setup = 1;
 }
 
+static int remove_duplicates_in_refs(struct ref **ref, int nr)
+{
+	struct string_list names = STRING_LIST_INIT_NODUP;
+	int src, dst;
+
+	for (src = dst = 0; src < nr; src++) {
+		struct string_list_item *item;
+		item = string_list_insert(&names, ref[src]->name);
+		if (item->util)
+			continue; /* already have it */
+		item->util = ref[src];
+		if (src != dst)
+			ref[dst] = ref[src];
+		dst++;
+	}
+	for (src = dst; src < nr; src++)
+		ref[src] = NULL;
+	string_list_clear(&names, 0);
+	return dst;
+}
+
 struct ref *fetch_pack(struct fetch_pack_args *args,
 		       int fd[], struct child_process *conn,
 		       const struct ref *ref,
 		       const char *dest,
-		       struct string_list *sought,
+		       struct ref **sought, int nr_sought,
 		       char **pack_lockfile)
 {
 	struct stat st;
@@ -903,16 +922,14 @@ struct ref *fetch_pack(struct fetch_pack_args *args,
 			st.st_mtime = 0;
 	}
 
-	if (sought->nr) {
-		sort_string_list(sought);
-		string_list_remove_duplicates(sought, 0);
-	}
+	if (nr_sought)
+		nr_sought = remove_duplicates_in_refs(sought, nr_sought);
 
 	if (!ref) {
 		packet_flush(fd[1]);
 		die("no matching remote head");
 	}
-	ref_cpy = do_fetch_pack(args, fd, ref, sought, pack_lockfile);
+	ref_cpy = do_fetch_pack(args, fd, ref, sought, nr_sought, pack_lockfile);
 
 	if (args->depth > 0) {
 		static struct lock_file lock;
diff --git a/fetch-pack.h b/fetch-pack.h
index cb14871..dc5266c 100644
--- a/fetch-pack.h
+++ b/fetch-pack.h
@@ -20,17 +20,16 @@ struct fetch_pack_args {
 };
 
 /*
- * sought contains the full names of remote references that should be
- * updated from.  On return, the names that were found on the remote
- * will have been removed from the list.  The util members of the
- * string_list_items are used internally; they must be NULL on entry
- * (and will be NULL on exit).
+ * sought represents remote references that should be updated from.
+ * On return, the names that were found on the remote will have been
+ * marked as such.
  */
 struct ref *fetch_pack(struct fetch_pack_args *args,
 		       int fd[], struct child_process *conn,
 		       const struct ref *ref,
 		       const char *dest,
-		       struct string_list *sought,
+		       struct ref **sought,
+		       int nr_sought,
 		       char **pack_lockfile);
 
 #endif
diff --git a/transport.c b/transport.c
index 2673d27..64ce651 100644
--- a/transport.c
+++ b/transport.c
@@ -518,11 +518,9 @@ static int fetch_refs_via_pack(struct transport *transport,
 			       int nr_heads, struct ref **to_fetch)
 {
 	struct git_transport_data *data = transport->data;
-	struct string_list sought = STRING_LIST_INIT_DUP;
 	const struct ref *refs;
 	char *dest = xstrdup(transport->url);
 	struct fetch_pack_args args;
-	int i;
 	struct ref *refs_tmp = NULL;
 
 	memset(&args, 0, sizeof(args));
@@ -536,9 +534,6 @@ static int fetch_refs_via_pack(struct transport *transport,
 	args.no_progress = !transport->progress;
 	args.depth = data->options.depth;
 
-	for (i = 0; i < nr_heads; i++)
-		string_list_append(&sought, to_fetch[i]->name);
-
 	if (!data->got_remote_heads) {
 		connect_setup(transport, 0, 0);
 		get_remote_heads(data->fd[0], &refs_tmp, 0, NULL);
@@ -547,7 +542,8 @@ static int fetch_refs_via_pack(struct transport *transport,
 
 	refs = fetch_pack(&args, data->fd, data->conn,
 			  refs_tmp ? refs_tmp : transport->remote_refs,
-			  dest, &sought, &transport->pack_lockfile);
+			  dest, to_fetch, nr_heads,
+			  &transport->pack_lockfile);
 	close(data->fd[0]);
 	close(data->fd[1]);
 	if (finish_connect(data->conn))
@@ -557,7 +553,6 @@ static int fetch_refs_via_pack(struct transport *transport,
 
 	free_refs(refs_tmp);
 
-	string_list_clear(&sought, 0);
 	free(dest);
 	return (refs ? 0 : -1);
 }
-- 
1.8.1.2.589.ga9b91ac

^ permalink raw reply related

* [PATCH v3 6/8] upload-pack: optionally allow fetching from the tips of hidden refs
From: Junio C Hamano @ 2013-01-30 18:45 UTC (permalink / raw)
  To: git; +Cc: Jeff King, Shawn Pearce
In-Reply-To: <1359571542-19852-1-git-send-email-gitster@pobox.com>

With uploadpack.allowtipsha1inwant configuration option set, future
versions of "git fetch" that allow an exact object name (likely to
have been obtained out of band) on the LHS of the fetch refspec can
make a request with a "want" line that names an object that may not
have been advertised due to transfer.hiderefs configuration.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 Documentation/config.txt |  8 +++++++-
 upload-pack.c            | 25 +++++++++++++++++++------
 2 files changed, 26 insertions(+), 7 deletions(-)

diff --git a/Documentation/config.txt b/Documentation/config.txt
index f57c802..2dce021 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -2066,13 +2066,19 @@ transfer.hiderefs::
 	and is hidden from `git ls-remote`, `git fetch`, `git push :`,
 	etc.  An attempt to update or delete a hidden ref by `git push`
 	is rejected, and an attempt to fetch a hidden ref by `git fetch`
-	will fail.
+	will fail.  See also `uploadpack.allowtipsha1inwant`.
 
 transfer.unpackLimit::
 	When `fetch.unpackLimit` or `receive.unpackLimit` are
 	not set, the value of this variable is used instead.
 	The default value is 100.
 
+uploadpack.allowtipsha1inwant::
+	When `transfer.hiderefs` is in effect, allow `upload-pack`
+	to accept a fetch request that asks for an object at the tip
+	of a hidden ref (by default, such a request is rejected).
+	see also `transfer.hiderefs`.
+
 url.<base>.insteadOf::
 	Any URL that starts with this value will be rewritten to
 	start, instead, with <base>. In cases where some site serves a
diff --git a/upload-pack.c b/upload-pack.c
index 6b10843..37977e2 100644
--- a/upload-pack.c
+++ b/upload-pack.c
@@ -26,6 +26,7 @@ static const char upload_pack_usage[] = "git upload-pack [--strict] [--timeout=<
 #define SHALLOW		(1u << 16)
 #define NOT_SHALLOW	(1u << 17)
 #define CLIENT_SHALLOW	(1u << 18)
+#define HIDDEN_REF	(1u << 19)
 
 static unsigned long oldest_have;
 
@@ -33,6 +34,7 @@ static int multi_ack;
 static int no_done;
 static int use_thin_pack, use_ofs_delta, use_include_tag;
 static int no_progress, daemon_mode;
+static int allow_tip_sha1_in_want;
 static int shallow_nr;
 static struct object_array have_obj;
 static struct object_array want_obj;
@@ -487,6 +489,12 @@ static int get_common_commits(void)
 	}
 }
 
+static int is_our_ref(struct object *o)
+{
+	return o->flags &
+		((allow_tip_sha1_in_want ? HIDDEN_REF : 0) | OUR_REF);
+}
+
 static void check_non_tip(void)
 {
 	static const char *argv[] = {
@@ -523,7 +531,7 @@ static void check_non_tip(void)
 		o = get_indexed_object(--i);
 		if (!o)
 			continue;
-		if (!(o->flags & OUR_REF))
+		if (!is_our_ref(o))
 			continue;
 		memcpy(namebuf + 1, sha1_to_hex(o->sha1), 40);
 		if (write_in_full(cmd.in, namebuf, 42) < 0)
@@ -532,7 +540,7 @@ static void check_non_tip(void)
 	namebuf[40] = '\n';
 	for (i = 0; i < want_obj.nr; i++) {
 		o = want_obj.objects[i].item;
-		if (o->flags & OUR_REF)
+		if (is_our_ref(o))
 			continue;
 		memcpy(namebuf, sha1_to_hex(o->sha1), 40);
 		if (write_in_full(cmd.in, namebuf, 41) < 0)
@@ -566,7 +574,7 @@ error:
 	/* Pick one of them (we know there at least is one) */
 	for (i = 0; i < want_obj.nr; i++) {
 		o = want_obj.objects[i].item;
-		if (!(o->flags & OUR_REF))
+		if (!is_our_ref(o))
 			die("git upload-pack: not our ref %s",
 			    sha1_to_hex(o->sha1));
 	}
@@ -646,7 +654,7 @@ static void receive_needs(void)
 			    sha1_to_hex(sha1_buf));
 		if (!(o->flags & WANTED)) {
 			o->flags |= WANTED;
-			if (!(o->flags & OUR_REF))
+			if (!is_our_ref(o))
 				has_non_tip = 1;
 			add_object_array(o, NULL, &want_obj);
 		}
@@ -725,8 +733,10 @@ static int mark_our_ref(const char *refname, const unsigned char *sha1, int flag
 {
 	struct object *o = lookup_unknown_object(sha1);
 
-	if (ref_is_hidden(refname))
+	if (ref_is_hidden(refname)) {
+		o->flags |= HIDDEN_REF;
 		return 1;
+	}
 	if (!o)
 		die("git upload-pack: cannot find object %s:", sha1_to_hex(sha1));
 	o->flags |= OUR_REF;
@@ -745,9 +755,10 @@ static int send_ref(const char *refname, const unsigned char *sha1, int flag, vo
 		return 0;
 
 	if (capabilities)
-		packet_write(1, "%s %s%c%s%s agent=%s\n",
+		packet_write(1, "%s %s%c%s%s%s agent=%s\n",
 			     sha1_to_hex(sha1), refname_nons,
 			     0, capabilities,
+			     allow_tip_sha1_in_want ? " allow-tip-sha1-in-want" : "",
 			     stateless_rpc ? " no-done" : "",
 			     git_user_agent_sanitized());
 	else
@@ -781,6 +792,8 @@ static void upload_pack(void)
 
 static int upload_pack_config(const char *var, const char *value, void *unused)
 {
+	if (!strcmp("uploadpack.allowtipsha1inwant", var))
+		allow_tip_sha1_in_want = git_config_bool(var, value);
 	return parse_hide_refs_config(var, value, unused);
 }
 
-- 
1.8.1.2.589.ga9b91ac

^ permalink raw reply related

* [PATCH v3 7/8] fetch: fetch objects by their exact SHA-1 object names
From: Junio C Hamano @ 2013-01-30 18:45 UTC (permalink / raw)
  To: git; +Cc: Jeff King, Shawn Pearce
In-Reply-To: <1359571542-19852-1-git-send-email-gitster@pobox.com>

Teach "git fetch" to accept an exact SHA-1 object name the user may
obtain out of band on the LHS of a pathspec, and send it on a "want"
message when the server side advertises the allow-tip-sha1-in-want
capability.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 fetch-pack.c          | 22 +++++++++++++++++++++-
 remote.c              | 12 +++++++++++-
 remote.h              |  1 +
 t/t5516-fetch-push.sh | 34 ++++++++++++++++++++++++++++++++++
 4 files changed, 67 insertions(+), 2 deletions(-)

diff --git a/fetch-pack.c b/fetch-pack.c
index 915c0b7..70db646 100644
--- a/fetch-pack.c
+++ b/fetch-pack.c
@@ -36,7 +36,7 @@ static int marked;
 #define MAX_IN_VAIN 256
 
 static struct commit_list *rev_list;
-static int non_common_revs, multi_ack, use_sideband;
+static int non_common_revs, multi_ack, use_sideband, allow_tip_sha1_in_want;
 
 static void rev_list_push(struct commit *commit, int mark)
 {
@@ -563,6 +563,21 @@ static void filter_refs(struct fetch_pack_args *args,
 		}
 	}
 
+	/* Append unmatched requests to the list */
+	if (allow_tip_sha1_in_want) {
+		for (i = 0; i < nr_sought; i++) {
+			ref = sought[i];
+			if (ref->matched)
+				continue;
+			if (get_sha1_hex(ref->name, ref->old_sha1))
+				continue;
+
+			ref->matched = 1;
+			*newtail = ref;
+			ref->next = NULL;
+			newtail = &ref->next;
+		}
+	}
 	*refs = newlist;
 }
 
@@ -803,6 +818,11 @@ static struct ref *do_fetch_pack(struct fetch_pack_args *args,
 			fprintf(stderr, "Server supports side-band\n");
 		use_sideband = 1;
 	}
+	if (server_supports("allow-tip-sha1-in-want")) {
+		if (args->verbose)
+			fprintf(stderr, "Server supports allow-tip-sha1-in-want\n");
+		allow_tip_sha1_in_want = 1;
+	}
 	if (!server_supports("thin-pack"))
 		args->use_thin_pack = 0;
 	if (!server_supports("no-progress"))
diff --git a/remote.c b/remote.c
index 1b7828d..1118d05 100644
--- a/remote.c
+++ b/remote.c
@@ -15,6 +15,7 @@ static struct refspec s_tag_refspec = {
 	0,
 	1,
 	0,
+	0,
 	"refs/tags/*",
 	"refs/tags/*"
 };
@@ -565,9 +566,13 @@ static struct refspec *parse_refspec_internal(int nr_refspec, const char **refsp
 		flags = REFNAME_ALLOW_ONELEVEL | (is_glob ? REFNAME_REFSPEC_PATTERN : 0);
 
 		if (fetch) {
+			unsigned char unused[40];
+
 			/* LHS */
 			if (!*rs[i].src)
 				; /* empty is ok; it means "HEAD" */
+			else if (llen == 40 && !get_sha1_hex(rs[i].src, unused))
+				rs[i].exact_sha1 = 1; /* ok */
 			else if (!check_refname_format(rs[i].src, flags))
 				; /* valid looking ref is ok */
 			else
@@ -1495,7 +1500,12 @@ int get_fetch_map(const struct ref *remote_refs,
 	} else {
 		const char *name = refspec->src[0] ? refspec->src : "HEAD";
 
-		ref_map = get_remote_ref(remote_refs, name);
+		if (refspec->exact_sha1) {
+			ref_map = alloc_ref(name);
+			get_sha1_hex(name, ref_map->old_sha1);
+		} else {
+			ref_map = get_remote_ref(remote_refs, name);
+		}
 		if (!missing_ok && !ref_map)
 			die("Couldn't find remote ref %s", name);
 		if (ref_map) {
diff --git a/remote.h b/remote.h
index 251d8fd..f7b08f1 100644
--- a/remote.h
+++ b/remote.h
@@ -62,6 +62,7 @@ struct refspec {
 	unsigned force : 1;
 	unsigned pattern : 1;
 	unsigned matching : 1;
+	unsigned exact_sha1 : 1;
 
 	char *src;
 	char *dst;
diff --git a/t/t5516-fetch-push.sh b/t/t5516-fetch-push.sh
index 852efb6..522056f 100755
--- a/t/t5516-fetch-push.sh
+++ b/t/t5516-fetch-push.sh
@@ -1037,6 +1037,40 @@ test_expect_success 'push --prune refspec' '
 	! check_push_result $the_first_commit tmp/foo tmp/bar
 '
 
+test_expect_success 'fetch exact SHA1' '
+	mk_test heads/master hidden/one &&
+	git push testrepo master:refs/hidden/one &&
+	(
+		cd testrepo &&
+		git config transfer.hiderefs refs/hidden
+	) &&
+	check_push_result $the_commit hidden/one &&
+
+	mk_child child &&
+	(
+		cd child &&
+
+		# make sure $the_commit does not exist here
+		git repack -a -d &&
+		git prune &&
+		test_must_fail git cat-file -t $the_commit &&
+
+		# fetching the hidden object should fail by default
+		test_must_fail git fetch -v ../testrepo $the_commit:refs/heads/copy &&
+		test_must_fail git rev-parse --verify refs/heads/copy &&
+
+		# the server side can allow it to succeed
+		(
+			cd ../testrepo &&
+			git config uploadpack.allowtipsha1inwant true
+		) &&
+
+		git fetch -v ../testrepo $the_commit:refs/heads/copy &&
+		result=$(git rev-parse --verify refs/heads/copy) &&
+		test "$the_commit" = "$result"
+	)
+'
+
 test_expect_success 'push to update a hidden ref' '
 	mk_test heads/master hidden/one hidden/two hidden/three &&
 	(
-- 
1.8.1.2.589.ga9b91ac

^ permalink raw reply related

* [PATCH v3 8/8] WIP: receive.allowupdatestohidden
From: Junio C Hamano @ 2013-01-30 18:45 UTC (permalink / raw)
  To: git; +Cc: Jeff King, Shawn Pearce
In-Reply-To: <1359571542-19852-1-git-send-email-gitster@pobox.com>

This does not work yet, and for a good reason.  As the side that
pushes to a hidden ref never sees that the ref already exists, a
request to update such a ref will come in the form of "please
_create_ this ref and point it at this object", which will not pass
the compare-and-swap based anti-race safety at the receiving end.

Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 Documentation/config.txt |  6 ++++++
 builtin/receive-pack.c   |  9 ++++++++-
 t/t5516-fetch-push.sh    | 24 ++++++++++++++++++++++++
 3 files changed, 38 insertions(+), 1 deletion(-)

diff --git a/Documentation/config.txt b/Documentation/config.txt
index 2dce021..8f13fc0 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -1849,6 +1849,12 @@ receive.updateserverinfo::
 	If set to true, git-receive-pack will run git-update-server-info
 	after receiving data from git-push and updating refs.
 
+receive.allowupdatestohidden::
+	When `transfer.hiderefs` is in effect, allow `receive-pack`
+	to accept a push request that asks to update or delete a
+	hidden ref (by default, such a request is rejected).
+	see also `transfer.hiderefs`.
+
 remote.<name>.url::
 	The URL of a remote repository.  See linkgit:git-fetch[1] or
 	linkgit:git-push[1].
diff --git a/builtin/receive-pack.c b/builtin/receive-pack.c
index a8248d9..88500e7 100644
--- a/builtin/receive-pack.c
+++ b/builtin/receive-pack.c
@@ -41,6 +41,7 @@ static int auto_gc = 1;
 static const char *head_name;
 static void *head_name_to_free;
 static int sent_capabilities;
+static int allow_updates_to_hidden;
 
 static enum deny_action parse_deny_action(const char *var, const char *value)
 {
@@ -119,6 +120,11 @@ static int receive_pack_config(const char *var, const char *value, void *cb)
 		return 0;
 	}
 
+	if (strcmp(var, "receive.allowupdatestohidden") == 0) {
+		allow_updates_to_hidden = git_config_bool(var, value);
+		return 0;
+	}
+
 	return git_default_config(var, value, cb);
 }
 
@@ -726,7 +732,8 @@ static void execute_commands(struct command *commands, const char *unpacker_erro
 				       0, &cmd))
 		set_connectivity_errors(commands);
 
-	reject_updates_to_hidden(commands);
+	if (!allow_updates_to_hidden)
+		reject_updates_to_hidden(commands);
 
 	if (run_receive_hook(commands, pre_receive_hook, 0)) {
 		for (cmd = commands; cmd; cmd = cmd->next) {
diff --git a/t/t5516-fetch-push.sh b/t/t5516-fetch-push.sh
index 522056f..4c8aef9 100755
--- a/t/t5516-fetch-push.sh
+++ b/t/t5516-fetch-push.sh
@@ -1095,4 +1095,28 @@ test_expect_success 'push to update a hidden ref' '
 	check_push_result $the_first_commit hidden/three
 '
 
+test_expect_failure 'allow push to update a hidden ref' '
+	mk_test heads/master hidden/one hidden/two hidden/three &&
+	(
+		cd testrepo &&
+		git config transfer.hiderefs refs/hidden &&
+		git config receive.allowupdatestohidden yes
+	) &&
+
+	# push to unhidden ref succeeds normally
+	git push testrepo master:refs/heads/master &&
+	check_push_result $the_commit heads/master &&
+
+	# push to update a hidden ref should succeed
+	git push testrepo master:refs/hidden/one &&
+	check_push_result $the_commit heads/master &&
+
+	# push to delete a hidden ref should succeed
+	git push testrepo :refs/hidden/two &&
+	(
+		cd testrepo &&
+		test_must_fail git show-ref -q refs/hidden/one
+	)
+'
+
 test_done
-- 
1.8.1.2.589.ga9b91ac

^ permalink raw reply related

* RE: [feature request] git add completion should exclude staged content
From: Marc Khouzam @ 2013-01-30 18:55 UTC (permalink / raw)
  To: 'Manlio Perillo'
  Cc: 'Junio C Hamano', 'Michael J Gruber',
	'wookietreiber', 'git@vger.kernel.org'
In-Reply-To: <51096543.9050100@gmail.com>


> -----Original Message-----
> From: git-owner@vger.kernel.org 
> [mailto:git-owner@vger.kernel.org] On Behalf Of Manlio Perillo
> Sent: Wednesday, January 30, 2013 1:24 PM
> To: Marc Khouzam
> Cc: 'Junio C Hamano'; 'Michael J Gruber'; 'wookietreiber'; 
> 'git@vger.kernel.org'
> Subject: Re: [feature request] git add completion should 
> exclude staged content
> 
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
> 
> Il 30/01/2013 15:06, Marc Khouzam ha scritto:
> > [...]
> >> I will try to update the patch, with your latest suggestions (avoid
> >> tricky POSIX shell syntax, and CDPATH issue - if I remember 
> >> correctly),
> >> and with an update for the t/t9902-completion.sh test (that I 
> >> completely
> >> missed).
> > 
> > Hi Manlio,
> > 
> 
> Hi.
> 
> > I'm trying to update git-completion.tcsh to work properly with
> > your nice new completion feature.  But I'm having trouble with 
> > the missing '/' at the end of directories.
> > 
> > The new logic in git-completion.bash tells bash that 'filenames'
> > completion is ongoing so bash will add a '/' after directories.
> > Sadly, tcsh won't do that, so it would be simpler if
> > git-completion.bash added the '/' itself.  I looked at the 
> > git-completion.bash script changes and I noticed that for 
> > bash version < 4, you have to add the '/' yourself.
> 
> The compatible version is not only required for Bash; you can 
> use it for
> other shells.
> 
> Try to redefine the __git_index_file_list_filter function to use the
> version that adds a slash to directory names.

I hadn't thought of that!
Although I would prefer not to have special cases like that,
it does work well.
Thanks!

> > I also noticed the following comment:
> > 
> >  # XXX if we append a slash to directory names when using
> >  # `compopt -o filenames`, Bash will append another slash.
> >  # This is pretty stupid, and this the reason why we have to
> >  # define a compatible version for this function.
> > 
> > So I gather you would rather add a '/' all the time to deal
> > with older bash version transparently.  This would be great
> > for tcsh also.  I'm trying to figure out
> > when bash mis-behaves when you add the '/' all the time?
> > When I try it (I have bash 4.1.5(1)-release) I didn't run
> > into the double slash problem you mention in the comment.
> > 
> 
> I'm using the same version: 4.1.5(1), on Debian stable.
> 
> > I'm hoping we can straighten this out and have
> > git-completion.bash add the '/' all the time.
> > 
> > Could you explain when the problem happens?
> > 
> 
> Bash 4.1.5(1) always adds an additional slash for directories.
> I have tested it right now: change the filter function to use the
> compatible version:
> 
> __git_index_file_list_filter ()
> {
> 	# Default to Bash >= 4.x
> 	__git_index_file_list_filter_compat
> }
> 
> 
> Then running `git add <TAB>` inside the git repository, I get 
> this file
> completion list:
> 
> $ git add <TAB>
> contrib//

Ok, I see.  The double-slash is visible in the completion list
but it does not appear on the command-line when bash automatically
adds it.  So if you typed 
  git add contri<tab>
you will properly get
  git add contrib/
That is the case I was looking at.
I understand why you cannot put that second slash in the code now.

Thanks

> 
> 
> > Thanks
> > 
> 
> 
> Thanks to you
> 
> Manlio
> -----BEGIN PGP SIGNATURE-----
> Version: GnuPG v1.4.10 (GNU/Linux)
> Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/
> 
> iEYEARECAAYFAlEJZUMACgkQscQJ24LbaUQUGACgkMG/bZrJKBzlZ8toEQwmggQX
> m9kAn2ATJbSp87kOkoCCc00eHmh71r3y
> =D9iu
> -----END PGP SIGNATURE-----
> --
> To unsubscribe from this list: send the line "unsubscribe git" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

^ permalink raw reply

* [BUG] `git branch --contains ID name` creates branch "name"
From: Peter Wu @ 2013-01-30 18:57 UTC (permalink / raw)
  To: git

Hi,

I was trying to check whether a certain branch contained a commit and ran:

     git branch --contains ddc150f7a33ae0c9cb16eaac3641abc00f56316f master

This resulted in:

    fatal: A branch named 'master' already exists.
When "name" does not exist, this command creates a branch. I expect this 
command to search the mentioned branch, not trying to create it. The manual 
page of git-branch(1) does not mention such special behavior either.

Git version 1.8.1.2

Regards,
Peter

^ permalink raw reply

* Re: What's cooking in git.git (Jan 2013, #11; Wed, 30)
From: John Keeping @ 2013-01-30 19:07 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git, Brandon Casey
In-Reply-To: <7vd2wmldw9.fsf@alter.siamese.dyndns.org>

On Wed, Jan 30, 2013 at 10:33:10AM -0800, Junio C Hamano wrote:
> [Discarded]
> 
> * jk/update-install-for-p4 (2013-01-20) 1 commit
>  . INSTALL: git-p4 doesn't support Python 3
> 
>  Made obsolete by bc/git-p4-for-python-2.4 topic.

I disagree with this - that branch doesn't change INSTALL to list "not
Python 3" in the supported versions.

Brandon, would you mind doing s/2.4 or later/2.4 - 2.7/ on your branch?


John

^ permalink raw reply

* Re: What's cooking in git.git (Jan 2013, #11; Wed, 30)
From: Junio C Hamano @ 2013-01-30 19:17 UTC (permalink / raw)
  To: John Keeping; +Cc: git, Brandon Casey
In-Reply-To: <20130130190759.GJ1342@serenity.lan>

John Keeping <john@keeping.me.uk> writes:

> On Wed, Jan 30, 2013 at 10:33:10AM -0800, Junio C Hamano wrote:
>> [Discarded]
>> 
>> * jk/update-install-for-p4 (2013-01-20) 1 commit
>>  . INSTALL: git-p4 doesn't support Python 3
>> 
>>  Made obsolete by bc/git-p4-for-python-2.4 topic.
>
> I disagree with this - that branch doesn't change INSTALL to list "not
> Python 3" in the supported versions.
>
> Brandon, would you mind doing s/2.4 or later/2.4 - 2.7/ on your branch?

Thanks for being a careful reader.

Let's do something like this on top of the topic.

 INSTALL | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/INSTALL b/INSTALL
index b96e16d..2dc3b61 100644
--- a/INSTALL
+++ b/INSTALL
@@ -131,8 +131,9 @@ Issues of note:
 	  use English. Under autoconf the configure script will do this
 	  automatically if it can't find libintl on the system.
 
-	- Python version 2.4 or later is needed to use the git-p4
-	  interface to Perforce.
+	- Python version 2.4 or later (but not 3.x, which is not
+	  supported by Perforce) is needed to use the git-p4 interface
+	  to Perforce.
 
  - Some platform specific issues are dealt with Makefile rules,
    but depending on your specific installation, you may not

^ permalink raw reply related

* Re: What's cooking in git.git (Jan 2013, #11; Wed, 30)
From: John Keeping @ 2013-01-30 19:19 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git, Brandon Casey
In-Reply-To: <7v4nhylbus.fsf@alter.siamese.dyndns.org>

On Wed, Jan 30, 2013 at 11:17:15AM -0800, Junio C Hamano wrote:
> Let's do something like this on top of the topic.

This looks good to me.

>  INSTALL | 5 +++--
>  1 file changed, 3 insertions(+), 2 deletions(-)
> 
> diff --git a/INSTALL b/INSTALL
> index b96e16d..2dc3b61 100644
> --- a/INSTALL
> +++ b/INSTALL
> @@ -131,8 +131,9 @@ Issues of note:
>  	  use English. Under autoconf the configure script will do this
>  	  automatically if it can't find libintl on the system.
>  
> -	- Python version 2.4 or later is needed to use the git-p4
> -	  interface to Perforce.
> +	- Python version 2.4 or later (but not 3.x, which is not
> +	  supported by Perforce) is needed to use the git-p4 interface
> +	  to Perforce.
>  
>   - Some platform specific issues are dealt with Makefile rules,
>     but depending on your specific installation, you may not
> --
> To unsubscribe from this list: send the line "unsubscribe git" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* [PATCH] git_remote_helpers: remove GIT-PYTHON-VERSION upon "clean"
From: Junio C Hamano @ 2013-01-30 19:30 UTC (permalink / raw)
  To: git; +Cc: John Keeping

fadf8c7 (git_remote_helpers: force rebuild if python version changes, 2013-01-20)
started using a marker file to keep track of the version of Python interpreter
used for the last build, but forgot to remove it when asked to "make clean".

Signed-off-by: Junio C Hamano <gitster@pobox.com>
---
 git_remote_helpers/Makefile | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/git_remote_helpers/Makefile b/git_remote_helpers/Makefile
index 0d2ae74..3d12232 100644
--- a/git_remote_helpers/Makefile
+++ b/git_remote_helpers/Makefile
@@ -42,4 +42,4 @@ instlibdir: $(pysetupfile)
 
 clean:
 	$(QUIET)$(PYTHON_PATH) $(pysetupfile) $(QUIETSETUP) clean -a
-	$(RM) *.pyo *.pyc
+	$(RM) *.pyo *.pyc GIT-PYTHON-VERSION

^ permalink raw reply related

* [PATCH 1/3] fixup! mergetool--lib: add functions for finding available tools
From: John Keeping @ 2013-01-30 19:55 UTC (permalink / raw)
  To: git; +Cc: David Aguilar, Junio C Hamano
In-Reply-To: <cover.1359575447.git.john@keeping.me.uk>

Signed-off-by: John Keeping <john@keeping.me.uk>
---
 git-mergetool--lib.sh | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/git-mergetool--lib.sh b/git-mergetool--lib.sh
index 25631cd..b6ed2fa 100644
--- a/git-mergetool--lib.sh
+++ b/git-mergetool--lib.sh
@@ -34,9 +34,9 @@ show_tool_names () {
 				then
 					echo "$preamble"
 					preamble=
-					shown_any=yes
 				fi
-				printf "%s%s\n" "$per_line_prefix" "$tool"
+				shown_any=yes
+				printf "%s%s\n" "$per_line_prefix" "$toolname"
 			fi
 		done
 		test -n "$shown_any"
@@ -244,6 +244,7 @@ show_tool_help () {
 
 	tab='	' av_shown= unav_shown=
 
+	cmd_name=${TOOL_MODE}tool
 	if show_tool_names 'mode_ok && is_available' "$tab$tab" \
 		"$tool_opt may be set to one of the following:"
 	then
-- 
1.8.1.1

^ permalink raw reply related

* [PATCH 3/3] mergetool--lib: list user configured tools in '--tool-help'
From: John Keeping @ 2013-01-30 19:55 UTC (permalink / raw)
  To: git; +Cc: David Aguilar, Junio C Hamano
In-Reply-To: <cover.1359575447.git.john@keeping.me.uk>

Signed-off-by: John Keeping <john@keeping.me.uk>
---
 git-mergetool--lib.sh | 41 ++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 40 insertions(+), 1 deletion(-)

diff --git a/git-mergetool--lib.sh b/git-mergetool--lib.sh
index b44a2c8..e338be5 100644
--- a/git-mergetool--lib.sh
+++ b/git-mergetool--lib.sh
@@ -20,9 +20,24 @@ is_available () {
 	type "$merge_tool_path" >/dev/null 2>&1
 }
 
+list_config_tools () {
+	section=$1
+	line_prefix=${2:-}
+
+	git config --get-regexp $section'\..*\.cmd' |
+	while read -r key value
+	do
+		toolname=${key#$section.}
+		toolname=${toolname%.cmd}
+
+		printf "%s%s\n" "$line_prefix" "$toolname"
+	done
+}
+
 show_tool_names () {
 	condition=${1:-true} per_line_prefix=${2:-} preamble=${3:-}
 	not_found_msg=${4:-}
+	extra_content=${5:-}
 
 	shown_any=
 	( cd "$MERGE_TOOLS_DIR" && ls ) | {
@@ -41,6 +56,19 @@ show_tool_names () {
 			fi
 		done
 
+		if test -n "$extra_content"
+		then
+			if test -n "$preamble"
+			then
+				# Note: no '\n' here since we don't want a
+				# blank line if there is no initial content.
+				printf "%s" "$preamble"
+				preamble=
+			fi
+			shown_any=yes
+			printf "\n%s\n" "$extra_content"
+		fi
+
 		if test -n "$preamble" && test -n "$not_found_msg"
 		then
 			printf "%s\n" "$not_found_msg"
@@ -255,9 +283,20 @@ show_tool_help () {
 	any_shown=no
 
 	cmd_name=${TOOL_MODE}tool
+	config_tools=$({
+		diff_mode && list_config_tools difftool "$tab$tab"
+		list_config_tools mergetool "$tab$tab"
+	} | sort)
+	extra_content=
+	if test -n "$config_tools"
+	then
+		extra_content="${tab}user-defined:${LF}$config_tools"
+	fi
+
 	show_tool_names 'mode_ok && is_available' "$tab$tab" \
 		"$tool_opt may be set to one of the following:" \
-		"No suitable tool for 'git $cmd_name --tool=<tool>' found." &&
+		"No suitable tool for 'git $cmd_name --tool=<tool>' found." \
+		"$extra_content" &&
 		any_shown=yes
 
 	show_tool_names 'mode_ok && ! is_available' "$tab$tab" \
-- 
1.8.1.1

^ permalink raw reply related

* Re: [BUG] incorrect search result returned when using git log with a future date parameter
From: Junio C Hamano @ 2013-01-30 19:57 UTC (permalink / raw)
  To: Caspar Zhang; +Cc: git, Gris Ge
In-Reply-To: <51090466.9070105@casparzhang.com>

Caspar Zhang <caspar@casparzhang.com> writes:

> .... A date parsing function should parse _all dates with
> correctly format_, despite if it's an old date, or the date in the
> future.

When it is fed 2013-02-12, it is ambiguous and "approxidate" can and
should use whatever heuristics (including rejection of future) to
guess what the user wanted, but 2013-02-13 cannot be interpreted in
any other way, so we should parse it as such.

Patches welcome, as long as the fix does not make things worse for
cases other than you observed.

Thanks.

^ permalink raw reply

* Re: [feature request] git add completion should exclude staged content
From: Manlio Perillo @ 2013-01-30 19:58 UTC (permalink / raw)
  To: Marc Khouzam
  Cc: 'Junio C Hamano', 'Michael J Gruber',
	'wookietreiber', 'git@vger.kernel.org'
In-Reply-To: <E59706EF8DB1D147B15BECA3322E4BDC097E39@eusaamb103.ericsson.se>

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Il 30/01/2013 19:55, Marc Khouzam ha scritto:
> [...]
>>>> The new logic in git-completion.bash tells bash that 'filenames'
>>>> completion is ongoing so bash will add a '/' after directories.
>>>> Sadly, tcsh won't do that, so it would be simpler if
>>>> git-completion.bash added the '/' itself.  I looked at the 
>>>> git-completion.bash script changes and I noticed that for 
>>>> bash version < 4, you have to add the '/' yourself.
> 
> The compatible version is not only required for Bash; you can 
> use it for
> other shells.
> 
> Try to redefine the __git_index_file_list_filter function to use the
> version that adds a slash to directory names.
> 
>> I hadn't thought of that!
>> Although I would prefer not to have special cases like that,
>> it does work well.

The zsh compatible code does something like this; this is the reason I
tried to do the same thing, in order to keep coding consistent.

> [...]
>
> Bash 4.1.5(1) always adds an additional slash for directories.
> I have tested it right now: change the filter function to use the
> compatible version:
> 
> __git_index_file_list_filter ()
> {
> 	# Default to Bash >= 4.x
> 	__git_index_file_list_filter_compat
> }
> 
> 
> Then running `git add <TAB>` inside the git repository, I get 
> this file
> completion list:
> 
> $ git add <TAB>
> contrib//
> 
>> Ok, I see.  The double-slash is visible in the completion list
>> but it does not appear on the command-line when bash automatically
>> adds it.

Right; that's why I wrote in the comment that Bash behaviour "seems" stupid.
But probably that comment should be remove or changed for the final
version of the patch; I'll leave that to a Bash expert.

> [...]


Regards  Manlio
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.10 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iEYEARECAAYFAlEJe0kACgkQscQJ24LbaUScGgCeMDDdprJMgnYtFzqnFQamhfvU
BikAniMkwbOEVkkomOd9G0m3KY44f/9O
=c8rC
-----END PGP SIGNATURE-----

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox