Git development
 help / color / mirror / Atom feed
* [PATCH] docs: minor grammar fixes for v1.7.9 release notes
From: Jeff King @ 2012-01-25 22:20 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git


Signed-off-by: Jeff King <peff@peff.net>
---
Easier to view with --color-words, of course.

I also looked through "git log --first-parent v1.7.8..master" to see if
anything had been missed. I think you hit the feature highlights pretty
well (I notice you mostly include features and not bug-fixes, which I
assume is to keep the list to a readable length).

 Documentation/RelNotes/1.7.9.txt |   13 +++++++------
 1 files changed, 7 insertions(+), 6 deletions(-)

diff --git a/Documentation/RelNotes/1.7.9.txt b/Documentation/RelNotes/1.7.9.txt
index f1294b4..95320aa 100644
--- a/Documentation/RelNotes/1.7.9.txt
+++ b/Documentation/RelNotes/1.7.9.txt
@@ -12,19 +12,20 @@ Updates since v1.7.8
 
  * Git uses gettext to translate its most common interface messages
    into the user's language if translations are available and the
-   locale is appropriately set. Distributors can drop in new PO files
+   locale is appropriately set. Distributors can drop new PO files
    in po/ to add new translations.
 
- * The code to handle username/password for HTTP transaction used in
+ * The code to handle username/password for HTTP transactions used in
    "git push" & "git fetch" learned to talk "credential API" to
    external programs to cache or store them, to allow integration with
    platform native keychain mechanisms.
 
- * The prompted input in the terminal use our own getpass() replacement
-   when possible. HTTP transactions used to ask username without echoing
-   back what was typed, but with this change you will see it as you type.
+ * The input prompts in the terminal use our own getpass() replacement
+   when possible. HTTP transactions used to ask for the username without
+   echoing back what was typed, but with this change you will see it as
+   you type.
 
- * The internal of "revert/cherry-pick" has been tweaked to prepare
+ * The internals of "revert/cherry-pick" have been tweaked to prepare
    building more generic "sequencer" on top of the implementation that
    drives them.
 
-- 
1.7.9.rc2.293.gaae2

^ permalink raw reply related

* Re: git version not changed after installing new version
From: Carlos Martín Nieto @ 2012-01-25 22:29 UTC (permalink / raw)
  To: freefly; +Cc: git
In-Reply-To: <loom.20120125T211638-609@post.gmane.org>

[-- Attachment #1: Type: text/plain, Size: 695 bytes --]

On Wed, 2012-01-25 at 20:20 +0000, freefly wrote:
> > Please don't cull the CC list. It's customary in the git ML to send a
> > copy of the message to each participant.
> > 
> 
> > There you go then. That should get set in ~/.bashrc so edit that file to
> > change the order.
> > 
> >    cmn
> 
> I didn't the rules about ML and culling some of them 
> have guidelines to reduce the noise. 
> So you want me to edit the ~/.bashrc 
> and put change the order of those paths ?

With the places you've installed git in, that's what you need to do. You
need to tell your shell to look at /usr/local/bin before /usr/bin,
otherwise it won't use your locally-installed git.

   cmn

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 490 bytes --]

^ permalink raw reply

* Re: [PATCH 3/5] run-command: Elaborate execvp error checking
From: Frans Klaver @ 2012-01-25 22:48 UTC (permalink / raw)
  To: Jonathan Nieder; +Cc: git, Junio C. Hamano, Johannes Sixt
In-Reply-To: <20120125192222.GH1824@burratino>

On Wed, 25 Jan 2012 20:22:22 +0100, Jonathan Nieder <jrnieder@gmail.com>  
wrote:

> Frans Klaver wrote:
>> Jonathan Nieder wrote:
>
>>> Could you give an example?
>>
>> The case that triggered me to work on this. I had an incorrect entry
>> in my PATH and some aliasing tests failed. The generated command
>> output was something like
>>
>> fatal: script: Access Denied
>
> Sorry for the lack of clarity.  I meant that a (precise) "before and
> after" example could make the commit message a lot easier to
> understand.

Ah I see. I'll add something along those lines.


> [...]
>>> What happens on Windows?
>>
>> I haven't changed anything on the windows side, so that probably
>> sticks to the old behavior.
>
> This was mostly a comment on the change description --- unless I look
> at the patch, if I try this out on Windows after reading the changelog
> I would end up utterly confused.  For patch 5/5, it also brings up
> worries about consistency --- if systems are going to be relying on a
> missing #! interpreter being treated differently from a missing script
> for the sake of silent_exec_failure, do the same considerations apply
> on Windows, too?

I'm actually not sure if scripts would be relying on this. There is of  
course a good chance that people actually will rely on it, regardless of  
what we think. If there are consistency concerns on different platforms  
I'd probably have to work on that as well. Mentioning that windows isn't  
affected by these changes would be a start though.

> Perhaps it's more along the lines of "this is not supposed to happen
> in practice, and when it does, humans will find it easier to debug if
> we error out hard instead of falling back to the 'if the command does
> not exist' behavior (e.g., by trying an alias next)".  In other words,
> maybe this is intended as an optional nicety rather than something
> scripts would ever rely on.

Exactly. My concern was primarily the human interaction, so getting at  
least some pointer to the cause of the error. Would that be nice to have  
on windows as well? It probably would.

^ permalink raw reply

* Re: [PATCH 3/5] run-command: Elaborate execvp error checking
From: Frans Klaver @ 2012-01-25 22:59 UTC (permalink / raw)
  To: Johannes Sixt; +Cc: git, Junio C. Hamano, Jonathan Nieder
In-Reply-To: <4F205212.5080007@kdbg.org>

On Wed, 25 Jan 2012 20:03:46 +0100, Johannes Sixt <j6t@kdbg.org> wrote:

> Am 24.01.2012 23:32, schrieb Frans Klaver:
>> +static void inspect_failure(const char *argv0, int silent_exec_failure)
>> +{
>> +	int err = errno;
>> +	struct strbuf sb = STRBUF_INIT;
>> +
>> +	/* errors not related to path */
>> +	if (errno == E2BIG || errno == ENOMEM)
>> +		die_file_error(argv0, err);
>> +
>> +	if (strchr(argv0, '/')) {
>> +		if (file_exists(argv0)) {
>> +			strbuf_add(&sb, argv0, strlen(argv0));
>> +			inspect_file(&sb, err, argv0);
>
> Can we end up here if errno == ENOENT? If so, silent_exec_failure must
> be checked. (inspect_file does not return.)

Hm, good catch. Yes, we can if the interpreter isn't found. I never  
intended to actually leave the "interpreter not found" ENOENT case in it's  
current shape, so it probably slipped through. Will fix inspect_failure  
here to guarantee silent_exec_failure is heeded. Patch 5/5 would probably  
remove it again.

Thanks.

^ permalink raw reply

* Re: [PATCH 5/5] run-command: Error out if interpreter not found
From: Frans Klaver @ 2012-01-25 23:09 UTC (permalink / raw)
  To: Johannes Sixt; +Cc: Jonathan Nieder, git, Junio C. Hamano
In-Reply-To: <4F205028.4060606@kdbg.org>

On Wed, 25 Jan 2012 19:55:36 +0100, Johannes Sixt <j6t@kdbg.org> wrote:

>> I guess it could use similar code to this patch series to tackle
>> all this.
>
> No thanks. IMHO, this is already too much code for too little gain.

That's OK. If it's not only you who feels this way, I'd better spend my  
time on something that does add value.

Thanks for having a look in any case.

Frans

^ permalink raw reply

* [PATCH v3 0/3] git-p4: Search for parent commit on branch creation
From: Vitor Antunes @ 2012-01-25 23:48 UTC (permalink / raw)
  To: git; +Cc: Pete Wyckoff, Luke Diamand, Vitor Antunes

I think this will, hopefully, be the final version of this series of
patches. This version includes the following changes since v2:

 - Move search algorithm into its own function.
 - Use lists instead of strings on shell commands.
 - Some small (almost cosmetic) updates to test cases.

Pete Wyckoff (1):
  git-p4: Change p4 command invocation

Vitor Antunes (2):
  git-p4: Search for parent commit on branch creation
  git-p4: Add test case for complex branch import

 contrib/fast-import/git-p4 |   48 +++++++++++++++++++++-
 t/t9801-git-p4-branch.sh   |   94 ++++++++++++++++++++++++++++++++++++++++---
 2 files changed, 133 insertions(+), 9 deletions(-)

-- 
1.7.8.3

^ permalink raw reply

* [PATCH v3 3/3] git-p4: Change p4 command invocation
From: Vitor Antunes @ 2012-01-25 23:48 UTC (permalink / raw)
  To: git; +Cc: Pete Wyckoff, Luke Diamand, Vitor Antunes
In-Reply-To: <1327535304-11332-1-git-send-email-vitor.hda@gmail.com>

From: Pete Wyckoff <pw@padd.com>

Change p4 command invocation to avoid going through the shell. This
allows names with spaces and wildcards to work.

Signed-off-by: Pete Wyckoff <pw@padd.com>
Signed-off-by: Vitor Antunes <vitor.hda@gmail.com>
---
 contrib/fast-import/git-p4 |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4
index 584cc41..74d3613 100755
--- a/contrib/fast-import/git-p4
+++ b/contrib/fast-import/git-p4
@@ -1975,7 +1975,7 @@ class P4Sync(Command, P4UserMap):
     def importChanges(self, changes):
         cnt = 1
         for change in changes:
-            description = p4Cmd("describe %s" % change)
+            description = p4Cmd(["describe", str(change)])
             self.updateOptionDict(description)
 
             if not self.silent:
-- 
1.7.8.3

^ permalink raw reply related

* [PATCH v3 1/3] git-p4: Search for parent commit on branch creation
From: Vitor Antunes @ 2012-01-25 23:48 UTC (permalink / raw)
  To: git; +Cc: Pete Wyckoff, Luke Diamand, Vitor Antunes
In-Reply-To: <1327535304-11332-1-git-send-email-vitor.hda@gmail.com>

To find out which is its parent the commit of the new branch is compared
sequentially to each blob of the parent branch from the newest to the
oldest. The first blob which results in a zero diff is considered the
parent commit. If none is found, then the commit is applied to the top
of the parent branch.

A fast-import "checkpoint" call is required because diff-tree is only
able to work with blobs on disk. But most of these commits will not be
part of the final imported tree, making fast-import fail. To avoid this,
the temporary branches are tracked and then removed at the end of the
import process.

Signed-off-by: Vitor Antunes <vitor.hda@gmail.com>
---
 contrib/fast-import/git-p4 |   46 +++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 45 insertions(+), 1 deletions(-)

diff --git a/contrib/fast-import/git-p4 b/contrib/fast-import/git-p4
index 3e1aa27..584cc41 100755
--- a/contrib/fast-import/git-p4
+++ b/contrib/fast-import/git-p4
@@ -1429,6 +1429,8 @@ class P4Sync(Command, P4UserMap):
         self.cloneExclude = []
         self.useClientSpec = False
         self.clientSpecDirs = None
+        self.tempBranches = []
+        self.tempBranchLocation = "git-p4-tmp"
 
         if gitConfig("git-p4.syncFromOrigin") == "false":
             self.syncWithOrigin = False
@@ -1450,6 +1452,14 @@ class P4Sync(Command, P4UserMap):
                    .replace("%25", "%")
         return path
 
+    # Force a checkpoint in fast-import and wait for it to finish
+    def checkpoint(self):
+        self.gitStream.write("checkpoint\n\n")
+        self.gitStream.write("progress checkpoint\n\n")
+        out = self.gitOutput.readline()
+        if self.verbose:
+            print "checkpoint finished: " + out
+
     def extractFilesFromCommit(self, commit):
         self.cloneExclude = [re.sub(r"\.\.\.$", "", path)
                              for path in self.cloneExclude]
@@ -1948,6 +1958,20 @@ class P4Sync(Command, P4UserMap):
         self.importChanges(changes)
         return True
 
+    def searchParent(self, parent, branch, target):
+        parentFound = False
+        for blob in read_pipe_lines(["git", "rev-list", "--reverse", "--no-merges", parent]):
+            blob = blob.strip()
+            if len(read_pipe(["git", "diff-tree", blob, target])) == 0:
+                parentFound = True
+                if self.verbose:
+                    print "Found parent of %s in commit %s" % (branch, blob)
+                break
+        if parentFound:
+            return blob
+        else:
+            return None
+
     def importChanges(self, changes):
         cnt = 1
         for change in changes:
@@ -2004,7 +2028,21 @@ class P4Sync(Command, P4UserMap):
                             parent = self.initialParents[branch]
                             del self.initialParents[branch]
 
-                        self.commit(description, filesForCommit, branch, [branchPrefix], parent)
+                        blob = None
+                        if len(parent) > 0:
+                            tempBranch = os.path.join(self.tempBranchLocation, "%d" % (change))
+                            if self.verbose:
+                                print "Creating temporary branch: " + tempBranch
+                            self.commit(description, filesForCommit, tempBranch, [branchPrefix])
+                            self.tempBranches.append(tempBranch)
+                            self.checkpoint()
+                            blob = self.searchParent(parent, branch, tempBranch)
+                        if blob:
+                            self.commit(description, filesForCommit, branch, [branchPrefix], blob)
+                        else:
+                            if self.verbose:
+                                print "Parent of %s not found. Committing into head of %s" % (branch, parent)
+                            self.commit(description, filesForCommit, branch, [branchPrefix], parent)
                 else:
                     files = self.extractFilesFromCommit(description)
                     self.commit(description, files, self.branch, self.depotPaths,
@@ -2339,6 +2377,12 @@ class P4Sync(Command, P4UserMap):
         self.gitOutput.close()
         self.gitError.close()
 
+        # Cleanup temporary branches created during import
+        if self.tempBranches != []:
+            for branch in self.tempBranches:
+                read_pipe("git update-ref -d %s" % branch)
+            os.rmdir(os.path.join(os.environ.get("GIT_DIR", ".git"), self.tempBranchLocation))
+
         return True
 
 class P4Rebase(Command):
-- 
1.7.8.3

^ permalink raw reply related

* [PATCH v3 2/3] git-p4: Add test case for complex branch import
From: Vitor Antunes @ 2012-01-25 23:48 UTC (permalink / raw)
  To: git; +Cc: Pete Wyckoff, Luke Diamand, Vitor Antunes
In-Reply-To: <1327535304-11332-1-git-send-email-vitor.hda@gmail.com>

Check if branches created from old changelists are correctly imported.
Also included some updates to simple branch test so that both are
coherent in respect to each other.

Signed-off-by: Vitor Antunes <vitor.hda@gmail.com>
---
 t/t9801-git-p4-branch.sh |   94 ++++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 87 insertions(+), 7 deletions(-)

diff --git a/t/t9801-git-p4-branch.sh b/t/t9801-git-p4-branch.sh
index a25f18d..6ff713b 100755
--- a/t/t9801-git-p4-branch.sh
+++ b/t/t9801-git-p4-branch.sh
@@ -172,9 +172,9 @@ test_expect_success 'add simple p4 branches' '
 		echo file1 >file1 &&
 		echo file2 >file2 &&
 		p4 add file1 file2 &&
-		p4 submit -d "branch1" &&
+		p4 submit -d "Create branch1" &&
 		p4 integrate //depot/branch1/... //depot/branch2/... &&
-		p4 submit -d "branch2" &&
+		p4 submit -d "Integrate branch2 from branch1" &&
 		echo file3 >file3 &&
 		p4 add file3 &&
 		p4 submit -d "add file3 in branch1" &&
@@ -182,7 +182,7 @@ test_expect_success 'add simple p4 branches' '
 		echo update >>file2 &&
 		p4 submit -d "update file2 in branch1" &&
 		p4 integrate //depot/branch1/... //depot/branch3/... &&
-		p4 submit -d "branch3"
+		p4 submit -d "Integrate branch3 from branch1"
 	)
 '
 
@@ -203,17 +203,17 @@ test_expect_success 'git-p4 clone simple branches' '
 		test -f file1 &&
 		test -f file2 &&
 		test -f file3 &&
-		grep -q update file2 &&
+		grep update file2 &&
 		git reset --hard p4/depot/branch2 &&
 		test -f file1 &&
 		test -f file2 &&
 		test ! -f file3 &&
-		test_must_fail grep -q update file2 &&
+		test_must_fail grep update file2 &&
 		git reset --hard p4/depot/branch3 &&
 		test -f file1 &&
 		test -f file2 &&
 		test -f file3 &&
-		grep -q update file2 &&
+		grep update file2 &&
 		cd "$cli" &&
 		cd branch1 &&
 		p4 edit file2 &&
@@ -222,7 +222,87 @@ test_expect_success 'git-p4 clone simple branches' '
 		cd "$git" &&
 		git reset --hard p4/depot/branch1 &&
 		"$GITP4" rebase &&
-		grep -q file2_ file2
+		grep file2_ file2
+	)
+'
+
+# Create a complex branch structure in P4 depot to check if they are correctly
+# cloned. The branches are created from older changelists to check if git-p4 is
+# able to correctly detect them.
+# The final expected structure is:
+# `branch1
+# | `- file1
+# | `- file2 (updated)
+# | `- file3
+# `branch2
+# | `- file1
+# | `- file2
+# `branch3
+# | `- file1
+# | `- file2 (updated)
+# | `- file3
+# `branch4
+# | `- file1
+# | `- file2
+# `branch5
+#   `- file1
+#   `- file2
+#   `- file3
+test_expect_success 'git-p4 add complex branches' '
+	test_when_finished cleanup_git &&
+	test_create_repo "$git" &&
+	(
+		cd "$cli" &&
+		changelist=$(p4 changes -m1 //depot/... | cut -d" " -f2) &&
+		changelist=$(($changelist - 5)) &&
+		p4 integrate //depot/branch1/...@$changelist //depot/branch4/... &&
+		p4 submit -d "Integrate branch4 from branch1@${changelist}" &&
+		changelist=$(($changelist + 2)) &&
+		p4 integrate //depot/branch1/...@$changelist //depot/branch5/... &&
+		p4 submit -d "Integrate branch5 from branch1@${changelist}"
+	)
+'
+
+# Configure branches through git-config and clone them. git-p4 will only be able
+# to clone the original structure if it is able to detect the origin changelist
+# of each branch.
+test_expect_success 'git-p4 clone complex branches' '
+	test_when_finished cleanup_git &&
+	test_create_repo "$git" &&
+	(
+		cd "$git" &&
+		git config git-p4.branchList branch1:branch2 &&
+		git config --add git-p4.branchList branch1:branch3 &&
+		git config --add git-p4.branchList branch1:branch4 &&
+		git config --add git-p4.branchList branch1:branch5 &&
+		"$GITP4" clone --dest=. --detect-branches //depot@all &&
+		git log --all --graph --decorate --stat &&
+		git reset --hard p4/depot/branch1 &&
+		test_path_is_file file1 &&
+		test_path_is_file file2 &&
+		test_path_is_file file3 &&
+		grep update file2 &&
+		git reset --hard p4/depot/branch2 &&
+		test_path_is_file file1 &&
+		test_path_is_file file2 &&
+		test_path_is_missing file3 &&
+		test_must_fail grep update file2 &&
+		git reset --hard p4/depot/branch3 &&
+		test_path_is_file file1 &&
+		test_path_is_file file2 &&
+		test_path_is_file file3 &&
+		grep update file2 &&
+		git reset --hard p4/depot/branch4 &&
+		test_path_is_file file1 &&
+		test_path_is_file file2 &&
+		test_path_is_missing file3 &&
+		test_must_fail grep update file2 &&
+		git reset --hard p4/depot/branch5 &&
+		test_path_is_file file1 &&
+		test_path_is_file file2 &&
+		test_path_is_file file3 &&
+		test_must_fail grep update file2 &&
+		test_path_is_missing .git/git-p4-tmp
 	)
 '
 
-- 
1.7.8.3

^ permalink raw reply related

* Re: Question about commit message wrapping
From: Sidney San Martín @ 2012-01-26  1:50 UTC (permalink / raw)
  To: Drew Northup
  Cc: Michael Haggerty, Frans Klaver, Holger Hellmuth, Andrew Ardill,
	JakubNarebski, git@vger.kernel.org
In-Reply-To: <1325433812.4752.88.camel@drew-northup.unet.maine.edu>

Hey Drew. Sorry about the lag; I really appreciate your (and the other guys on the list) taking the time to write back. You made some interesting points in your last email and I want to respond to them.

- - -

It may come down to personal preference and how we are each used to editing text.

All the programs I use on a daily basis use soft line wrapping (not encoding any of the line breaks I see on screen into what I’m typing). Most of them use proportional type too. So, I guess I don’t *expect* to be able to manage how text wraps. Neither my email client nor the editor I use to write commit messages are set up for hard wrapping.

I posed the question to the list because having to switch into “I have to hit return every so often” mode (or play with my editor) to write commit message screws with my head, and lately I just stopped doing it in my own projects. I was wondering if anyone else was thinking along the same lines and would prefer to write their commits without line breaks (except to break paragraphs, lists, etc.).

On Jan 1, 2012, at 8:03 AM, Drew Northup wrote:

> FWIW, I'm leaving text in this email as my mail client found it (and not
> reflowing as I usually do). You can clearly see the effect of one mail
> client assuming that the end display is doing all of the wrapping (I'll
> not name names). When I first read the mail it looked fine because my
> mail client IGNORED the inconsistencies in line wrap modes.

That's interesting — it looks like my main mail client, Apple Mail, uses tricks (which I think we've discovered are mostly powered by quoted-printable encoding) to get around the old SMTP line length limits. (Is there where the differences in behavior between mail clients come from? I don't know much about the history.)

As a result, I’m not really sure what you mean. What effects and inconsistencies are you seeing? My phone, my computer, and my webmail (Google) all show pretty much the same thing: the lines from your and Michael’s emails are wrapped at ~72 characters, and the lines from my email are wrapped to the width of the window. But, they all look OK.

The only side effect is that on my phone, your/Michael’s text breaks about half way through every other line (since it's wrapped to a wider width than fits on the screen).

I don’t think I have ever manually reflowed text like you mention. When do you do it, and why?

(It may be that the thing I’m proposing wouldn’t be appropriate for git itself and other repos that use email to exchange patches. I use remotes for the repos I use on a daily basis, so I don’t have to deal with email clients like you guys do.)

> In virtually all modern tools the default font is the "system default"
> font, which is typically variable width. In some places I've even seen
> variable pitch font rendering (I know there's a more technical term for
> it, but I'm not taking the time to look it up right now) used, which is
> distinct in that it makes the text easier to read when there are
> potentially overlapping descenders and ascenders on adjoining lines
> while leaving text without that feature unchanged in line spacing and
> kerning. Try rendering ASCII-ART with that enabled!
> However, it is a rare GUI tool that does not allow the user to change
> the font to something more appropriate (I use fixed-width fonts for most
> programming and scripting, but they are not any more helpful for reading
> log messages for instance).

That’s not really the motivation behind my proposal, but I checked and actually none of the GUIs I tested before have options to change to a fixed-width font for commit messages.

It’s not really the point, though. Proportional type is nice! Have you ever seen Docco? It’s a tool that takes a well-commented source file like <http://documentcloud.github.com/backbone/backbone.js> and creates a beautiful two-column view like <http://documentcloud.github.com/backbone/docs/backbone.html> with the comments on one side in a nice (for text) proportional font and the code on the other in a nice (for code) monospaced one. The text and the code both each look great. I want the guys who develop the next generation of git clients to have the same freedom to make commit messages look great.

ASCII art in text has been a casualty of the rise of proportional type… but there are ways to save it (GitHub’s code blocks are an example); teaching everyone (and forcing the tools) to format text the old way is, I believe, the wrong approach.

> Text-based programming tools usually just
> use the console font, whatever it is--and woe be to the programmer who
> switches their "console" font to something variable width. (Doing so
> makes any application written with curses/ncurses in mind look very very
> odd as well.)

What about manpages? They use the console font but lines get wrapped to the width of the terminal (and I want this feature of git to do that, too). They’re *not* preformatted in terms of width.

>> - don’t insert line breaks when you write a commit message (and don't provide a way to do so automatically),
> 
> Most of the "tools" I have seen that ignore all user-entered line breaks
> are actually poorly written applications attempting to protect some sort
> of backing database from an injection attack. Given that, many WIKI
> systems typically ignore single line breaks when rendering (double line
> breaks are taken to be paragraph breaks in those cases I am aware of),
> so any argument about that quickly becomes moot as well. If somebody is
> writing a tool that does not allow me to force multiple line breaks when
> desired then so far as I am concerned their tool is broken. I don't see
> a point in changing GIT as a whole because somebody writes a broken GUI
> implementation.

Misunderstanding — the tools I tested don’t insert don’t insert line breaks for you to help you wrap your commit messages to a certain width. They keep user-entered line breaks (but since they use proportional type and lack column counters, there’s no way to wrap to 72 columns, even by hand, except by copying and pasting from another editor… or counting).

> 
>> - do wrap commit messages when showing them.
>> 
>> Jakub, you said that education was the answer to getting some consistency in line wrapping, but I have trouble imagining the makers of new tools using fixed-width text for anything other than code.
> 
> Remember, as soon as you think you've idiot-proofed something somebody
> builds a better idiot. That's why Jakub (and many others of us) would
> prefer just to tell people about the way things are intended to work and
> then get out of the way and let people make their own mistakes.

See above, this isn’t idiot-proofing. New tools use proportional fonts because they’re more readable, and soft wrapping because it makes sense in the context that they create and read commit messages.

>>> And given that commit messages sometimes
>>> contain "flowable" paragraph text, sometimes code snippets, sometimes
>>> ASCII art, etc, no automatic wrapping will work correctly unless
>>> everybody agrees that commit messages must be written in some specific
>>> form of markup (or lightweight markup).  And I can't imagine such a
>>> thing ever happening.
>> 
>> The two biggest websites I know of for talking about code, GitHub and Stack Overflow, both adopted flavors of Markdown. It is basically the formatting syntax already used for commit messages in the Git project itself (this email too), so can be formatted to look good in a specific environment (i.e. proportional fonts) and looks good by itself.
>> 
>> (Actually, as far as I can tell commit messages are the only place GitHub doesn’t currently render user-entered text as Markdown.)
>> 
>> I think, now and in the future, consistency will be found most easily in in Markdown-like formatting and least in 80 columns of fixed-width text.
> 
> Given that there is little consensus even between Markdown-like
> formatting methods (which have in some cases been around since the
> advent of movable type presses, so far as I am aware) I have to agree
> with Michael here.

I think that the syntax laid out at <http://daringfireball.net/projects/markdown/syntax> is pretty consistently-used. Any differences that you think would affect this case? I think only a small subset would be relevant (paragraph breaks, ordered and unordered lists, and indented code blocks) and every implementation I’ve seen handles those the same way.

I think that supporting this small subset, and only for users who turn it on, would work. It matches how many commits are already formatted, there’s nothing new to learn.

P.S. Happy belated New Year!

^ permalink raw reply

* Re: [PATCH v3 0/3] git-p4: Search for parent commit on branch creation
From: Pete Wyckoff @ 2012-01-26  4:21 UTC (permalink / raw)
  To: Vitor Antunes; +Cc: git, Luke Diamand
In-Reply-To: <1327535304-11332-1-git-send-email-vitor.hda@gmail.com>

vitor.hda@gmail.com wrote on Wed, 25 Jan 2012 23:48 +0000:
> I think this will, hopefully, be the final version of this series of
> patches. This version includes the following changes since v2:
> 
>  - Move search algorithm into its own function.
>  - Use lists instead of strings on shell commands.
>  - Some small (almost cosmetic) updates to test cases.

Whole series

Acked-by: Pete Wyckoff <pw@padd.com>

Thanks for making all the changes.

> Pete Wyckoff (1):
>   git-p4: Change p4 command invocation
> 
> Vitor Antunes (2):
>   git-p4: Search for parent commit on branch creation
>   git-p4: Add test case for complex branch import
> 
>  contrib/fast-import/git-p4 |   48 +++++++++++++++++++++-
>  t/t9801-git-p4-branch.sh   |   94 ++++++++++++++++++++++++++++++++++++++++---
>  2 files changed, 133 insertions(+), 9 deletions(-)
> 
> -- 
> 1.7.8.3
> 

^ permalink raw reply

* [RFC/PATCH 0/4] config include directives
From: Jeff King @ 2012-01-26  7:35 UTC (permalink / raw)
  To: git

This series provides a way for config files to include other config
files in two ways:

  1. From other files in the filesystem. This is implemented by patch 1
     below, and is hopefully straightforward and uncontroversial.  See
     that patch for more rationale.

  2. From blobs in the repo. This is implemented by patch 4, with
     patches 2 and 3 providing the necessary refactoring. This
     is one way of implementing the often asked-for "respect shared
     config inside the repo" feature, but attempts to mitigate some of
     the security concerns. The interface for using it safely is a bit
     raw, but I think it's a sane building block, and somebody could
     write a fancier shared-config updater on top of it if they wanted
     to.

  [1/4]: config: add include directive
  [2/4]: config: factor out config file stack management
  [3/4]: config: support parsing config data from buffers
  [4/4]: config: allow including config from repository blobs

-Peff

^ permalink raw reply

* [PATCH 1/4] config: add include directive
From: Jeff King @ 2012-01-26  7:37 UTC (permalink / raw)
  To: git
In-Reply-To: <20120126073547.GA28689@sigill.intra.peff.net>

It can be useful to split your ~/.gitconfig across multiple
files. For example, you might have a "main" file which is
used on many machines, but a small set of per-machine
tweaks. Or you may want to make some of your config public
(e.g., clever aliases) while keeping other data back (e.g.,
your name or other identifying information). Or you may want
to include a number of config options in some subset of your
repos without copying and pasting (e.g., you want to
reference them from the .git/config of participating repos).

This patch introduces an include directive for config files.
It looks like:

  [include]
    path = /path/to/file

This is syntactically backwards-compatible with existing git
config parsers (i.e., they will see it as another config
entry and ignore it unless you are looking up include.path).

The implementation provides a "git_config_include" callback
which wraps regular config callbacks.  Callers can pass it
to git_config_from_file, and it will transparently follow
any include directives, passing all of the discovered
options to the real callback.

Include directives are turned on for regular git config
parsing (i.e., when you call git_config()), as well as for
lookups via the "git config" program. They are not turned on
in other cases, including:

  1. Parsing of other config-like files, like .gitmodules.
     There isn't a real need, and I'd rather be conservative
     and avoid unnecessary incompatibility or confusion.

  2. Writing files via "git config"; we want to treat
     include.* variables as literal items to be copied (or
     modified), and not expand them. So "git config
     --unset-all foo.bar" would operate _only_ on
     .git/config, not any of its included files (just as it
     also does not operate on ~/.gitconfig).

Signed-off-by: Jeff King <peff@peff.net>
---
 Documentation/config.txt     |   15 ++++++
 Documentation/git-config.txt |    5 ++
 builtin/config.c             |   29 +++++++++---
 cache.h                      |    6 +++
 config.c                     |   58 +++++++++++++++++++++++++
 t/t1305-config-include.sh    |   98 ++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 204 insertions(+), 7 deletions(-)
 create mode 100755 t/t1305-config-include.sh

diff --git a/Documentation/config.txt b/Documentation/config.txt
index abeb82b..e55dae1 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -84,6 +84,17 @@ customary UNIX fashion.
 
 Some variables may require a special value format.
 
+Includes
+~~~~~~~~
+
+You can include one config file from another by setting the special
+`include.path` variable to the name of the file to be included. The
+included file is expanded immediately, as if its contents had been
+found at the location of the include directive. If the value of the
+`include.path` variable is a relative path, the path is considered to be
+relative to the configuration file in which the include directive was
+found. See below for examples.
+
 Example
 ~~~~~~~
 
@@ -106,6 +117,10 @@ Example
 		gitProxy="ssh" for "kernel.org"
 		gitProxy=default-proxy ; for the rest
 
+	[include]
+		path = /path/to/foo.inc ; include by absolute path
+		path = foo ; expand "foo" relative to the current file
+
 Variables
 ~~~~~~~~~
 
diff --git a/Documentation/git-config.txt b/Documentation/git-config.txt
index e7ecf5d..aa8303b 100644
--- a/Documentation/git-config.txt
+++ b/Documentation/git-config.txt
@@ -178,6 +178,11 @@ See also <<FILES>>.
 	Opens an editor to modify the specified config file; either
 	'--system', '--global', or repository (default).
 
+--includes::
+--no-includes::
+	Respect `include.*` directives in config files when looking up
+	values. Defaults to on.
+
 [[FILES]]
 FILES
 -----
diff --git a/builtin/config.c b/builtin/config.c
index d35c06a..9105f87 100644
--- a/builtin/config.c
+++ b/builtin/config.c
@@ -25,6 +25,7 @@ static const char *given_config_file;
 static int actions, types;
 static const char *get_color_slot, *get_colorbool_slot;
 static int end_null;
+static int respect_includes = 1;
 
 #define ACTION_GET (1<<0)
 #define ACTION_GET_ALL (1<<1)
@@ -74,6 +75,8 @@ static struct option builtin_config_options[] = {
 	OPT_BIT(0, "path", &types, "value is a path (file or directory name)", TYPE_PATH),
 	OPT_GROUP("Other"),
 	OPT_BOOLEAN('z', "null", &end_null, "terminate values with NUL byte"),
+	OPT_BOOLEAN(0, "includes", &respect_includes,
+		    "respect include directives on lookup"),
 	OPT_END(),
 };
 
@@ -161,6 +164,9 @@ static int get_value(const char *key_, const char *regex_)
 	int ret = -1;
 	char *global = NULL, *repo_config = NULL;
 	const char *system_wide = NULL, *local;
+	struct git_config_include_data inc;
+	config_fn_t fn;
+	void *data;
 
 	local = config_exclusive_filename;
 	if (!local) {
@@ -213,19 +219,28 @@ static int get_value(const char *key_, const char *regex_)
 		}
 	}
 
+	fn = show_config;
+	data = NULL;
+	if (respect_includes) {
+		inc.fn = fn;
+		inc.data = data;
+		fn = git_config_include;
+		data = &inc;
+	}
+
 	if (do_all && system_wide)
-		git_config_from_file(show_config, system_wide, NULL);
+		git_config_from_file(fn, system_wide, data);
 	if (do_all && global)
-		git_config_from_file(show_config, global, NULL);
+		git_config_from_file(fn, global, data);
 	if (do_all)
-		git_config_from_file(show_config, local, NULL);
-	git_config_from_parameters(show_config, NULL);
+		git_config_from_file(fn, local, data);
+	git_config_from_parameters(fn, data);
 	if (!do_all && !seen)
-		git_config_from_file(show_config, local, NULL);
+		git_config_from_file(fn, local, data);
 	if (!do_all && !seen && global)
-		git_config_from_file(show_config, global, NULL);
+		git_config_from_file(fn, global, data);
 	if (!do_all && !seen && system_wide)
-		git_config_from_file(show_config, system_wide, NULL);
+		git_config_from_file(fn, system_wide, data);
 
 	free(key);
 	if (regexp) {
diff --git a/cache.h b/cache.h
index 10afd71..21bbb0a 100644
--- a/cache.h
+++ b/cache.h
@@ -1138,6 +1138,12 @@ extern const char *get_commit_output_encoding(void);
 
 extern int git_config_parse_parameter(const char *, config_fn_t fn, void *data);
 
+struct git_config_include_data {
+	config_fn_t fn;
+	void *data;
+};
+int git_config_include(const char *name, const char *value, void *vdata);
+
 extern const char *config_exclusive_filename;
 
 #define MAX_GITNAME (1000)
diff --git a/config.c b/config.c
index 40f9c6d..a6966c1 100644
--- a/config.c
+++ b/config.c
@@ -874,10 +874,68 @@ int git_config_system(void)
 	return !git_env_bool("GIT_CONFIG_NOSYSTEM", 0);
 }
 
+static int handle_path_include(const char *path, void *data)
+{
+	int ret = 0;
+	struct strbuf buf = STRBUF_INIT;
+
+	/*
+	 * Use an absolute value as-is, but interpret relative paths
+	 * based on the including config file.
+	 */
+	if (!is_absolute_path(path)) {
+		char *slash;
+		if (!cf)
+			return error("relative config includes must come from files");
+		strbuf_addstr(&buf, absolute_path(cf->name));
+		slash = find_last_dir_sep(buf.buf);
+		if (!slash)
+			die("BUG: no directory separator in an absolute path?");
+		strbuf_setlen(&buf, slash - buf.buf + 1);
+		strbuf_addf(&buf, "%s", path);
+		path = buf.buf;
+	}
+
+	if (!access(path, R_OK))
+		ret = git_config_from_file(git_config_include, path, data);
+	strbuf_release(&buf);
+	return ret;
+}
+
+int git_config_include(const char *name, const char *value, void *vdata)
+{
+	const struct git_config_include_data *data = vdata;
+	const char *type;
+	int ret;
+
+	/*
+	 * Pass along all values, including "include" directives; this makes it
+	 * possible to query information on the includes themselves.
+	 */
+	ret = data->fn(name, value, data->data);
+	if (ret < 0)
+		return ret;
+
+	if (prefixcmp(name, "include."))
+		return ret;
+	type = strrchr(name, '.') + 1;
+
+	if (!strcmp(type, "path"))
+		ret = handle_path_include(value, vdata);
+
+	return ret;
+}
+
 int git_config_early(config_fn_t fn, void *data, const char *repo_config)
 {
 	int ret = 0, found = 0;
 	const char *home = NULL;
+	struct git_config_include_data inc;
+
+	inc.fn = fn;
+	inc.data = data;
+	fn = git_config_include;
+	data = &inc;
 
 	/* Setting $GIT_CONFIG makes git read _only_ the given config file. */
 	if (config_exclusive_filename)
diff --git a/t/t1305-config-include.sh b/t/t1305-config-include.sh
new file mode 100755
index 0000000..4db3091
--- /dev/null
+++ b/t/t1305-config-include.sh
@@ -0,0 +1,98 @@
+#!/bin/sh
+
+test_description='test config file include directives'
+. ./test-lib.sh
+
+test_expect_success 'include file by absolute path' '
+	echo "[test]one = 1" >one &&
+	echo "[include]path = \"$PWD/one\"" >base &&
+	echo 1 >expect &&
+	git config -f base test.one >actual &&
+	test_cmp expect actual
+'
+
+test_expect_success 'include file by relative path' '
+	echo "[test]one = 1" >one &&
+	echo "[include]path = one" >base &&
+	echo 1 >expect &&
+	git config -f base test.one >actual &&
+	test_cmp expect actual
+'
+
+test_expect_success 'recursive relative paths' '
+	mkdir subdir &&
+	echo "[test]three = 3" >subdir/three &&
+	echo "[include]path = three" >subdir/two &&
+	echo "[include]path = subdir/two" >base &&
+	echo 3 >expect &&
+	git config -f base test.three >actual &&
+	test_cmp expect actual
+'
+
+test_expect_success 'include options can still be examined' '
+	echo "[test]one = 1" >one &&
+	echo "[include]path = one" >base &&
+	echo one >expect &&
+	git config -f base include.path >actual &&
+	test_cmp expect actual
+'
+
+test_expect_success 'listing includes option and expansion' '
+	echo "[test]one = 1" >one &&
+	echo "[include]path = one" >base &&
+	cat >expect <<-\EOF &&
+	include.path=one
+	test.one=1
+	EOF
+	git config -f base --list >actual &&
+	test_cmp expect actual
+'
+
+test_expect_success 'writing config file does not expand includes' '
+	echo "[test]one = 1" >one &&
+	echo "[include]path = one" >base &&
+	git config -f base test.two 2 &&
+	echo 2 >expect &&
+	git config -f base --no-includes test.two >actual &&
+	test_cmp expect actual &&
+	test_must_fail git config -f base --no-includes test.one
+'
+
+test_expect_success 'config modification does not affect includes' '
+	echo "[test]one = 1" >one &&
+	echo "[include]path = one" >base &&
+	git config -f base test.one 2 &&
+	echo 1 >expect &&
+	git config -f one test.one >actual &&
+	test_cmp expect actual &&
+	cat >expect <<-\EOF &&
+	1
+	2
+	EOF
+	git config -f base --get-all test.one >actual &&
+	test_cmp expect actual
+'
+
+test_expect_success 'missing include files are ignored' '
+	cat >base <<-\EOF &&
+	[include]path = foo
+	[test]value = yes
+	EOF
+	echo yes >expect &&
+	git config -f base test.value >actual &&
+	test_cmp expect actual
+'
+
+test_expect_success 'absolute includes from command line work' '
+	echo "[test]one = 1" >one &&
+	echo 1 >expect &&
+	git -c include.path="$PWD/one" config test.one >actual &&
+	test_cmp expect actual
+'
+
+test_expect_success 'relative includes from command line fail' '
+	echo "[test]one = 1" >one &&
+	test_must_fail git -c include.path=one config test.one
+'
+
+test_done
-- 
1.7.9.rc2.293.gaae2

^ permalink raw reply related

* [PATCH 2/4] config: factor out config file stack management
From: Jeff King @ 2012-01-26  7:38 UTC (permalink / raw)
  To: git
In-Reply-To: <20120126073547.GA28689@sigill.intra.peff.net>

Because a config callback may start parsing a new file, the
global context regarding the current config file is stored
as a stack. Currently we only need to manage that stack from
git_config_from_file. Let's factor it out to allow new
sources of config data.

Signed-off-by: Jeff King <peff@peff.net>
---
 config.c |   30 +++++++++++++++++++-----------
 1 files changed, 19 insertions(+), 11 deletions(-)

diff --git a/config.c b/config.c
index a6966c1..b82f749 100644
--- a/config.c
+++ b/config.c
@@ -826,6 +826,23 @@ int git_default_config(const char *var, const char *value, void *dummy)
 	return 0;
 }
 
+static void config_file_push(config_file *top, const char *name)
+{
+	top->prev = cf;
+	top->f = NULL;
+	top->name = name;
+	top->linenr = 1;
+	top->eof = 0;
+	strbuf_init(&top->value, 1024);
+	cf = top;
+}
+
+static void config_file_pop(config_file *top)
+{
+	strbuf_release(&top->value);
+	cf = top->prev;
+}
+
 int git_config_from_file(config_fn_t fn, const char *filename, void *data)
 {
 	int ret;
@@ -835,21 +852,12 @@ int git_config_from_file(config_fn_t fn, const char *filename, void *data)
 	if (f) {
 		config_file top;
 
-		/* push config-file parsing state stack */
-		top.prev = cf;
+		config_file_push(&top, filename);
 		top.f = f;
-		top.name = filename;
-		top.linenr = 1;
-		top.eof = 0;
-		strbuf_init(&top.value, 1024);
-		cf = &top;
 
 		ret = git_parse_file(fn, data);
 
-		/* pop config-file parsing state stack */
-		strbuf_release(&top.value);
-		cf = top.prev;
-
+		config_file_pop(&top);
 		fclose(f);
 	}
 	return ret;
-- 
1.7.9.rc2.293.gaae2

^ permalink raw reply related

* [PATCH 3/4] config: support parsing config data from buffers
From: Jeff King @ 2012-01-26  7:40 UTC (permalink / raw)
  To: git
In-Reply-To: <20120126073547.GA28689@sigill.intra.peff.net>

The only two ways to parse config data are from a file or
from the command-line. Because the command-line format is
totally different from the file format, they don't share any
code. Therefore, to add new sources of file-like config data,
we have to refactor git_parse_file to handle reading from
something besides stdio.

To fix this, our config_file structure now holds either a
"FILE *" pointer or a memory buffer. We intercept calls to
fgetc and ungetc and either pass them along to stdio, or
fake them with our buffer. This leaves the main parsing code
intact and easy to read.

Signed-off-by: Jeff King <peff@peff.net>
---
 cache.h  |    1 +
 config.c |   58 +++++++++++++++++++++++++++++++++++++++++++++++++++++-----
 2 files changed, 54 insertions(+), 5 deletions(-)

diff --git a/cache.h b/cache.h
index 21bbb0a..a298897 100644
--- a/cache.h
+++ b/cache.h
@@ -1110,6 +1110,7 @@ extern int update_server_info(int);
 typedef int (*config_fn_t)(const char *, const char *, void *);
 extern int git_default_config(const char *, const char *, void *);
 extern int git_config_from_file(config_fn_t fn, const char *, void *);
+extern int git_config_from_buffer(config_fn_t fn, void *, const char *, char *, unsigned long );
 extern void git_config_push_parameter(const char *text);
 extern int git_config_from_parameters(config_fn_t fn, void *data);
 extern int git_config(config_fn_t fn, void *);
diff --git a/config.c b/config.c
index b82f749..49a3d1a 100644
--- a/config.c
+++ b/config.c
@@ -18,6 +18,9 @@ typedef struct config_file {
 	const char *name;
 	int linenr;
 	int eof;
+	char *buf;
+	unsigned long size;
+	unsigned long cur;
 	struct strbuf value;
 	char var[MAXNAME];
 } config_file;
@@ -101,19 +104,45 @@ int git_config_from_parameters(config_fn_t fn, void *data)
 	return nr > 0;
 }
 
+static int get_one_char(void)
+{
+	if (cf->f)
+		return fgetc(cf->f);
+	else if (cf->buf) {
+		if (cf->cur < cf->size)
+			return cf->buf[cf->cur++];
+		return EOF;
+	}
+
+	die("BUG: attempt to read from NULL config_file");
+}
+
+static int unget_one_char(int c)
+{
+	if (cf->f)
+		ungetc(c, cf->f);
+	else if (cf->buf) {
+		if (cf->cur == 0)
+			return EOF;
+		cf->buf[--cf->cur] = c;
+		return c;
+	}
+
+	die("BUG: attempt to ungetc NULL config_file");
+}
+
 static int get_next_char(void)
 {
 	int c;
-	FILE *f;
 
 	c = '\n';
-	if (cf && ((f = cf->f) != NULL)) {
-		c = fgetc(f);
+	if (cf && (cf->f || cf->buf)) {
+		c = get_one_char();
 		if (c == '\r') {
 			/* DOS like systems */
-			c = fgetc(f);
+			c = get_one_char();
 			if (c != '\n') {
-				ungetc(c, f);
+				unget_one_char(c);
 				c = '\r';
 			}
 		}
@@ -833,6 +862,9 @@ static void config_file_push(config_file *top, const char *name)
 	top->name = name;
 	top->linenr = 1;
 	top->eof = 0;
+	top->buf = NULL;
+	top->size = 0;
+	top->cur = 0;
 	strbuf_init(&top->value, 1024);
 	cf = top;
 }
@@ -863,6 +895,22 @@ int git_config_from_file(config_fn_t fn, const char *filename, void *data)
 	return ret;
 }
 
+int git_config_from_buffer(config_fn_t fn, void *data, const char *name,
+			   char *buf, unsigned long size)
+{
+	int ret;
+	config_file top;
+
+	config_file_push(&top, name);
+	top.buf = buf;
+	top.size = size;
+
+	ret = git_parse_file(fn, data);
+
+	config_file_pop(&top);
+	return ret;
+}
+
 const char *git_etc_gitconfig(void)
 {
 	static const char *system_wide;
-- 
1.7.9.rc2.293.gaae2

^ permalink raw reply related

* [PATCH 4/4] config: allow including config from repository blobs
From: Jeff King @ 2012-01-26  7:42 UTC (permalink / raw)
  To: git
In-Reply-To: <20120126073547.GA28689@sigill.intra.peff.net>

One often-requested feature is to allow projects to ship
suggested config to people who clone. The most obvious way
of implementing this would be to respect .gitconfig files
within the working tree. However, this has two problems:

  1. Because git configuration can cause the execution of
     arbitrary code, that creates a potential security problem.
     While you may be comfortable running "make" on a newly
     cloned project, you at least have the opportunity to
     inspect the downloaded contents.  But by automatically
     respecting downloaded git configuration, you cannot
     even safely use git to inspect those contents!

  2. Configuration options tend not to be tied to a specific
     version of the project. So if you are using "git
     checkout" to sight-see to an older revision, you
     probably still want to be using the most recent version
     of the suggested config.

Instead, this patch lets you include configuration directly
from a blob in the repository (using the usual object name
lookup rules). This avoids (2) by pointing directly to a tag
or branch tip. It is still possible to be dangerous as in
(1) above, but the danger can be avoided by not pointing
directly into remote blobs (and the documentation warns of
this and gives a safe example).

Signed-off-by: Jeff King <peff@peff.net>
---
 Documentation/config.txt  |   41 ++++++++++++++++++++++++++++++++++++++++-
 config.c                  |   25 ++++++++++++++++++++++++-
 t/t1305-config-include.sh |   38 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 102 insertions(+), 2 deletions(-)

diff --git a/Documentation/config.txt b/Documentation/config.txt
index e55dae1..38e83df 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -93,7 +93,14 @@ included file is expanded immediately, as if its contents had been
 found at the location of the include directive. If the value of the
 `include.path` variable is a relative path, the path is considered to be
 relative to the configuration file in which the include directive was
-found. See below for examples.
+found.
+
+You can also include configuration from a blob stored in your repository
+by setting the special `include.ref` variable to the name of an object
+containing your configuration data (in the same format as a regular
+config file).
+
+See below for examples.
 
 Example
 ~~~~~~~
@@ -120,6 +127,38 @@ Example
 	[include]
 		path = /path/to/foo.inc ; include by absolute path
 		path = foo ; expand "foo" relative to the current file
+		ref = config:.gitconfig ; look on "config" branch
+		ref = origin/master:.gitconfig ; this is unsafe! see below
+
+
+Security Considerations
+~~~~~~~~~~~~~~~~~~~~~~~
+
+Because git configuration may cause git to execute arbitrary shell
+commands, it is important to verify any configuration you receive over
+the network. In particular, it is not a good idea to point `include.ref`
+directly at a remote tracking branch like `origin/master:shared-config`.
+After a fetch, you have no way of inspecting the shared-config you have
+just received without running git (and thus respecting the downloaded
+config). Instead, you can create a local tag representing the last
+verified version of the config, and only update the tag after inspecting
+any new content.
+
+For example:
+
+	# initially, look at their suggested config
+	git show origin/master:shared-config
+
+	# if it looks good to you, point a local ref at it
+	git tag config origin/master
+	git config include.ref config:shared-config
+
+	# much later, fetch any changes and examine them
+	git fetch origin
+	git diff config origin/master -- shared-config
+
+	# If the changes look OK, update your local version
+	git tag -f config origin/master
 
 Variables
 ~~~~~~~~~
diff --git a/config.c b/config.c
index 49a3d1a..c41fb3b 100644
--- a/config.c
+++ b/config.c
@@ -941,7 +941,7 @@ static int handle_path_include(const char *path, void *data)
 	 */
 	if (!is_absolute_path(path)) {
 		char *slash;
-		if (!cf)
+		if (!cf || !cf->f)
 			return error("relative config includes must come from files");
 		strbuf_addstr(&buf, absolute_path(cf->name));
 		slash = find_last_dir_sep(buf.buf);
@@ -958,6 +958,27 @@ static int handle_path_include(const char *path, void *data)
 	return ret;
 }
 
+static int handle_ref_include(const char *ref, void *data)
+{
+	unsigned char sha1[20];
+	char *buf;
+	unsigned long size;
+	enum object_type type;
+	int ret;
+
+	if (get_sha1(ref, sha1))
+		return 0;
+	buf = read_sha1_file(sha1, &type, &size);
+	if (!buf)
+		return error("unable to read include ref '%s'", ref);
+	if (type != OBJ_BLOB)
+		return error("include ref '%s' is not a blob", ref);
+
+	ret = git_config_from_buffer(git_config_include, data, ref, buf, size);
+	free(buf);
+	return ret;
+}
+
 int git_config_include(const char *name, const char *value, void *vdata)
 {
 	const struct git_config_include_data *data = vdata;
@@ -978,6 +999,8 @@ int git_config_include(const char *name, const char *value, void *vdata)
 
 	if (!strcmp(type, "path"))
 		ret = handle_path_include(value, vdata);
+	else if (!strcmp(type, "ref"))
+		ret = handle_ref_include(value, vdata);
 
 	return ret;
 }
diff --git a/t/t1305-config-include.sh b/t/t1305-config-include.sh
index 4db3091..31d3b9b 100755
--- a/t/t1305-config-include.sh
+++ b/t/t1305-config-include.sh
@@ -95,4 +95,42 @@ test_expect_success 'relative includes from command line fail' '
 	test_must_fail git -c include.path=one config test.one
 '
 
+test_expect_success 'include from ref' '
+	echo "[test]one = 1" >one &&
+	git add one &&
+	git commit -m one &&
+	rm one &&
+	echo "[include]ref = HEAD:one" >base &&
+	echo 1 >expect &&
+	git config -f base test.one >actual &&
+	test_cmp expect actual
+'
+
+test_expect_success 'relative file include from ref fails' '
+	echo "[test]two = 2" >two &&
+	echo "[include]path = two" >one &&
+	git add one &&
+	git commit -m one &&
+	echo "[include]ref = HEAD:one" >base &&
+	test_must_fail git config -f base test.two
+'
+
+test_expect_success 'non-existent include refs are ignored' '
+	cat >base <<-\EOF &&
+	[include]ref = my-missing-config-branch:foo.cfg
+	[test]value = yes
+	EOF
+	echo yes >expect &&
+	git config -f base test.value >actual &&
+	test_cmp expect actual
+'
+
+test_expect_success 'non-blob include refs fail' '
+	cat >base <<-\EOF &&
+	[include]ref = HEAD
+	[test]value = yes
+	EOF
+	test_must_fail git config -f base test.value
+'
+
 test_done
-- 
1.7.9.rc2.293.gaae2

^ permalink raw reply related

* Re: Git svn migration does not work because fatal git checkout updating paths is incompatible with switching branches
From: Christine Bauers @ 2012-01-26  8:50 UTC (permalink / raw)
  To: Carlos Martín Nieto; +Cc: git
In-Reply-To: <1327518563.31804.82.camel@centaur.lab.cmartin.tk>

Am 25.01.2012 20:09, schrieb Carlos Martín Nieto:
> On Wed, 2012-01-25 at 19:04 +0100, Christine Bauers wrote:
>> Hi there,
>>
>> I´m trying to migrate a repository from svn to git which branches and
>> tags with the following migration script:
>>
>> git svn clone --no-metadata --stdlayout --A ../users.txt
>> svn://host/svn/project/subproject subproject
>>
>> cd subproject
>> git config svn.authorsfile ../../users.txt
>> git svn fetch
>>
>> git checkout -b branch1 remotes/branch1
>> git checkout -b branch2 remotes/branch2
>> git checkout -b branch3 remotes/branch3
>>
>> git checkout -b src_v1 remotes/tags/src
>> git checkout master
>> git tag src src_v1
>> git branch -D src_v1
>>
>> git checkout -b WebContent_v1 remotes/tags/WebContent
>> git checkout master
>> git tag WebContent WebContent_v1
>> git branch -D WebContent_v1
>>
>> and get the follwoing errors:
>>
>> W: Ignoring error from SVN, path probably does not exist: (160013):
>> Filesystem has no item: Datei nicht gefunden: Revision 8966, Pfad
>> »subproject«
>> W: Do not be alarmed at the above message git-svn is just searching
>> aggressively for old history.
>> This may take a while on large repositories
>> fatal: git checkout: updating paths is incompatible with switching branches.
>> Did you intend to checkout 'remotes/branch1' which can not be resolved
>> as commit?
>> fatal: git checkout: updating paths is incompatible with switching branches.
>> Did you intend to checkout 'remotes/branch2 which can not be resolved as
>> commit?
>> fatal: git checkout: updating paths is incompatible with switching branches.
>> Did you intend to checkout 'remotes/branch3' which can not be resolved
>> as commit?
>> fatal: git checkout: updating paths is incompatible with switching branches.
>> Did you intend to checkout 'remotes/tags/src' which can not be resolved
>> as commit?
>> error: pathspec 'master' did not match any file(s) known to git.
>> fatal: Failed to resolve 'src_v1' as a valid ref.
>> error: branch 'src_v1' not found.
>> fatal: git checkout: updating paths is incompatible with switching branches.
>> Did you intend to checkout 'remotes/tags/WebContent' which can not be
>> resolved as commit?
>> error: pathspec 'master' did not match any file(s) known to git.
>> fatal: Failed to resolve 'WebContent_v1' as a valid ref.
>> error: branch 'WebContent_v1' not found.
>>
>> How do I solve this problem?
> First try to figure out where the problem happens. It could be that
> git-svn isn't recognising the branches properly, or that the layout
> isn't what it expects or any number of things.
>
> What layout does the repo have? Does it correspond to what git-svn is
> expecting? All those error messages come from the fact that you're
> telling git some starting points that it can't find. Make sure those
> exist and they have the name you're giving. What does `git branch -a`
> say? You're presumably not giving us the real names, so we can't tell if
> there are problems there.
>
> If you're looking to migrate completely, something like
> svn-dump-fast-export ( https://github.com/barrbrain/svn-dump-fast-export
> ) might get you there better.
>
>     cmn


Thanks for your answer. I would say the problem happens while cloning the project, because git branch -a and git branch -r says nothing. The question is why aren´t there any branches? Here is the structure of the project:


marketplace

     braches

         lyth_dev

         meinbestand_suche

         umkreis_suche

     tags

         src

         WebContent

     trunk

         src

         WebContent

     trunk_112233

         src

         WebContent

And here again the script:


git svn clone --no-metadata --stdlayout --A ../users.txt svn://host/svn/projects/marketplace marketplace

cd marketplace

git config svn.authorsfile ../../users.txt

git svn fetch

#Checkout Branches

git checkout -b lyth_dev remotes/lyth_dev

git checkout -b meinbestand_suche remotes/meinbestand_suche

git checkout -b umkreis_suche remotes/umkreis_suche


#Checkout der tags

git checkout -b src_v1 remotes/tags/src

git checkout master

git tag src src_v1

git branch -D src_v1

git checkout -b WebContent_v1 remotes/tags/WebContent

git checkout master

git tag WebContent WebContent_v1

git branch -D WebContent_v1

Is there something wrong with this script? Or does the errors maybe occurs because there is a trunk_112233. The log file says the following:

Initialized empty Git repository in c:/project/marketplace/.git/
Checked through r8445
Checked through r8545
Checked through r8645
Checked through r8745
Checked through r8845
Checked through r8945
Checked through r8968
Checked through r8968

And that´s all. It says nothing about references.

Do you have any ideas?

Thanks

^ permalink raw reply

* Re: [PATCH 1/4] config: add include directive
From: Johannes Sixt @ 2012-01-26  9:16 UTC (permalink / raw)
  To: Jeff King; +Cc: git
In-Reply-To: <20120126073752.GA30474@sigill.intra.peff.net>

Am 1/26/2012 8:37, schrieb Jeff King:
> This patch introduces an include directive for config files.

Nice. I haven't had a need for it, yet, but the concept looks good.

> +test_expect_success 'recursive relative paths' '
> +	mkdir subdir &&
> +	echo "[test]three = 3" >subdir/three &&
> +	echo "[include]path = three" >subdir/two &&
> +	echo "[include]path = subdir/two" >base &&
> +	echo 3 >expect &&
> +	git config -f base test.three >actual &&
> +	test_cmp expect actual
> +'

Isn't it rather "chained relative paths"? Recursive would be if I write

  [include]path = .gitconfig

in my ~/.gitconfig. What happens in this case?

-- Hannes

^ permalink raw reply

* Re: [PATCH 4/4] config: allow including config from repository blobs
From: Johannes Sixt @ 2012-01-26  9:25 UTC (permalink / raw)
  To: Jeff King; +Cc: git
In-Reply-To: <20120126074208.GD30474@sigill.intra.peff.net>

Am 1/26/2012 8:42, schrieb Jeff King:
> +static int handle_ref_include(const char *ref, void *data)
> +{
> +	unsigned char sha1[20];
> +	char *buf;
> +	unsigned long size;
> +	enum object_type type;
> +	int ret;
> +
> +	if (get_sha1(ref, sha1))
> +		return 0;
> +	buf = read_sha1_file(sha1, &type, &size);
> +	if (!buf)
> +		return error("unable to read include ref '%s'", ref);
> +	if (type != OBJ_BLOB)
> +		return error("include ref '%s' is not a blob", ref);
> +
> +	ret = git_config_from_buffer(git_config_include, data, ref, buf, size);
> +	free(buf);
> +	return ret;
> +}

What happens if a ref cannot be resolved, for example due to repository
corruption? Does git just emit an error and then carries on, or does it
always die? Can I run at least git-fsck in such a case?

-- Hannes

^ permalink raw reply

* Re: [PATCH] Don't search files with an unset "grep" attribute
From: Stephen Bash @ 2012-01-26 13:51 UTC (permalink / raw)
  To: Jeff King
  Cc: Conrad Irwin, git, Nguyen Thai Ngoc Duy, Dov Grobgeld,
	Junio C Hamano
In-Reply-To: <20120125214625.GA4666@sigill.intra.peff.net>

----- Original Message -----
> From: "Jeff King" <peff@peff.net>
> Sent: Wednesday, January 25, 2012 4:46:26 PM
> Subject: Re: [PATCH] Don't search files with an unset "grep" attribute
>
> ... snip ...
> 
> So if this was all spelled:
> 
>   $ cat .gitattributes
>   *.pdf filetype=pdf
>   $ cat .git/config
>   [filetype "pdf"]
>           binary = true
>           textconv = pdf2txt
> 
> I think it would be a no-brainer that those type attributes should
> apply to "git grep".

Looking at this purely as a user, what difference/advantage would that bring versus

  $ cat .gitattributes
  *.pdf binary=true textconv=pdf2text

or

  $ cat .gitattributes
  [attr]pdf binary=true textconv=pdf2text
  *.pdf pdf

(admittedly I have no clue if gitattributes actually supports anything like this)

I guess my point is as a user, I've gravitated to "gitattributes is about files in my repo, gitconfig is about Git's behavior" (though this is a grey area).

To partially answer my own question: one advantage of putting the filetype information in a config file is it allows system- and user-wide filetype settings.  In my personal experience I've always handled that information on a per-repository basis, but that doesn't mean everyone would want to.

Thanks,
Stephen

^ permalink raw reply

* Re: git version not changed after installing new version
From: freefly @ 2012-01-26 14:33 UTC (permalink / raw)
  To: git
In-Reply-To: <1327530594.31804.87.camel@centaur.lab.cmartin.tk>

 
Thanks ... 
I really appreciate your time.  

^ permalink raw reply

* Re: git version not changed after installing new version
From: freefly @ 2012-01-26 15:13 UTC (permalink / raw)
  To: git
In-Reply-To: <loom.20120126T144828-400@post.gmane.org>

that doesn't seem to change the path :(

which git => /usr/bin/git

version still points to the old one  :(

This is my current path that I changed, as you told me to do... 

/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/X11/bin:/usr/local/git/bin

^ permalink raw reply

* Re: git svn dcommit sends to wrong branch
From: badgerhardy @ 2012-01-26 15:27 UTC (permalink / raw)
  To: git
In-Reply-To: <877h0yz269.fsf@thomas.inf.ethz.ch>


Thomas Rast wrote
> 
> Victor Engmark &lt;victor.engmark@&gt; writes:
> 
> The rule is that the commits go to the branch named in the git-svn-id
> line of the most recent first-parent ancestor of HEAD.
> 
> You can find the "base" commit in question with
> 
>   git log -1 --first-parent --grep=^git-svn-id:
> 
>> And more importantly, how do I "replay" my commits on trunk?
> 
> You need to rebase the commits on trunk, and (very important) strip the
> git-svn-id lines from their messages.  If you only had a handful of
> commits, your best bet is to use something like
> 
>   git checkout -b newbranch
>   git rebase -i --onto svn/trunk svn/branch_name  # or whatever git-svn
> named the remote branches
>   # edit all the 'pick' into 'reword'
>   # in every commit message editor that pops up, remove the git-svn-id
> line
> 
>   gitk  # make sure that you like the resulting history!
>   git svn dcommit
> 

I had the same problem and have followed these instructions (thanks!). I now
have a 'newbranch' that will correctly dcommit to the svn trunk. What
happens to the git 'master'? Is this recoverable or do I need to delete it
and rename the 'newbranch' as master?

Thanks,

--
View this message in context: http://git.661346.n2.nabble.com/git-svn-dcommit-sends-to-wrong-branch-tp7172744p7227251.html
Sent from the git mailing list archive at Nabble.com.

^ permalink raw reply

* Re: [PATCH] Don't search files with an unset "grep" attribute
From: Michael Haggerty @ 2012-01-26 16:45 UTC (permalink / raw)
  To: Jeff King
  Cc: Junio C Hamano, Conrad Irwin, git, Nguyen Thai Ngoc Duy,
	Dov Grobgeld
In-Reply-To: <20120125214625.GA4666@sigill.intra.peff.net>

On 01/25/2012 10:46 PM, Jeff King wrote:
> But what I'm not sure I agree with is that the idea of "I don't want to
> include path X in my grep" maps to "just mark the file as binary".

Anybody who wants this policy can simply set

    [attr]binary -diff -text -grep

If they want finer granularity, they can adjust the settings for
particular file types or for particular files.

> But should I mark everything in compat/nedmalloc as binary? I don't
> think so. I _do_ want to see changes in nedmalloc in "git log" or "git
> diff". They don't bother me because they're infrequent, and we still
> want to produce regular text patches for the list when they come up. But
> because nedmalloc contains a lot of lines of code (even though they
> don't change a lot), it happens to produce a lot of uninteresting
> matches when grepping.

I think decisions such as whether to include an imported module in "git
diff" output is a personal preference and should not be decided at the
level of the git project.  The in-tree .gitattributes files should, by
and large, just *describe* the files and leave it to users to associate
policies with the tags (or at least make it possible for users to
override the policies) via .git/info/attributes.  For example, the
repository could set an "external=nedmalloc" attribute on all files
under compat/nedmalloc, and users could themselves configure a macro
"[attr]external -diff -grep" (or maybe something like
"[attr]external=nedmalloc -diff -grep") if that is their preference.

> It would be nice to be able to treat them differently in the cases you
> wanted to, but not _have_ to do so. Attribute macros can almost
> implement this. You could add "-grep" to binary. But you can't (as far
> as I know) do "macro=foo" to handle arbitrary diff drivers. I suspect we
> could extend the rules to allow macros that take an argument and pass it
> to their constituent attributes.

Is it really common to want to use the same argument on multiple macros
without also wanting to set other things specifically?  If not, then
there is not much reason to complicate macros with argument support.

For example, I do something like

    [attr]type-python type=python text diff=python check-ws
    *.py type-python

    [attr]type-makefile type=makefile text diff check-ws -check-tab
    Makefile.* type-makefile

for the main file types in my repository, and it is not very cumbersome.

"type-python" and "type=python" seem redundant but they are not.
"type-python" is needed so that it can be used as a macro.
"type=python" makes it easier to inquire about the type of a file using
something like "git check-attr type -- PATH" rather than having to
inquire about each possible type-* attribute.  It might be nice to
support a slightly extended macro definition syntax like

    [attr]type=python text diff=python check-ws
    *.py type=python

    [attr]type=makefile text diff check-ws -check-tab
    Makefile.* type=makefile

(i.e., macros that are only triggered for particular values of an
attribute).

Michael

-- 
Michael Haggerty
mhagger@alum.mit.edu
http://softwareswirl.blogspot.com/

^ permalink raw reply

* Re: git version not changed after installing new version
From: Holger Hellmuth @ 2012-01-26 16:52 UTC (permalink / raw)
  To: freefly; +Cc: git
In-Reply-To: <loom.20120126T161101-463@post.gmane.org>

On 26.01.2012 16:13, freefly wrote:
> that doesn't seem to change the path :(
>
> which git =>  /usr/bin/git
>
> version still points to the old one  :(
>
> This is my current path that I changed, as you told me to do...
>
> /usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/X11/bin:/usr/local/git/bin

Put /usr/local/git/bin in front (it is easy to overlook the "git/" in 
there as software often uses /usr/local/bin)

^ 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