Git development
 help / color / mirror / Atom feed
* [PATCH v3 1/8] Introduce new static function real_path_internal()
From: Michael Haggerty @ 2012-10-21  5:57 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Jiang Xin, Lea Wiemann, David Reiss, Johannes Sixt, git,
	Michael Haggerty
In-Reply-To: <1350799057-13846-1-git-send-email-mhagger@alum.mit.edu>

It accepts a new parameter, die_on_error.  If die_on_error is false,
it simply cleans up after itself and returns NULL rather than dying.

Signed-off-by: Michael Haggerty <mhagger@alum.mit.edu>
---
 abspath.c | 93 ++++++++++++++++++++++++++++++++++++++++++++++++---------------
 1 file changed, 72 insertions(+), 21 deletions(-)

diff --git a/abspath.c b/abspath.c
index 05f2d79..a7ab8e9 100644
--- a/abspath.c
+++ b/abspath.c
@@ -15,15 +15,26 @@ int is_directory(const char *path)
 #define MAXDEPTH 5
 
 /*
- * Use this to get the real path, i.e. resolve links. If you want an
- * absolute path but don't mind links, use absolute_path.
+ * Return the real path (i.e., absolute path, with symlinks resolved
+ * and extra slashes removed) equivalent to the specified path.  (If
+ * you want an absolute path but don't mind links, use
+ * absolute_path().)  The return value is a pointer to a static
+ * buffer.
+ *
+ * The input and all intermediate paths must be shorter than MAX_PATH.
+ * The directory part of path (i.e., everything up to the last
+ * dir_sep) must denote a valid, existing directory, but the last
+ * component need not exist.  If die_on_error is set, then die with an
+ * informative error message if there is a problem.  Otherwise, return
+ * NULL on errors (without generating any output).
  *
  * If path is our buffer, then return path, as it's already what the
  * user wants.
  */
-const char *real_path(const char *path)
+static const char *real_path_internal(const char *path, int die_on_error)
 {
 	static char bufs[2][PATH_MAX + 1], *buf = bufs[0], *next_buf = bufs[1];
+	char *retval = NULL;
 	char cwd[1024] = "";
 	int buf_index = 1;
 
@@ -35,11 +46,19 @@ const char *real_path(const char *path)
 	if (path == buf || path == next_buf)
 		return path;
 
-	if (!*path)
-		die("The empty string is not a valid path");
+	if (!*path) {
+		if (die_on_error)
+			die("The empty string is not a valid path");
+		else
+			goto error_out;
+	}
 
-	if (strlcpy(buf, path, PATH_MAX) >= PATH_MAX)
-		die ("Too long path: %.*s", 60, path);
+	if (strlcpy(buf, path, PATH_MAX) >= PATH_MAX) {
+		if (die_on_error)
+			die("Too long path: %.*s", 60, path);
+		else
+			goto error_out;
+	}
 
 	while (depth--) {
 		if (!is_directory(buf)) {
@@ -54,20 +73,36 @@ const char *real_path(const char *path)
 		}
 
 		if (*buf) {
-			if (!*cwd && !getcwd(cwd, sizeof(cwd)))
-				die_errno ("Could not get current working directory");
+			if (!*cwd && !getcwd(cwd, sizeof(cwd))) {
+				if (die_on_error)
+					die_errno("Could not get current working directory");
+				else
+					goto error_out;
+			}
 
-			if (chdir(buf))
-				die_errno ("Could not switch to '%s'", buf);
+			if (chdir(buf)) {
+				if (die_on_error)
+					die_errno("Could not switch to '%s'", buf);
+				else
+					goto error_out;
+			}
+		}
+		if (!getcwd(buf, PATH_MAX)) {
+			if (die_on_error)
+				die_errno("Could not get current working directory");
+			else
+				goto error_out;
 		}
-		if (!getcwd(buf, PATH_MAX))
-			die_errno ("Could not get current working directory");
 
 		if (last_elem) {
 			size_t len = strlen(buf);
-			if (len + strlen(last_elem) + 2 > PATH_MAX)
-				die ("Too long path name: '%s/%s'",
-						buf, last_elem);
+			if (len + strlen(last_elem) + 2 > PATH_MAX) {
+				if (die_on_error)
+					die("Too long path name: '%s/%s'",
+					    buf, last_elem);
+				else
+					goto error_out;
+			}
 			if (len && !is_dir_sep(buf[len-1]))
 				buf[len++] = '/';
 			strcpy(buf + len, last_elem);
@@ -77,10 +112,18 @@ const char *real_path(const char *path)
 
 		if (!lstat(buf, &st) && S_ISLNK(st.st_mode)) {
 			ssize_t len = readlink(buf, next_buf, PATH_MAX);
-			if (len < 0)
-				die_errno ("Invalid symlink '%s'", buf);
-			if (PATH_MAX <= len)
-				die("symbolic link too long: %s", buf);
+			if (len < 0) {
+				if (die_on_error)
+					die_errno("Invalid symlink '%s'", buf);
+				else
+					goto error_out;
+			}
+			if (PATH_MAX <= len) {
+				if (die_on_error)
+					die("symbolic link too long: %s", buf);
+				else
+					goto error_out;
+			}
 			next_buf[len] = '\0';
 			buf = next_buf;
 			buf_index = 1 - buf_index;
@@ -89,10 +132,18 @@ const char *real_path(const char *path)
 			break;
 	}
 
+	retval = buf;
+error_out:
+	free(last_elem);
 	if (*cwd && chdir(cwd))
 		die_errno ("Could not change back to '%s'", cwd);
 
-	return buf;
+	return retval;
+}
+
+const char *real_path(const char *path)
+{
+	return real_path_internal(path, 1);
 }
 
 static const char *get_pwd_cwd(void)
-- 
1.7.11.3

^ permalink raw reply related

* [PATCH v3 0/8] Fix GIT_CEILING_DIRECTORIES that contain symlinks
From: Michael Haggerty @ 2012-10-21  5:57 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Jiang Xin, Lea Wiemann, David Reiss, Johannes Sixt, git,
	Michael Haggerty

v3 of the series, reworked WRT v2:

* Change longest_ancestor_length() to take a string_list for its
  prefixes argument (instead of a PATH_SEP-separated string).

* Move the responsibility for canonicalizing prefixes from
  longest_ancestor_length() to its caller in
  setup_git_directory_gently_1().  This keeps
  longest_ancestor_length() testable, though the test inputs now have
  to be canonicalized.

* Remove function string_list_longest_prefix(), which was mainly
  intended to be used in the implementation of
  longest_ancestor_length() but is now unneeded.

Thanks to Junio for his comments.

I would like to explicitly point out a possible objection to this
whole enterprise.  GIT_CEILING_DIRECTORIES is used to prevent git from
mucking around in certain directories, to avoid expensive accesses
(for example of remote directories).  The original motivation for the
feature was a user whose home directory /home/$USER was automounted.
When git was invoked outside of a git tree, it would crawl up the
filesystem tree, eventually reaching /home, and then try to access the
paths

    /home
    /home/.git
    /home/.git/objects
    /home/objects

The last three accesses would be very expensive because the system
would attempt to automount the entries listed.

This patch series has the side effect that all of the directories
listed in GIT_CEILING_DIRECTORIES are accessed *unconditionally* to
resolve any symlinks that are present in their paths.  It is
admittedly odd that a feature intended to avoid accessing expensive
directories would now *intentionally* access directories near the
expensive ones.  In the above scenario this shouldn't be a problem,
because /home would be the directory listed in
GIT_CEILING_DIRECTORIES, and accessing /home itself shouldn't be
expensive.  But there might be other scenarios for which this patch
series causes a performance regression.

Another point: After this change, it would be trivially possible to
support non-absolute paths in GIT_CEILING_DIRECTORIES; just remove the
call to is_absolute_path() from normalize_ceiling_entry().  This might
be convenient for the test suite.

Michael Haggerty (8):
  Introduce new static function real_path_internal()
  real_path_internal(): add comment explaining use of cwd
  Introduce new function real_path_if_valid()
  longest_ancestor_length(): use string_list_split()
  longest_ancestor_length(): take a string_list argument for prefixes
  longest_ancestor_length(): require prefix list entries to be
    normalized
  normalize_ceiling_entry(): resolve symlinks
  string_list_longest_prefix(): remove function

 Documentation/technical/api-string-list.txt |   8 ---
 abspath.c                                   | 105 ++++++++++++++++++++++------
 cache.h                                     |   3 +-
 path.c                                      |  46 ++++++------
 setup.c                                     |  32 ++++++++-
 string-list.c                               |  20 ------
 string-list.h                               |   8 ---
 t/t0060-path-utils.sh                       |  41 ++++-------
 t/t0063-string-list.sh                      |  30 --------
 test-path-utils.c                           |   8 ++-
 test-string-list.c                          |  20 ------
 11 files changed, 157 insertions(+), 164 deletions(-)

-- 
1.7.11.3

^ permalink raw reply

* Re: What's cooking in git.git (Oct 2012, #06; Fri, 19)
From: Junio C Hamano @ 2012-10-21  5:57 UTC (permalink / raw)
  To: Nguyen Thai Ngoc Duy; +Cc: git
In-Reply-To: <CACsJy8A2PdG69hB1=YgHMAdibO=7_Uu5qvmyAqcrhdBVWy761g@mail.gmail.com>

Nguyen Thai Ngoc Duy <pclouds@gmail.com> writes:

>>  I suspect that this needs to be plugged to pathspec matching code;
>>  otherwise "git log -- 'Docum*/**/*.txt'" would not show the log for
>>  commits that touch Documentation/git.txt, which would be confusing
>>  to the users.
>
> I do want non-recursive "*" in pathspec and "**" can help retain the
> recursive "*" semantics. But can we just flip the coin at some point
> and change "*" semantics in pathspec from recursive to non-recursive?

Fair enough; that indeed is a valid concern.  Something like
":(glob)" magic may be necessary as an early step.  Longer term
(like Git 3.0 where we might say "screw the existing users" and
redesign "if we were doing Git from scratch"), it would be nice to
have excludes, attributes and pathspecs all share the same syntax,
though.

^ permalink raw reply

* Re: What's cooking in git.git (Oct 2012, #06; Fri, 19)
From: Nguyen Thai Ngoc Duy @ 2012-10-21  4:24 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <7vmwzii37w.fsf@alter.siamese.dyndns.org>

On Sat, Oct 20, 2012 at 4:03 AM, Junio C Hamano <gitster@pobox.com> wrote:
> * nd/wildmatch (2012-10-15) 13 commits
>
>  Allows pathname patterns in .gitignore and .gitattributes files
>  with double-asterisks "foo/**/bar" to match any number of directory
>  hierarchies.
>
>  I suspect that this needs to be plugged to pathspec matching code;
>  otherwise "git log -- 'Docum*/**/*.txt'" would not show the log for
>  commits that touch Documentation/git.txt, which would be confusing
>  to the users.

I do want non-recursive "*" in pathspec and "**" can help retain the
recursive "*" semantics. But can we just flip the coin at some point
and change "*" semantics in pathspec from recursive to non-recursive?

I have no problem with that but then we might want to change other
places that use fnmatch without FNM_PATHNAME too, e.g. apply, branch,
for-each-ref... Or we could go with new syntax
":(glob)Docu*/**/*.txt". A bit ugly.
-- 
Duy

^ permalink raw reply

* Re: Report a bug, about track remote repository.
From: Cheeray Huang @ 2012-10-21  2:44 UTC (permalink / raw)
  To: Philip Oakley; +Cc: git
In-Reply-To: <F15116C3B49A439AB06C8068F79E4C0F@PhilipOakley>

On 2012年10月21日 07:46, Philip Oakley wrote:
>
> At this point you have created the 'conflict' - You can't have two 
> different branches that both track the same identical remote branch 
> and expect that they can be both different and identical at the same 
> time.

> Only one push (from two branches trying) can suceed. You either force 
> the remote to match the current branch, and loose any information that 
> it had about the other branch, or the remote stays with one branch. 
> Simply don't do it [that way]. If the local branches are different, 
> then you need distinct remote branches.

Yes, if it will lead a conflict, I think git should give a warning for 
it and prevent these operations rather than give a comment to inform you 
to push something.



-- 
Best Regards!

Qiyu Huang( Cheeray )

^ permalink raw reply

* Re: looking for suggestions for managing a tree of server configs
From: david @ 2012-10-21  2:34 UTC (permalink / raw)
  To: Drew Northup; +Cc: Junio C Hamano, git
In-Reply-To: <CAM9Z-nmHxyqnyq1fChhv7hP_awgsaO2FT1t29PAwrvZkaA-hgg@mail.gmail.com>

On Sat, 20 Oct 2012, Drew Northup wrote:

> On Sun, Oct 14, 2012 at 12:57 AM,  <david@lang.hm> wrote:
>> On Sat, 13 Oct 2012, Junio C Hamano wrote:
>>> david@lang.hm writes:
>>>> I've got a directory tree that holds config data for all my
>>>> servers. This consists of one directory per server (which is updated
>>>> periodically from what is currently configured on that server), plus
>>>> higher level summary reports and similar information.
>>>>
>>>> today I have just a single git tree covering everything, and I make a
>>>> commit each time one of the per-server directories is updated, and
>>>> again when the top-level stuff is created.
>>>
>>> It is quite clear to me what you are keeping at the top-level files,
>>> but if a large portion of the configuration for these servers are
>>> shared, it might not be a bad idea to have a canonical "gold-master"
>>> configuration branch, to which the shared updates are applied, with
>>> a branch per server that forks from that canonical branch to keep
>>> the machine specific tweaks as differences from the canonical stuff,
>>> instead of having N subdirectories (one per machine).
>>
>> In an ideal world yes, but right now these machines are updated by many
>> different tools (unforuntantly including 'vi'), so these directories aren't
>> the config to be pushed out to the boxes (i.e. what they should be), it's
>> instead an archived 'what is', the result of changes from all the tools.
>>
>> The systems are all built with a standard image, but the automation tools I
>> do have tend to push identical files out to many of the systems (or files
>> identical except for a couple of lines)
>
> David,
> Is there any particular reason you aren't using etckeeper?

not really, I've thought of that as a tool for managing a single system. 
Some of the data in configs is sensitive (and much of it is not in /etc), 
but I guess I should be able to work around those issues.

I can e-mail 'patches' to the central server, but I'm then back to the 
same question that I started out with.

How can I sanely organize all these different, but similar sets of files 
on the central server?

David Lang

^ permalink raw reply

* [PATCH] Fix git p4 sync errors
From: Matt Arsenault @ 2012-10-21  1:59 UTC (permalink / raw)
  To: git

>From 425e4dc6992d07aa00039c5bb8e8c76def591fd3 Mon Sep 17 00:00:00 2001
From: Matt Arsenault <arsenm2@gmail.com>
Date: Sat, 20 Oct 2012 18:48:45 -0700
Subject: [PATCH] git-p4: Fix not using -s option to describe

This solves errors in some cases when syncing renamed files.
Other places where describe is used use the -s, except this one.

Signed-off-by: Matt Arsenault <arsenm2@gmail.com>
---
 git-p4.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/git-p4.py b/git-p4.py
index 882b1bb..e203508 100755
--- a/git-p4.py
+++ b/git-p4.py
@@ -2543,7 +2543,7 @@ class P4Sync(Command, P4UserMap):
     def importChanges(self, changes):
         cnt = 1
         for change in changes:
-            description = p4Cmd(["describe", str(change)])
+            description = p4Cmd(["describe", "-s", str(change)])
             self.updateOptionDict(description)
 
             if not self.silent:
-- 
1.7.12.2

^ permalink raw reply related

* Re: looking for suggestions for managing a tree of server configs
From: Drew Northup @ 2012-10-21  1:50 UTC (permalink / raw)
  To: david; +Cc: Junio C Hamano, git
In-Reply-To: <alpine.DEB.2.02.1210132153040.6253@asgard.lang.hm>

On Sun, Oct 14, 2012 at 12:57 AM,  <david@lang.hm> wrote:
> On Sat, 13 Oct 2012, Junio C Hamano wrote:
>> david@lang.hm writes:
>>> I've got a directory tree that holds config data for all my
>>> servers. This consists of one directory per server (which is updated
>>> periodically from what is currently configured on that server), plus
>>> higher level summary reports and similar information.
>>>
>>> today I have just a single git tree covering everything, and I make a
>>> commit each time one of the per-server directories is updated, and
>>> again when the top-level stuff is created.
>>
>> It is quite clear to me what you are keeping at the top-level files,
>> but if a large portion of the configuration for these servers are
>> shared, it might not be a bad idea to have a canonical "gold-master"
>> configuration branch, to which the shared updates are applied, with
>> a branch per server that forks from that canonical branch to keep
>> the machine specific tweaks as differences from the canonical stuff,
>> instead of having N subdirectories (one per machine).
>
> In an ideal world yes, but right now these machines are updated by many
> different tools (unforuntantly including 'vi'), so these directories aren't
> the config to be pushed out to the boxes (i.e. what they should be), it's
> instead an archived 'what is', the result of changes from all the tools.
>
> The systems are all built with a standard image, but the automation tools I
> do have tend to push identical files out to many of the systems (or files
> identical except for a couple of lines)

David,
Is there any particular reason you aren't using etckeeper?

-- 
-Drew Northup
--------------------------------------------------------------
"As opposed to vegetable or mineral error?"
-John Pescatore, SANS NewsBites Vol. 12 Num. 59

^ permalink raw reply

* Re: Report a bug, about track remote repository.
From: Philip Oakley @ 2012-10-20 23:46 UTC (permalink / raw)
  To: Cheeray Huang, git
In-Reply-To: <5082F255.9060600@gmail.com>

From: "Cheeray Huang" <cheeray.huang@gmail.com>
> Hi,
>
> I think I found a bug, when I used local branches to track remote 
> branch. But I'm not very sure, can anyone double check this?  I'd like 
> to finger this out. I think you can reproduce this bug as below steps:
>
> precondition:
>
> Suppose that you have a remote branch in repository, named 
> origin/work. And then you want to track it with a local branch.
>
> Steps:
>
> 1. So you can do this:
>
> git checkout -t origin/work
>
> now, you have a local branch also named "work" to track "origin/work".
> It works nicely, you can use "push/pull" command without any detail 
> parameters to sync anything with the remote branch.
>
> 2. Create another branch, ex. named "work2", to track "origin/work" 
> again, though maybe there are not so many people that will do like 
> this.

At this point you have created the 'conflict' - You can't have two 
different branches that both track the same identical remote branch and 
expect that they can be both different and identical at the same time.

>
> You will find that local branch "work2" can't "push" to "origin/work".
> ex. After you committed something in work2, you typed "git status", 
> git would tell you:
>
> Your branch is ahead of 'origin/work' by x commit.
>
> And then you used "git push", git can't display the information about 
> changing hash value in remote branch, just printed "everything is up 
> to date".

Only one push (from two branches trying) can suceed. You either force 
the remote to match the current branch, and loose any information that 
it had about the other branch, or the remote stays with one branch. 
Simply don't do it [that way]. If the local branches are different, then 
you need distinct remote branches.

>
> Actually, you can use some exact parameters to solve this,  such as:
>
> git push origin work2:work
>
> But, I still think it is a bug.
>
> BTW, I found this bug when I used github. I don't know whether it is 
> related to github.
>
>
> -- 
> B&R,
> Cheeray

^ permalink raw reply

* Re: Subtree in Git
From: Herman van Rink @ 2012-10-20 20:03 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: dag, greened, Hilco Wijbenga, Git Users
In-Reply-To: <nng4npe6zsj.fsf@transit.us.cray.com>

On 07/11/2012 06:14 PM, dag@cray.com wrote:
> Herman van Rink <rink@initfour.nl> writes:
>
>>> It's hard to tell what's what with one big diff.  Each command should
>>> get its own commit plus more if infrastructure work has to be done.  I
>>> realize it's a bit of a pain to reformulate this but git rebase -i makes
>>> it easy and the history will be much better long-term.
>>>
>>> Each command should be described briefly in the commit log.
>> That would indeed be nice, but as some parts interdependent it would be
>> rather complicated.
> Do the interdependent parts first, then.  These should be pure
> infrastructure.
>
>> And what is the use if their not fully independently testable.
> The command should be testable as soon as they are fully implemented,
> no?
>
> I'm thinking about a sequence like this:
>
> - Infrastructure for command A (and possibly B, C, etc. if they are
>   interdependent).
> - Command A + tests
> - Infrastructure for command B
> - Command B + tests
> - etc.
>
>> If you want to fake a nice history tree then go ahead, I just don't have
>> the energy to go through these commits again just for that.
> Well, I can't do this either, both because it would take time to get up
> to speed on the patches and because I have a million other things going
> on at the moment.  So unfortunately, this is going to sit until someone
> can take it up.
>
> Unless Junio accepts your patches, of course.  :)

Junio, Could you please consider merging the single commit from my
subtree-updates branch? https://github.com/helmo/git/tree/subtree-updates

I've seen a few reactions on the git userlist refer to issues which have
long been solved in these collected updates.


>
>>> Some questions/comments:
>>>
>>> - Is .gittrees the right solution?  I like the feature it provides but
>>>   an external file feels a bit hacky.  I wonder if there is a better way
>>>   to track this metadata.  Notes maybe?  Other git experts will have to
>>>   chime in with suggestions.
>> It's similar to what git submodule does. And when you add this file to
>> the index you can use it on other checkouts as well.
> Well, I guess I'm not strongly opposed, I was just asking the question.
>
>>> - This code seems to be repeated a lot.  Maybe it should be a utility
>>>   function.
>> Yes that's there three times...
> So you agree it should be factored?
>
>>> - I removed all this stuff in favor of the test library.  Please don't
>>>   reintroduce it.  These new tests will have to be rewritten in terms of
>>>   the existing test infrastructure.  It's not too hard.
>> I've left it in to be able to verify your new tests. Once all the new
>> tests are passing we can get rid of the old one, not before.
>> And as all the old tests are contained in test.sh it should not interfere...
> No, I'm very strongly against putting this back in.  The new tests will
> have to be updated to the upstream test infrastructure.
>
>                                       -Dave
> --
> 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
>


-- 

Met vriendelijke groet / Regards,

Herman van Rink
Initfour websolutions

^ permalink raw reply

* Re: [PATCH] Add --unannotate option to git-subtree
From: Herman van Rink @ 2012-10-20 19:33 UTC (permalink / raw)
  To: James Nylen; +Cc: git
In-Reply-To: <CABVa4NgdaiwfTvFe1CU+24QF-BA45tM2e3+9e2PJ_4ecuD0Cyg@mail.gmail.com>

On 10/16/2012 02:47 PM, James Nylen wrote:
> On Tue, Oct 9, 2012 at 4:26 PM, James Nylen <jnylen@gmail.com> wrote:
>> This new option does the reverse of --annotate, which is more useful
>> when contributing back to a library which is also included in the
>> repository for a larger project, and perhaps in other situations as
>> well.
>>
>> Rather than adding a marker to each commit when splitting out the
>> commits back to the subproject, --unannotate removes the specified
>> string (or bash glob pattern) from the beginning of the first line of
>> the commit message.  This enables the following workflow:
>>
>>  - Commit to a library included in a large project, with message:
>>      Library: Make some amazing change
>>
>>  - Use `git-subtree split` to send this change to the library maintainer
>>
>>  - Pass ` --unannotate='Library: ' ` or ` --unannotate='*: ' `
>>
>>  - This will turn the commit message for the library project into:
>>      Make some amazing change
>>
>> This helps to keep the commit messages meaningful in both the large
>> project and the library project.
>>
>> Signed-off-by: James Nylen <jnylen@gmail.com>
>> ---
> Has anybody looked at this?
>
> It has been very useful for me.


The version of subtree in contrib is rather out-dated unfortunately.
Your patch looks interesting though. I can see how this could be useful.

I've collected a bunch of patches in
https://github.com/helmo/git/tree/subtree-updates

Apart from a line in git-subtree.txt ending in whitespace I think I can
merge it in there.

>
>> Let me know if gmail has munged this patch.  You can also get at it
>> like this:
>>
>> $ git remote add nylen git://github.com/nylen/git.git
>> $ git fetch nylen
>> $ git show nylen/subtree-unannotate
>> ---
>>  contrib/subtree/git-subtree.sh  | 11 +++++++++--
>>  contrib/subtree/git-subtree.txt | 15 +++++++++++++++
>>  2 files changed, 24 insertions(+), 2 deletions(-)
>>
>> diff --git a/contrib/subtree/git-subtree.sh b/contrib/subtree/git-subtree.sh
>> index 920c664..8d1ed05 100755
>> --- a/contrib/subtree/git-subtree.sh
>> +++ b/contrib/subtree/git-subtree.sh
>> @@ -21,6 +21,7 @@ P,prefix=     the name of the subdir to split out
>>  m,message=    use the given message as the commit message for the merge commit
>>   options for 'split'
>>  annotate=     add a prefix to commit message of new commits
>> +unannotate=   remove a prefix from new commit messages (supports bash globbing)
>>  b,branch=     create a new branch from the split subtree
>>  ignore-joins  ignore prior --rejoin commits
>>  onto=         try connecting new tree to an existing one
>> @@ -43,6 +44,7 @@ onto=
>>  rejoin=
>>  ignore_joins=
>>  annotate=
>> +unannotate=
>>  squash=
>>  message=
>>
>> @@ -80,6 +82,8 @@ while [ $# -gt 0 ]; do
>>                 -d) debug=1 ;;
>>                 --annotate) annotate="$1"; shift ;;
>>                 --no-annotate) annotate= ;;
>> +               --unannotate) unannotate="$1"; shift ;;
>> +               --no-unannotate) unannotate= ;;
>>                 -b) branch="$1"; shift ;;
>>                 -P) prefix="$1"; shift ;;
>>                 -m) message="$1"; shift ;;
>> @@ -310,8 +314,11 @@ copy_commit()
>>                         GIT_COMMITTER_NAME \
>>                         GIT_COMMITTER_EMAIL \
>>                         GIT_COMMITTER_DATE
>> -               (echo -n "$annotate"; cat ) |
>> -               git commit-tree "$2" $3  # reads the rest of stdin
>> +               (
>> +                       read FIRST_LINE
>> +                       echo "$annotate${FIRST_LINE#$unannotate}"
>> +                       cat  # reads the rest of stdin
>> +               ) | git commit-tree "$2" $3
>>         ) || die "Can't copy commit $1"
>>  }
>>
>> diff --git a/contrib/subtree/git-subtree.txt b/contrib/subtree/git-subtree.txt
>> index 0c44fda..ae420aa 100644
>> --- a/contrib/subtree/git-subtree.txt
>> +++ b/contrib/subtree/git-subtree.txt
>> @@ -198,6 +198,21 @@ OPTIONS FOR split
>>         git subtree tries to make it work anyway, particularly
>>         if you use --rejoin, but it may not always be effective.
>>
>> +--unannotate=<annotation>::
>> +       This option is only valid for the split command.
>> +
>> +       When generating synthetic history, try to remove the prefix
>> +       <annotation> from each commit message (using bash's "strip
>> +       shortest match from beginning" command, which supports
>> +       globbing).  This makes sense if you format library commits
>> +       like "library: Change something or other" when you're working
>> +       in your project's repository, but you want to remove this
>> +       prefix when pushing back to the library's upstream repository.
>> +       (In this case --unannotate='*: ' would work well.)
>> +
>> +       Like --annotate,  you need to use the same <annotation>
>> +       whenever you split, or you may run into problems.
>> +
>>  -b <branch>::
>>  --branch=<branch>::
>>         This option is only valid for the split command.
>> --
>> 1.7.11.3
> --
> 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
>


-- 

Met vriendelijke groet / Regards,

Herman van Rink
Initfour websolutions

^ permalink raw reply

* Re: [DOCBUG] git subtree synopsis needs updating
From: Herman van Rink @ 2012-10-20 19:40 UTC (permalink / raw)
  To: Yann Dirson; +Cc: git list
In-Reply-To: <20121019152158.4297707b@chalon.bertin.fr>

On 10/19/2012 03:21 PM, Yann Dirson wrote:
> As the examples in git-subtree.txt show, the synopsis in the same file should
> surely get a patch along the lines of:
>
> -'git subtree' add   -P <prefix> <commit>
> +'git subtree' add   -P <prefix> <repository> <commit>
>
> Failure to specify the repository (by just specifying a local commit) fails with
> the cryptic:
>
>  warning: read-tree: emptying the index with no arguments is deprecated; use --empty
>  fatal: just how do you expect me to merge 0 trees?
>
>
> Furthermore, the doc paragraph for add, aside from mentionning <repository>, also
> mentions a <refspec> which the synopsis does not show either.
>
>
> As a sidenote it someone wants to do some maintainance, using "." as repository when
> the branch to subtree-add is already locally available does not work well either
> (fails with "could not find ref myremote/myhead").
>

The version of subtree in contrib is rather out-dated unfortunately.

I've collected a bunch of patches in
https://github.com/helmo/git/tree/subtree-updates

The documentation issue is also fixed in there.

-- 

Met vriendelijke groet / Regards,

Herman van Rink
Initfour websolutions

^ permalink raw reply

* Re: [PATCH] grep: remove tautological check
From: Peter Krefting @ 2012-10-20 19:23 UTC (permalink / raw)
  To: David Soria Parra; +Cc: git
In-Reply-To: <1350753964-29346-1-git-send-email-dsp@php.net>

David Soria Parra:

> The enum grep_header_field is unsigned.

Enumerations can be either unsigned or signed, it is up to the 
compiler to decide. Even if you assign only positive number to named 
enumeration values, there are compilers that make them signed. I've 
been bitten by that enough.

-- 
\\// Peter - http://www.softwolves.pp.se/

^ permalink raw reply

* Report a bug, about track remote repository.
From: Cheeray Huang @ 2012-10-20 18:49 UTC (permalink / raw)
  To: git

Hi,

I think I found a bug, when I used local branches to track remote 
branch. But I'm not very sure, can anyone double check this?  I'd like 
to finger this out. I think you can reproduce this bug as below steps:

precondition:

Suppose that you have a remote branch in repository, named origin/work. 
And then you want to track it with a local branch.

Steps:

1. So you can do this:

git checkout -t origin/work

now, you have a local branch also named "work" to track "origin/work".
It works nicely, you can use "push/pull" command without any detail 
parameters to sync anything with the remote branch.

2. Create another branch, ex. named "work2", to track "origin/work" 
again, though maybe there are not so many people that will do like this.

You will find that local branch "work2" can't "push" to "origin/work".
ex. After you committed something in work2, you typed "git status", git 
would tell you:

Your branch is ahead of 'origin/work' by x commit.

And then you used "git push", git can't display the information about 
changing hash value in remote branch, just printed "everything is up to 
date".

Actually, you can use some exact parameters to solve this,  such as:

git push origin work2:work

But, I still think it is a bug.

BTW, I found this bug when I used github. I don't know whether it is  
related to github.


-- 
B&R,
Cheeray

^ permalink raw reply

* [PATCH] grep: remove tautological check
From: David Soria Parra @ 2012-10-20 17:26 UTC (permalink / raw)
  To: git; +Cc: David Soria Parra

The enum grep_header_field is unsigned. Therefore the field part of the
grep_pat structure is unsigned and cannot be less then 0. We remove the
tautological check for p->field < 0.

Signed-off-by: David Soria Parra <dsp@php.net>
---
 grep.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/grep.c b/grep.c
index 4bd1b8b..db177ef 100644
--- a/grep.c
+++ b/grep.c
@@ -625,7 +625,7 @@ static struct grep_expr *prep_header_patterns(struct grep_opt *opt)
 	for (p = opt->header_list; p; p = p->next) {
 		if (p->token != GREP_PATTERN_HEAD)
 			die("bug: a non-header pattern in grep header list.");
-		if (p->field < 0 || GREP_HEADER_FIELD_MAX <= p->field)
+		if (GREP_HEADER_FIELD_MAX <= p->field)
 			die("bug: unknown header field %d", p->field);
 		compile_regexp(p, opt);
 	}
-- 
1.8.0.rc3.332.g181c802

^ permalink raw reply related

* Re: [PATCH v2] Add new remote-hg transport helper
From: Felipe Contreras @ 2012-10-20 16:04 UTC (permalink / raw)
  To: Mike Hommey
  Cc: git, Junio C Hamano, Sverre Rabbelier, Ilari Liusvaara,
	Daniel Barkalow, Jeff King, Michael J Gruber
In-Reply-To: <20121020154301.GA31829@glandium.org>

On Sat, Oct 20, 2012 at 5:43 PM, Mike Hommey <mh@glandium.org> wrote:
> On Sat, Oct 20, 2012 at 05:00:06PM +0200, Felipe Contreras wrote:
>> Changes since v1:
>>
>>  * Improved documentation
>>  * Use more common 'python' binary
>>  * Warn, don't barf when a branch has multiple heads
>>  * Fixed marks to fetch after cloned
>>  * Support for cloning/pulling remote repositories
>>  * Use a more appropriate internal directory (e.g. .git/hg/origin)
>>  * Fixes for python3
>
> Are the resulting commits identical to what you'd get from using hg-git?

No, but should be easy to implement.

-- 
Felipe Contreras

^ permalink raw reply

* Re: [PATCH v2] Add new remote-hg transport helper
From: Mike Hommey @ 2012-10-20 15:43 UTC (permalink / raw)
  To: Felipe Contreras
  Cc: git, Junio C Hamano, Sverre Rabbelier, Ilari Liusvaara,
	Daniel Barkalow, Jeff King, Michael J Gruber
In-Reply-To: <1350745206-28955-1-git-send-email-felipe.contreras@gmail.com>

On Sat, Oct 20, 2012 at 05:00:06PM +0200, Felipe Contreras wrote:
> Changes since v1:
> 
>  * Improved documentation
>  * Use more common 'python' binary
>  * Warn, don't barf when a branch has multiple heads
>  * Fixed marks to fetch after cloned
>  * Support for cloning/pulling remote repositories
>  * Use a more appropriate internal directory (e.g. .git/hg/origin)
>  * Fixes for python3

Are the resulting commits identical to what you'd get from using hg-git?

Mike

^ permalink raw reply

* [PATCH v2] Add new remote-hg transport helper
From: Felipe Contreras @ 2012-10-20 15:00 UTC (permalink / raw)
  To: git
  Cc: Junio C Hamano, Sverre Rabbelier, Ilari Liusvaara,
	Daniel Barkalow, Jeff King, Michael J Gruber, Felipe Contreras

Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com>
---

I've looked at many hg<->git tools and none satisfy me. Too complicated, or too
slow, or to difficult to setup, etc.

The only one I've liked so far is hg-fast-export[1], which is indeed fast,
relatively simple, and relatively easy to use. But it's not properly maintained
any more.

So, I decided to write my own from scratch, using hg-fast-export as
inspiration, and voila.

This one doesn't have any dependencies, just put it into your $PATH, and you
can clone and fetch hg repositories. More importantly to me; the code is
simple, and easy to maintain.

One important remote-hg alternative is the one written by Sverre Rabbelier that
is now maintained and distributed in msysgit, however, in my opinion the code
is bloated, and there isn't even a standalone branch to take a look at the
patches, and give them a try.

This version has some features that Sverre's version doesn't:

 * Support for tags
 * Support to specify branchesto pull

Sverre's version has some features this one doesn't:

 * Support for pushing
 * Tests

[1] http://repo.or.cz/w/fast-export.git

Changes since v1:

 * Improved documentation
 * Use more common 'python' binary
 * Warn, don't barf when a branch has multiple heads
 * Fixed marks to fetch after cloned
 * Support for cloning/pulling remote repositories
 * Use a more appropriate internal directory (e.g. .git/hg/origin)
 * Fixes for python3

 contrib/remote-hg/git-remote-hg | 254 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 254 insertions(+)
 create mode 100755 contrib/remote-hg/git-remote-hg

diff --git a/contrib/remote-hg/git-remote-hg b/contrib/remote-hg/git-remote-hg
new file mode 100755
index 0000000..cc53091
--- /dev/null
+++ b/contrib/remote-hg/git-remote-hg
@@ -0,0 +1,254 @@
+#!/usr/bin/python
+
+# Inspired by Rocco Rutte's hg-fast-export
+
+# Just copy to your ~/bin, or anywhere in your $PATH.
+# Then you can clone with:
+# git clone hg::/path/to/mercurial/repo/
+
+from mercurial import hg, ui
+
+import re
+import sys
+import os
+import json
+
+first = True
+
+def die(msg, *args):
+    sys.stderr.write('ERROR: %s\n' % (msg % args))
+    sys.exit(1)
+
+def warn(msg, *args):
+    sys.stderr.write('WARNING: %s\n' % (msg % args))
+
+def gitmode(flags):
+    return 'l' in flags and '120000' or 'x' in flags and '100755' or '100644'
+
+def export_file(fc):
+    if fc.path() == '.hgtags':
+        return
+    d = fc.data()
+    print "M %s inline %s" % (gitmode(fc.flags()), fc.path())
+    print "data %d" % len(d)
+    print d
+
+def get_filechanges(repo, ctx, parents):
+    l = [repo.status(p, ctx)[:3] for p in parents]
+    changed, added, removed = [sum(e, []) for e in zip(*l)]
+    return added + changed, removed
+
+author_re = re.compile('^((.+?) )?(<.+?>)$')
+
+def fixup_user(user):
+    user = user.replace('"', '')
+    m = author_re.match(user)
+    if m:
+        name = m.group(1)
+        mail = m.group(3)
+    else:
+        name = user
+        mail = None
+
+    if not name:
+        name = 'Unknown'
+    if not mail:
+        mail = '<unknown>'
+
+    return '%s %s' % (name, mail)
+
+def get_repo(path, alias):
+    global dirname
+
+    myui = ui.ui()
+    myui.setconfig('ui', 'interactive', 'off')
+
+    if hg.islocal(path):
+        repo = hg.repository(myui, path)
+    else:
+        local_path = os.path.join(dirname, 'clone')
+        if not os.path.exists(local_path):
+            srcpeer, dstpeer = hg.clone(myui, {}, path, local_path, update=False, pull=True)
+            repo = dstpeer.local()
+        else:
+            repo = hg.repository(myui, local_path)
+            peer = hg.peer(myui, {}, path)
+            repo.pull(peer, heads=None, force=True)
+
+    return repo
+
+def hg_branch(b):
+    if b == 'master':
+        return 'default'
+    return b
+
+def git_branch(b):
+    if b == 'default':
+        return 'master'
+    return b
+
+def export_tag(repo, tag):
+    global prefix
+    print "reset %s/tags/%s" % (prefix, tag)
+    print "from :%s" % (repo[tag].rev() + 1)
+    print
+
+def export_branch(repo, branch):
+    global prefix, marks, cache, branches
+
+    heads = branches[hg_branch(branch)]
+
+    # verify there's only one head
+    if (len(heads) > 1):
+        warn("Branch '%s' has more than one head, consider merging" % hg_branch(branch))
+
+    head = repo[heads[0]]
+    tip = marks.get(branch, 0)
+    # mercurial takes too much time checking this
+    if tip == head.rev():
+        # nothing to do
+        return
+    revs = repo.revs('%u:%u' % (tip, head))
+    count = 0
+
+    revs = [rev for rev in revs if not cache.get(rev, False)]
+
+    for rev in revs:
+
+        c = repo[rev]
+        (manifest, user, (time, tz), files, desc, extra) = repo.changelog.read(c.node())
+        rev_branch = git_branch(extra['branch'])
+
+        tz = '%+03d%02d' % (-tz / 3600, -tz % 3600 / 60)
+
+        print "commit %s/branches/%s" % (prefix, rev_branch)
+        print "mark :%d" % (rev + 1)
+        print "committer %s %d %s" % (fixup_user(user), time, tz)
+        print "data %d" % (len(desc) + 1)
+        print desc
+        print
+
+        parents = [p for p in repo.changelog.parentrevs(rev) if p >= 0]
+
+        if len(parents) == 0:
+            modified = c.manifest().keys()
+            removed = []
+        else:
+            added = []
+            changed = []
+            print "from :%s" % (parents[0] + 1)
+            if len(parents) > 1:
+                print "merge :%s" % (parents[1] + 1)
+            modified, removed = get_filechanges(repo, c, parents)
+
+        for f in removed:
+            print "D %s" % (f)
+        for f in modified:
+            export_file(c.filectx(f))
+        print
+
+        count += 1
+        if (count % 100 == 0):
+            print "progress revision %d '%s' (%d/%d)" % (rev, branch, count, len(revs))
+            print "#############################################################"
+
+        cache[rev] = True
+
+    # store the latest revision
+    marks[branch] = rev
+
+def do_capabilities(repo, args):
+    global prefix, dirname
+
+    print "import"
+    print "refspec refs/heads/*:%s/branches/*" % prefix
+    print "refspec refs/tags/*:%s/tags/*" % prefix
+    print
+
+def do_list(repo, args):
+    global branches
+
+    head = repo.dirstate.branch()
+    for branch in repo.branchmap():
+        heads = repo.branchheads(branch)
+        if len(heads):
+            branches[branch] = heads
+
+    for branch in branches:
+        print "? refs/heads/%s" % git_branch(branch)
+    for tag, node in repo.tagslist():
+        if tag == 'tip':
+            continue
+        print "? refs/tags/%s" % tag
+    print "@refs/heads/%s HEAD" % git_branch(head)
+    print
+
+def do_import(repo, args):
+    global first
+
+    ref = args[1]
+
+    if first:
+        path = os.path.join(dirname, 'marks-git')
+
+        if os.path.exists(path):
+            print "feature import-marks=%s" % path
+        print "feature export-marks=%s" % path
+        sys.stdout.flush()
+        first = False
+
+    if (ref == 'HEAD'):
+        return
+
+    if ref.startswith('refs/heads/'):
+        branch = ref[len('refs/heads/'):]
+        export_branch(repo, branch)
+    elif ref.startswith('refs/tags/'):
+        tag = ref[len('refs/tags/'):]
+        export_tag(repo, tag)
+
+def main(args):
+    global prefix, dirname, marks, cache, branches
+
+    alias = args[1]
+    url = args[2]
+
+    gitdir = os.environ['GIT_DIR']
+    dirname = os.path.join(gitdir, 'hg', alias)
+    cache = {}
+    branches = {}
+
+    repo = get_repo(url, alias)
+    prefix = 'refs/hg/%s' % alias
+
+    if not os.path.exists(dirname):
+        os.makedirs(dirname)
+
+    marks_path = os.path.join(dirname, 'marks-hg')
+    try:
+        fp = open(marks_path, 'r')
+        marks = json.load(fp)
+        fp.close()
+    except IOError:
+        marks = {}
+
+    line = True
+    while (line):
+        line = sys.stdin.readline().strip()
+        if line == '':
+            break
+        args = line.split()
+        cmd = args[0]
+        if cmd == 'capabilities':
+            do_capabilities(repo, args)
+        elif cmd == 'list':
+            do_list(repo, args)
+        elif cmd == 'import':
+            do_import(repo, args)
+        sys.stdout.flush()
+
+    fp = open(marks_path, 'w')
+    json.dump(marks, fp)
+    fp.close()
+
+sys.exit(main(sys.argv))
-- 
1.8.0.rc2.7.g0961fdf.dirty

^ permalink raw reply related

* Re: Problems with  ./t9902-completion.sh
From: Torsten Bögershausen @ 2012-10-20 12:50 UTC (permalink / raw)
  To: Torsten Bögershausen; +Cc: Git Mailing List
In-Reply-To: <508292DC.8030700@web.de>

On 20.10.12 14:02, Torsten Bögershausen wrote:
> t9902  does not work on my Mac OS box,
> but only in one working directory.
> 
> Any idea where the "check-ignore" comea from ?
> /Torsten
> 


Oh, I find the answer myself:
 git status

# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#       ../git-check-ignore

From some experiments there was a git-check-ignore left.
(and make clean doesn't delete it)

sorry for the noise.

^ permalink raw reply

* Problems with  ./t9902-completion.sh
From: Torsten Bögershausen @ 2012-10-20 12:02 UTC (permalink / raw)
  To: Git Mailing List; +Cc: Torsten Bögershausen

t9902  does not work on my Mac OS box,
but only in one working directory.

Any idea where the "check-ignore" comea from ?
/Torsten


[snip]
--- expected    2012-10-20 11:54:35.000000000 +0000
+++ out    2012-10-20 11:54:35.000000000 +0000
@@ -1 +1,2 @@
+check-ignore
 checkout

This patch corrects the problem:
(s/check"/checko"/)


diff --git a/t/t9902-completion.sh b/t/t9902-completion.sh
index cbd0fb6..0df751b 100755
--- a/t/t9902-completion.sh
+++ b/t/t9902-completion.sh
@@ -222,19 +222,19 @@ test_expect_success 'general options' '
 '
 
 test_expect_success 'general options plus command' '
-       test_completion "git --version check" "checkout " &&
-       test_completion "git --paginate check" "checkout " &&
-       test_completion "git --git-dir=foo check" "checkout " &&
-       test_completion "git --bare check" "checkout " &&
+       test_completion "git --version checko" "checkout " &&
+       test_completion "git --paginate checko" "checkout " &&
+       test_completion "git --git-dir=foo checko" "checkout " &&
+       test_completion "git --bare checko" "checkout " &&
        test_completion "git --help des" "describe " &&
-       test_completion "git --exec-path=foo check" "checkout " &&
-       test_completion "git --html-path check" "checkout " &&
-       test_completion "git --no-pager check" "checkout " &&
-       test_completion "git --work-tree=foo check" "checkout " &&
-       test_completion "git --namespace=foo check" "checkout " &&
-       test_completion "git --paginate check" "checkout " &&
-       test_completion "git --info-path check" "checkout " &&
-       test_completion "git --no-replace-objects check" "checkout "
+       test_completion "git --exec-path=foo checko" "checkout " &&
+       test_completion "git --html-path checko" "checkout " &&
+       test_completion "git --no-pager checko" "checkout " &&
+       test_completion "git --work-tree=foo checko" "checkout " &&
+       test_completion "git --namespace=foo checko" "checkout " &&
+       test_completion "git --paginate checko" "checkout " &&
+       test_completion "git --info-path checko" "checkout " &&
+       test_completion "git --no-replace-objects checko" "checkout "
 '

^ permalink raw reply related

* [PATCH] New "git status" format with --alternate
From: Nguyễn Thái Ngọc Duy @ 2012-10-20  9:36 UTC (permalink / raw)
  To: git; +Cc: Nguyễn Thái Ngọc Duy

Another UI experiment, thrown at git@vger to see if it sticks. I've
been using this for a week and it feels good in general. But it may be
too specific to my taste to be useful for more people.

This format utilizes the screen estate as much as possible. It relies
on colors, so monochrome users are stuck with default format. In
short, it's a "GNU ls"-like output with footnotes:

 - entries of all kinds (untracked, modified, cached...) are sorted in
   a single list, laid out in columns
 - different kinds of files have different colors, more on this later
 - square brackets around a tracked file means differences between
   index and HEAD (aka "git diff --cached").
 - square brackets on untracked file means ignored file
 - more information such as renames, unmerged tyes... is added in form
   of footnotes

On a clean repository, "git status" prints nothing. Branch state
(rebasing/am-ing/....) is also printed.

This format is denser than the default format and easier to read (to
me) as there is only one table. Colors and brackets are the visual
clues. All the use of colors and brackets are explained in footnotes,
so new users should have no problems with it (provided that they know
basic concepts).

About colors, untracked files have no colors. Tracked files always do
(to catch your eyes). Added/Removed/Modified/Unmerged have different
colors. Text color reflects the changes between worktree and index
(aka "git diff"). Bracket color reflects changes between index and
HEAD (aka "git diff --cached").

If you see all magenta (modified) text without brackets, "git commit -a"
is your friend. If you see all yellow text (unmodified worktree)
and magenta brackets, "git commit" to go. A mix of magenta text and
brackets mean you need to do "git diff --cached" and "git diff" to
know what changes you are going to commit.

The merge of untracked/tracked files could be annoying if you don't
keep your repository clean, though. Not sure if mering is a good idea,
or just split them into two tables.

Final note: messy and incomplete implementation.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclouds@gmail.com>
---
 builtin/commit.c |  11 ++
 wt-status.c      | 339 ++++++++++++++++++++++++++++++++++++++++++++++++++++---
 wt-status.h      |   1 +
 3 files changed, 338 insertions(+), 13 deletions(-)

diff --git a/builtin/commit.c b/builtin/commit.c
index a17a5df..758cf11 100644
--- a/builtin/commit.c
+++ b/builtin/commit.c
@@ -114,6 +114,7 @@ static struct strbuf message = STRBUF_INIT;
 static enum {
 	STATUS_FORMAT_LONG,
 	STATUS_FORMAT_SHORT,
+	STATUS_FORMAT_ALTERNATE,
 	STATUS_FORMAT_PORCELAIN
 } status_format = STATUS_FORMAT_LONG;
 
@@ -451,6 +452,9 @@ static int run_status(FILE *fp, const char *index_file, const char *prefix, int
 	case STATUS_FORMAT_SHORT:
 		wt_shortstatus_print(s);
 		break;
+	case STATUS_FORMAT_ALTERNATE:
+		wt_altstatus_print(s);
+		break;
 	case STATUS_FORMAT_PORCELAIN:
 		wt_porcelain_print(s);
 		break;
@@ -1154,6 +1158,8 @@ int cmd_status(int argc, const char **argv, const char *prefix)
 		OPT__VERBOSE(&verbose, N_("be verbose")),
 		OPT_SET_INT('s', "short", &status_format,
 			    N_("show status concisely"), STATUS_FORMAT_SHORT),
+		OPT_SET_INT(0, "alternate", &status_format,
+			    N_("show status concisely"), STATUS_FORMAT_ALTERNATE),
 		OPT_BOOLEAN('b', "branch", &s.show_branch,
 			    N_("show branch information")),
 		OPT_SET_INT(0, "porcelain", &status_format,
@@ -1188,6 +1194,8 @@ int cmd_status(int argc, const char **argv, const char *prefix)
 
 	if (s.null_termination && status_format == STATUS_FORMAT_LONG)
 		status_format = STATUS_FORMAT_PORCELAIN;
+	if (s.null_termination && status_format == STATUS_FORMAT_ALTERNATE)
+		die(_("--alternate does not work with -z"));
 
 	handle_untracked_files_arg(&s);
 	if (show_ignored_in_status)
@@ -1213,6 +1221,9 @@ int cmd_status(int argc, const char **argv, const char *prefix)
 	case STATUS_FORMAT_SHORT:
 		wt_shortstatus_print(&s);
 		break;
+	case STATUS_FORMAT_ALTERNATE:
+		wt_altstatus_print(&s);
+		break;
 	case STATUS_FORMAT_PORCELAIN:
 		wt_porcelain_print(&s);
 		break;
diff --git a/wt-status.c b/wt-status.c
index 2a9658b..7502591 100644
--- a/wt-status.c
+++ b/wt-status.c
@@ -928,34 +928,40 @@ static void show_bisect_in_progress(struct wt_status *s,
 	wt_status_print_trailer(s);
 }
 
-static void wt_status_print_state(struct wt_status *s)
+static void wt_status_get_state(struct wt_status *s,
+				struct wt_status_state *state)
 {
-	const char *state_color = color(WT_STATUS_HEADER, s);
-	struct wt_status_state state;
 	struct stat st;
-
-	memset(&state, 0, sizeof(state));
+	memset(state, 0, sizeof(*state));
 
 	if (!stat(git_path("MERGE_HEAD"), &st)) {
-		state.merge_in_progress = 1;
+		state->merge_in_progress = 1;
 	} else if (!stat(git_path("rebase-apply"), &st)) {
 		if (!stat(git_path("rebase-apply/applying"), &st)) {
-			state.am_in_progress = 1;
+			state->am_in_progress = 1;
 			if (!stat(git_path("rebase-apply/patch"), &st) && !st.st_size)
-				state.am_empty_patch = 1;
+				state->am_empty_patch = 1;
 		} else {
-			state.rebase_in_progress = 1;
+			state->rebase_in_progress = 1;
 		}
 	} else if (!stat(git_path("rebase-merge"), &st)) {
 		if (!stat(git_path("rebase-merge/interactive"), &st))
-			state.rebase_interactive_in_progress = 1;
+			state->rebase_interactive_in_progress = 1;
 		else
-			state.rebase_in_progress = 1;
+			state->rebase_in_progress = 1;
 	} else if (!stat(git_path("CHERRY_PICK_HEAD"), &st)) {
-		state.cherry_pick_in_progress = 1;
+		state->cherry_pick_in_progress = 1;
 	}
 	if (!stat(git_path("BISECT_LOG"), &st))
-		state.bisect_in_progress = 1;
+		state->bisect_in_progress = 1;
+}
+
+static void wt_status_print_state(struct wt_status *s)
+{
+	const char *state_color = color(WT_STATUS_HEADER, s);
+	struct wt_status_state state;
+
+	wt_status_get_state(s, &state);
 
 	if (state.merge_in_progress)
 		show_merge_in_progress(s, &state, state_color);
@@ -1224,6 +1230,313 @@ void wt_shortstatus_print(struct wt_status *s)
 	}
 }
 
+static int cmp_items(const void *a, const void *b)
+{
+	const struct string_list_item *const *one = a;
+	const struct string_list_item *const *two = b;
+	return strcmp((*one)->string, (*two)->string);
+}
+
+static const char *col_unmerged = GIT_COLOR_CYAN;
+static const char *col_added = GIT_COLOR_GREEN;
+static const char *col_deleted = GIT_COLOR_RED;
+static const char *col_updated = GIT_COLOR_MAGENTA;
+static const char *col_tracked = GIT_COLOR_YELLOW;
+static const char *col_reset = GIT_COLOR_RESET;
+
+#define SHOW_TRACKED		8
+#define SHOW_UNMERGED		9
+#define SHOW_ADDED		10
+#define SHOW_DELETED		11
+#define SHOW_UPDATED		12
+#define SHOW_WORKTREE_DELETED	13
+#define SHOW_WORKTREE_UPDATED	14
+#define SHOW_UNTRACKED		15
+#define SHOW_IGNORED		16
+
+static void wt_altstatus_unmerged(struct wt_status *s,
+				  const char *name,
+				  struct wt_status_change_data *d,
+				  struct strbuf *out,
+				  struct string_list *footnotes,
+				  int *shown_how)
+{
+	struct strbuf onebuf = STRBUF_INIT;
+	const char *one;
+	const char *how = "";
+
+	switch (d->stagemask) {
+	case 1: how = "DD"; break; /* both deleted */
+	case 2: how = "AU"; break; /* added by us */
+	case 3: how = "UD"; break; /* deleted by them */
+	case 4: how = "UA"; break; /* added by them */
+	case 5: how = "DU"; break; /* deleted by us */
+	case 6: how = "AA"; break; /* both added */
+	case 7: how = "UU"; break; /* both modified */
+	}
+
+	if (!shown_how[d->stagemask]) {
+		const char *legend = NULL;
+		shown_how[d->stagemask] = 1;
+		switch (d->stagemask) {
+		case 1: legend = "[DD] deleted by both"; break;
+		case 2: legend = "[AU] added by us"; break;
+		case 3: legend = "[UD] deleted by them"; break;
+		case 4: legend = "[UA] added by them"; break;
+		case 5: legend = "[DU] deleted by us"; break;
+		case 6: legend = "[AA] added by both"; break;
+		case 7: legend = "[UU] modified by both"; break;
+		}
+		if (legend)
+			string_list_append(footnotes, xstrdup(legend));
+	}
+
+	if (!shown_how[SHOW_UNMERGED]) {
+		struct strbuf legend = STRBUF_INIT;
+		strbuf_addf(&legend, "%sfile%s -> unmerged entry",
+			    col_unmerged, col_reset);
+		string_list_append(footnotes, strbuf_detach(&legend, NULL));
+		shown_how[SHOW_UNMERGED] = 1;
+	}
+
+	one = quote_path(name, -1, &onebuf, s->prefix);
+	if (*one != '"' && strchr(one, ' ') != NULL) {
+		putchar('"');
+		strbuf_addch(&onebuf, '"');
+		one = onebuf.buf;
+	}
+	strbuf_addf(out," %s%s%s [%s]", col_unmerged, one, col_reset, how);
+	strbuf_release(&onebuf);
+}
+
+static void wt_altstatus_tracked(struct wt_status *s,
+				 const char *name,
+				 struct wt_status_change_data *d,
+				 struct strbuf *out,
+				 struct string_list *footnotes,
+				 int *shown_how)
+{
+	struct strbuf onebuf = STRBUF_INIT;
+	const char *one;
+	const char *color;
+
+	one = quote_path(name, -1, &onebuf, s->prefix);
+	if (*one != '"' && strchr(one, ' ') != NULL) {
+		putchar('"');
+		strbuf_addch(&onebuf, '"');
+		one = onebuf.buf;
+	}
+
+	switch (d->worktree_status) {
+	case DIFF_STATUS_DELETED:
+		color = col_deleted;
+		if (!shown_how[SHOW_WORKTREE_DELETED]) {
+			struct strbuf legend = STRBUF_INIT;
+			strbuf_addf(&legend, "%s[  ]%s -> removed from worktree",
+				    col_deleted, col_reset);
+			string_list_append(footnotes, strbuf_detach(&legend, NULL));
+			shown_how[SHOW_WORKTREE_DELETED] = 1;
+		}
+		break;
+	case 0:
+		color = col_tracked;
+		if (!shown_how[SHOW_TRACKED]) {
+			struct strbuf legend = STRBUF_INIT;
+			strbuf_addf(&legend, "%sfile%s -> worktree same as in index",
+				    col_tracked, col_reset);
+			string_list_append(footnotes, strbuf_detach(&legend, NULL));
+			shown_how[SHOW_TRACKED] = 1;
+		}
+		break;
+	default:
+		color = col_updated;
+		if (!shown_how[SHOW_WORKTREE_UPDATED]) {
+			struct strbuf legend = STRBUF_INIT;
+			strbuf_addf(&legend, "%sfile%s -> modified in worktree",
+				    col_updated, col_reset);
+			string_list_append(footnotes, strbuf_detach(&legend, NULL));
+			shown_how[SHOW_WORKTREE_UPDATED] = 1;
+		}
+	}
+
+	switch (d->index_status) {
+	case DIFF_STATUS_ADDED:
+		strbuf_addf(out, "%s[ %s%s%s ]%s",
+			    col_added, color, one,
+			    col_added, col_reset);
+		if (!shown_how[SHOW_ADDED]) {
+			struct strbuf legend = STRBUF_INIT;
+			strbuf_addf(&legend, "%sfile%s -> added to index",
+				    col_added, col_reset);
+			string_list_append(footnotes, strbuf_detach(&legend, NULL));
+			shown_how[SHOW_ADDED] = 1;
+		}
+		break;
+	case DIFF_STATUS_DELETED:
+		strbuf_addf(out, "%s[ %s%s%s ]%s",
+			    col_deleted, color, one,
+			    col_deleted, col_reset);
+		if (!shown_how[SHOW_DELETED]) {
+			struct strbuf legend = STRBUF_INIT;
+			strbuf_addf(&legend, "%sfile%s -> removed from index",
+				    col_deleted, col_reset);
+			string_list_append(footnotes, strbuf_detach(&legend, NULL));
+			shown_how[SHOW_DELETED] = 1;
+		}
+		break;
+	case 0:
+		strbuf_addf(out, "  %s%s%s", color, one, col_reset);
+		break;
+	default:
+		strbuf_addf(out, "%s[ %s%s%s ]%s",
+			    col_updated, color, one,
+			    col_updated, col_reset);
+		if (!shown_how[SHOW_UPDATED]) {
+			struct strbuf legend = STRBUF_INIT;
+			strbuf_addf(&legend, "%s[  ]%s -> changes in index",
+				    col_updated, col_reset);
+			string_list_append(footnotes, strbuf_detach(&legend, NULL));
+			shown_how[SHOW_UPDATED] = 1;
+		}
+	}
+
+	strbuf_release(&onebuf);
+
+	/* extra things at the end */
+	switch (d->worktree_status) {
+	case DIFF_STATUS_ADDED:
+	case DIFF_STATUS_DELETED:
+		break;
+	case DIFF_STATUS_TYPE_CHANGED:
+		/* FIXME */
+		strbuf_addf(out, "%s+x%s", GIT_COLOR_YELLOW,
+			    GIT_COLOR_RESET);
+		break;
+	case 0:
+		break;
+	}
+
+	if (d->head_path) {
+		struct strbuf tmp = STRBUF_INIT;
+		int id = footnotes->nr + 1;
+		strbuf_addf(out, " [%d]", id);
+		one = quote_path(d->head_path, -1, &onebuf, s->prefix);
+		if (*one != '"' && strchr(one, ' ') != NULL) {
+			putchar('"');
+			strbuf_addch(&onebuf, '"');
+			one = onebuf.buf;
+		}
+		strbuf_addf(&tmp, "[%d] renamed from %s", id, onebuf.buf);
+		strbuf_release(&onebuf);
+		string_list_append(footnotes, strbuf_detach(&tmp, NULL));
+	}
+}
+
+void wt_altstatus_print(struct wt_status *s)
+{
+	int i, n;
+	struct string_list_item **all, **p;
+	struct string_list footnotes = STRING_LIST_INIT_NODUP;
+	struct string_list output = STRING_LIST_INIT_NODUP;
+	struct column_options copts;
+	struct wt_status_state state;
+	int shown_how[17];
+
+	n = s->untracked.nr + s->ignored.nr + s->change.nr;
+	p = all = xmalloc(sizeof(*all) * n);
+
+	for (i = 0; i < s->change.nr; i++)
+		*p++ = s->change.items + i;
+	for (i = 0; i < s->untracked.nr; i++)
+		*p++ = s->untracked.items + i;
+	for (i = 0; i < s->ignored.nr; i++)
+		*p++ = s->ignored.items + i;
+	qsort(all, n, sizeof(*all), cmp_items);
+
+	wt_status_get_state(s, &state);
+	if (state.merge_in_progress)
+		printf("%s(Merge in progress)%s\n",
+		       GIT_COLOR_YELLOW,
+		       GIT_COLOR_RESET);
+	else if (state.am_in_progress)
+		printf("%s(git-am in progress)%s\n",
+		       GIT_COLOR_YELLOW,
+		       GIT_COLOR_RESET);
+	else if (state.rebase_in_progress || state.rebase_interactive_in_progress)
+		printf("%s(Rebase in progress)%s\n",
+		       GIT_COLOR_YELLOW,
+		       GIT_COLOR_RESET);
+	else if (state.cherry_pick_in_progress)
+		printf("%s(Cherry-pick in progress)%s\n",
+		       GIT_COLOR_YELLOW,
+		       GIT_COLOR_RESET);
+	if (state.bisect_in_progress)
+		printf("%s(Bisect in progress)%s\n",
+		       GIT_COLOR_YELLOW,
+		       GIT_COLOR_RESET);
+
+	memset(shown_how, 0, sizeof(shown_how));
+
+	memset(&copts, 0, sizeof(copts));
+	copts.padding = 1;
+
+	for (i = 0; i < n; i++) {
+		struct string_list_item *it = all[i];
+		struct strbuf out = STRBUF_INIT;
+
+		if (it >= s->change.items &&
+		    it < s->change.items + s->change.nr) {
+			struct wt_status_change_data *d;
+
+			d = it->util;
+			if (d->stagemask)
+				wt_altstatus_unmerged(s, it->string, d, &out, &footnotes, shown_how);
+			else
+				wt_altstatus_tracked(s, it->string, d, &out, &footnotes, shown_how);
+		} else {
+			struct strbuf onebuf = STRBUF_INIT;
+			const char *one;
+
+			one = quote_path(it->string, -1, &onebuf, s->prefix);
+			if (*one != '"' && strchr(one, ' ') != NULL) {
+				putchar('"');
+				strbuf_addch(&onebuf, '"');
+				one = onebuf.buf;
+			}
+
+			if (it >= s->untracked.items &&
+				 it < s->untracked.items + s->untracked.nr) {
+				strbuf_addf(&out, "  %s", one);
+				if (!shown_how[SHOW_UNTRACKED]) {
+					string_list_append(&footnotes, xstrdup("file -> untracked file"));
+					shown_how[SHOW_UNTRACKED] = 1;
+				}
+			} else if (it >= s->ignored.items &&
+				 it < s->ignored.items + s->ignored.nr) {
+				strbuf_addf(&out, "[ %s ]", one);
+				if (!shown_how[SHOW_IGNORED]) {
+					string_list_append(&footnotes, xstrdup("[file] -> ignored file"));
+					shown_how[SHOW_IGNORED] = 1;
+				}
+			} else
+				die("Where does this item come from?");
+
+			strbuf_release(&onebuf);
+		}
+		string_list_append(&output, strbuf_detach(&out, NULL));
+	}
+	print_columns(&output, s->colopts, &copts);
+	string_list_clear(&output, 0);
+
+	if (footnotes.nr) {
+		printf("\n");
+		memset(&copts, 0, sizeof(copts));
+		copts.padding = 3;
+		print_columns(&footnotes, s->colopts, &copts);
+	}
+	string_list_clear(&footnotes, 0);
+}
+
 void wt_porcelain_print(struct wt_status *s)
 {
 	s->use_color = 0;
diff --git a/wt-status.h b/wt-status.h
index 236b41f..8804400 100644
--- a/wt-status.h
+++ b/wt-status.h
@@ -86,6 +86,7 @@ void wt_status_print(struct wt_status *s);
 void wt_status_collect(struct wt_status *s);
 
 void wt_shortstatus_print(struct wt_status *s);
+void wt_altstatus_print(struct wt_status *s);
 void wt_porcelain_print(struct wt_status *s);
 
 void status_printf_ln(struct wt_status *s, const char *color, const char *fmt, ...)
-- 
1.8.0.rc2.25.gf0e8e5d

^ permalink raw reply related

* Re: [PATCH] Cache stat_tracking_info() for faster status and branch -v
From: Nguyen Thai Ngoc Duy @ 2012-10-20  9:02 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git
In-Reply-To: <7v7gqmjl6n.fsf@alter.siamese.dyndns.org>

On Sat, Oct 20, 2012 at 2:50 AM, Junio C Hamano <gitster@pobox.com> wrote:
> Not particularly interested in the cause, but not so strongly
> against it to veto it.

I wonder how many people keep old branches like I do, which are
usually far from remotes.

> Doesn't it make more sense to use a notes-cache that is keyed off of
> the commit object name X of the remote?  You will have a single note
> that stores a blob for the commit object remotes/origin/master, and
> the blob tells you how far the commit at the tip of 'frotz' is from
> it, and the same for 'xyzzy'.
>
> You would obviouly need to run "gc" on such a notes-cache tree from
> time to time, removing notes for commits that are not tip of any
> branch that could be a fork point, and from the remaining notes
> blobs, entries that describe commits that are not tip of any branch,
> if you go that route.

The notes-cache route looks much nicer. Thanks. We can also use Jeff's
persistent hash table from his rename-cache series.
-- 
Duy

^ permalink raw reply

* Re: libgit2 status
From: Andreas Ericsson @ 2012-10-20  7:58 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: Ramkumar Ramachandra, Thiago Farina, git, dag, Nicolas Sebrecht,
	greened
In-Reply-To: <7vvce6i5j2.fsf@alter.siamese.dyndns.org>

On 10/19/2012 10:13 PM, Junio C Hamano wrote:
> Ramkumar Ramachandra <artagnon@gmail.com> writes:
> 
>> Thiago Farina wrote:
>>> [...]
>>> With some structure like:
>>>
>>> include/git.h
>>> src/git.c
>>>
>>> ...
>>>
>>> whatever.
>>> [...]
>>
>> Junio- is it reasonable to expect the directory-restructuring by 2.0?
> 
> I actually hate "include/git.h vs src/git.c"; you have distinction
> between .c and .h already.
> 

Agreed. The way libgit2 does it is to have "src/tag.[ch]", which are
for internal use, and then "src/include/tag.h" which is the published
version that others can use to write code against the tag library.
src/tag.h always includes src/include/tag.h, so no code needs to be
duplicated, but internal parts of the library can still use lower-
level stuff if it wants to. It's a good compromise when creating a
library from application code and there were no opaque types from
the start.

-- 
Andreas Ericsson                   andreas.ericsson@op5.se
OP5 AB                             www.op5.se
Tel: +46 8-230225                  Fax: +46 8-230231

Considering the successes of the wars on alcohol, poverty, drugs and
terror, I think we should give some serious thought to declaring war
on peace.

^ permalink raw reply

* Re: [PATCH] contrib/hooks: avoid requiring root access in usage instructions
From: Jonathan Nieder @ 2012-10-20  7:03 UTC (permalink / raw)
  To: Junio C Hamano
  Cc: git, Olivier Berger, Michael Haggerty, Kevin P. Fleming,
	Chris Hiestand, Miklos Vajna
In-Reply-To: <7vzk3hhj1m.fsf@alter.siamese.dyndns.org>

Junio C Hamano wrote:

> We already encourage casting-in-stone a particular version of the
> sample hook when a new repository is created by copying them from
> the template directory.  This prevents from surprising users when an
> updated version of Git changes the behaviour of these samples.  Even
> if you think bugs in older ones may be corrected in newer ones,
> silently updating the hook the user chose to use by inspecting one
> particular version is not something we would want to do lightly.

For context, the sample hooks you are talking about are the *.sample
files from the templates/ directory.  Except for post-update.sample,
most are not very useful out of the box, and they are very much
intended as examples to start people's thinking, as opposed to
something one-size-fits-all.

By contrast, the post-receive-email script from contrib is a complete
program with a well-defined behavior and configuration that have
stayed consistent while the details of its implementation improved.
It can be used by symlinking into place, but maybe a better set of
instructions would say

	# This script takes no arguments and expects the same input format
	# as git's post-receive hook, so if this script is at
	# /usr/share/git-core/contrib/hooks/post-receive-email (as it is
	# on Debian and Fedora), you can do
	#
	#  cd /path/to/your/repository.git
	#  echo '#!/bin/sh' >hooks/post-receive
	#  echo 'exec /usr/share/git-core/contrib/hooks/post-receive-email' \
	#	>>hooks/post-receive
	#  chmod +x hooks/post-receive

That would make it more obvious what I can do next if my post-receive
input should be passed both to post-receive-email and some other tool
(perhaps in a pipeline using "tee").

Hmm?
Jonathan

^ permalink raw reply

* Re: [PATCH] contrib/hooks: avoid requiring root access in usage instructions
From: Junio C Hamano @ 2012-10-20  4:19 UTC (permalink / raw)
  To: Jonathan Nieder
  Cc: git, Olivier Berger, Michael Haggerty, Kevin P. Fleming,
	Chris Hiestand, Miklos Vajna
In-Reply-To: <20121020003104.GA26596@elie.Belkin>

Jonathan Nieder <jrnieder@gmail.com> writes:

> Comments in hooks/post-receive-email suggest:
>
>  For example, on debian the hook is stored in
>  /usr/share/git-core/contrib/hooks/post-receive-email:
>
>   chmod a+x post-receive-email
>   cd /path/to/your/repository.git
>   ln -sf /usr/share/git-core/contrib/hooks/post-receive-email hooks/post-receive
>
> Doing that means changing permissions on a file provided by a package,
> which is problematic in a number of ways: the permissions would be
> likely to change back in later upgrades, and changing them requires
> root access.  Copying the script into each repo that uses it is not
> much better, since each copy would be maintained separately and not
> benefit from bugfixes in the master copy.
>
> Better to ship the hook with executable permission and remove the
> chmod line so enabling the hook becomes a one-step process: just
> symlink it into place.
>
> Likewise for the pre-auto-gc-battery hook.
>
> Reported-by: Olivier Berger <olivier.berger@it-sudparis.eu>
> Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
> ---
> From <http://bugs.debian.org/687391>.
>
> Thoughts?

We already encourage casting-in-stone a particular version of the
sample hook when a new repository is created by copying them from
the template directory.  This prevents from surprising users when an
updated version of Git changes the behaviour of these samples.  Even
if you think bugs in older ones may be corrected in newer ones,
silently updating the hook the user chose to use by inspecting one
particular version is not something we would want to do lightly. A
buggy devil you know is better than a devil that suddenly changes
its behaviour depending on when your sysadmin updates the version of
Git without your knowing.

I personally think the same applies to these contrib/ hooks, and I
would think it is simpler and more consistent to correct the
instruction in these files to tell users to copy them.

Adding +x bits to these files is a good idea but that is orthogonal
to copying vs symlinking, I think.

> Jonathan
>
>  contrib/hooks/post-receive-email  | 1 -
>  contrib/hooks/pre-auto-gc-battery | 1 -
>  2 files changed, 2 deletions(-)
>  mode change 100644 => 100755 contrib/hooks/pre-auto-gc-battery
>
> diff --git a/contrib/hooks/post-receive-email b/contrib/hooks/post-receive-email
> index 8ca6607a..359f1ad2 100755
> --- a/contrib/hooks/post-receive-email
> +++ b/contrib/hooks/post-receive-email
> @@ -13,7 +13,6 @@
>  # For example, on debian the hook is stored in
>  # /usr/share/git-core/contrib/hooks/post-receive-email:
>  #
> -#  chmod a+x post-receive-email
>  #  cd /path/to/your/repository.git
>  #  ln -sf /usr/share/git-core/contrib/hooks/post-receive-email hooks/post-receive
>  #
> diff --git a/contrib/hooks/pre-auto-gc-battery b/contrib/hooks/pre-auto-gc-battery
> old mode 100644
> new mode 100755
> index 1f914c94..9d0c2d19
> --- a/contrib/hooks/pre-auto-gc-battery
> +++ b/contrib/hooks/pre-auto-gc-battery
> @@ -13,7 +13,6 @@
>  # For example, if the hook is stored in
>  # /usr/share/git-core/contrib/hooks/pre-auto-gc-battery:
>  #
> -# chmod a+x pre-auto-gc-battery
>  # cd /path/to/your/repository.git
>  # ln -sf /usr/share/git-core/contrib/hooks/pre-auto-gc-battery \
>  #	hooks/pre-auto-gc

^ 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