* Re: [PATCH] Use "" instead of "<unknown>" for placeholders
From: Michal Vitecek @ 2007-09-22 8:53 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git, Johannes Schindelin
In-Reply-To: <7vk5qjixqy.fsf@gitster.siamese.dyndns.org>
Junio C Hamano wrote:
>>>>>> I made it because I want to use my own pretty format which currently
>>>>>> only allows '%s' for subject and '%b' for body. But '%b' is
>>>>>> substituted with <undefined> if the body is "missing" which I
>>>>>> obviously don't like :)
>>>>> Then you should fix %b not to show "<undefined>".
>>>> I'll do it if it is okay. Shall I do the same for the other
>>>> placeholders as well?
>>> Yeah. Don't know why I did it that way.
>> Here comes the big patch :)
>
> Now, this breaks t6006 which needs this patch.
Oops - I'm sorry about that. I ran the test suite (1.5.3.1) but it
failed in 2 tests before the patch and in 2 tests after it so I
considered it okay.
> Looking at this patch, I am not sure if your change is really a
> desirable one --- shouldn't it be removing the line itself, not
> just <unknown> token?
This sounds as the best solution. I'll look into it. Thanks for your time.
--
fuf (fuf@mageo.cz)
^ permalink raw reply
* [StGit PATCH 3/4] Properly remove all config for a deleted branch
From: Karl Hasselström @ 2007-09-22 8:46 UTC (permalink / raw)
To: Catalin Marinas; +Cc: git, Aneesh Kumar, Karl Hasselström
In-Reply-To: <20070922084334.29884.60506.stgit@yoghurt>
This uses "git-config --remove-section", which was first released in
git 1.5.1-rc1. I'm not sure if this is later than what we used to
depend on; we already use "git-config --rename-section", but that's
been in since git 1.5.0-rc0.
Signed-off-by: Karl Hasselström <kha@treskal.com>
---
stgit/config.py | 7 +++++++
stgit/stack.py | 9 ++-------
2 files changed, 9 insertions(+), 7 deletions(-)
diff --git a/stgit/config.py b/stgit/config.py
index 799e1d7..51818bd 100644
--- a/stgit/config.py
+++ b/stgit/config.py
@@ -76,6 +76,13 @@ class GitConfig:
).returns([0, 1]).run()
self.__cache.clear()
+ def remove_section(self, name):
+ """Remove a section in the config file. Silently do nothing if
+ the section doesn't exist."""
+ Run('git-repo-config', '--remove-section', name
+ ).returns([0, 1]).discard_stderr().discard_output()
+ self.__cache.clear()
+
def set(self, name, value):
Run('git-repo-config', name, value).run()
self.__cache[name] = value
diff --git a/stgit/stack.py b/stgit/stack.py
index d6f6a6e..adfff25 100644
--- a/stgit/stack.py
+++ b/stgit/stack.py
@@ -744,13 +744,8 @@ class Series(PatchSet):
except GitException:
out.warn('Could not delete branch "%s"' % self.get_name())
- # Cleanup parent informations
- # FIXME: should one day make use of git-config --section-remove,
- # scheduled for 1.5.1
- config.unset('branch.%s.remote' % self.get_name())
- config.unset('branch.%s.merge' % self.get_name())
- config.unset('branch.%s.stgit.parentbranch' % self.get_name())
- config.unset(self.format_version_key())
+ config.remove_section('branch.%s' % self.get_name())
+ config.remove_section('branch.%s.stgit' % self.get_name())
def refresh_patch(self, files = None, message = None, edit = False,
show_patch = False,
^ permalink raw reply related
* [StGit PATCH 4/4] Add simple test for "stg branch --delete"
From: Karl Hasselström @ 2007-09-22 8:46 UTC (permalink / raw)
To: Catalin Marinas; +Cc: git, Aneesh Kumar, Karl Hasselström
In-Reply-To: <20070922084334.29884.60506.stgit@yoghurt>
Signed-off-by: Karl Hasselström <kha@treskal.com>
---
t/t1005-branch-delete.sh | 29 +++++++++++++++++++++++++++++
1 files changed, 29 insertions(+), 0 deletions(-)
create mode 100755 t/t1005-branch-delete.sh
diff --git a/t/t1005-branch-delete.sh b/t/t1005-branch-delete.sh
new file mode 100755
index 0000000..7a0872e
--- /dev/null
+++ b/t/t1005-branch-delete.sh
@@ -0,0 +1,29 @@
+#!/bin/sh
+
+test_description='Attempt to delete branches'
+
+. ./test-lib.sh
+
+stg init
+
+test_expect_success 'Create a branch (and switch to it)' '
+ stg branch --create foo
+ '
+
+test_expect_success 'Delete a branch' '
+ stg branch --delete master
+ '
+
+test_expect_success 'Make sure the branch ref was deleted' '
+ [ -z "$(git show-ref | grep master | tee /dev/stderr)" ]
+ '
+
+test_expect_success 'Make sure the branch config was deleted' '
+ [ -z "$(git config -l | grep branch\\.master | tee /dev/stderr)" ]
+ '
+
+test_expect_success 'Make sure the branch files were deleted' '
+ [ -z "$(find .git -type f | grep master | tee /dev/stderr)" ]
+ '
+
+test_done
^ permalink raw reply related
* [StGit PATCH 1/4] Don't special-case the "master" branch during branch delete
From: Karl Hasselström @ 2007-09-22 8:46 UTC (permalink / raw)
To: Catalin Marinas; +Cc: git, Aneesh Kumar, Karl Hasselström
In-Reply-To: <20070922084334.29884.60506.stgit@yoghurt>
It's unintuitive, unsymmetric and doesn't work if there is no
"master". Instead, prohibit deletion of the current branch.
Signed-off-by: Karl Hasselström <kha@treskal.com>
---
stgit/commands/branch.py | 11 ++---------
1 files changed, 2 insertions(+), 9 deletions(-)
diff --git a/stgit/commands/branch.py b/stgit/commands/branch.py
index 2d491d5..8c99936 100644
--- a/stgit/commands/branch.py
+++ b/stgit/commands/branch.py
@@ -96,17 +96,10 @@ def __delete_branch(doomed_name, force = False):
out.start('Deleting branch "%s"' % doomed_name)
if __is_current_branch(doomed_name):
- check_local_changes()
- check_conflicts()
- check_head_top_equal()
-
- if doomed_name != 'master':
- git.switch_branch('master')
+ raise CmdException('Cannot delete the current branch')
doomed.delete(force)
-
- if doomed_name != 'master':
- git.delete_branch(doomed_name)
+ git.delete_branch(doomed_name)
out.done()
^ permalink raw reply related
* [StGit PATCH 2/4] Don't try to delete the branch twice
From: Karl Hasselström @ 2007-09-22 8:46 UTC (permalink / raw)
To: Catalin Marinas; +Cc: git, Aneesh Kumar, Karl Hasselström
In-Reply-To: <20070922084334.29884.60506.stgit@yoghurt>
We already delete it in Stack.delete(), so don't do it here too.
Signed-off-by: Karl Hasselström <kha@treskal.com>
---
stgit/commands/branch.py | 1 -
1 files changed, 0 insertions(+), 1 deletions(-)
diff --git a/stgit/commands/branch.py b/stgit/commands/branch.py
index 8c99936..c16fc69 100644
--- a/stgit/commands/branch.py
+++ b/stgit/commands/branch.py
@@ -99,7 +99,6 @@ def __delete_branch(doomed_name, force = False):
raise CmdException('Cannot delete the current branch')
doomed.delete(force)
- git.delete_branch(doomed_name)
out.done()
^ permalink raw reply related
* [StGit PATCH 0/4] Fix "stg branch --delete"
From: Karl Hasselström @ 2007-09-22 8:46 UTC (permalink / raw)
To: Catalin Marinas; +Cc: git, Aneesh Kumar
In-Reply-To: <20070921094830.GB26307@diana.vm.bytemark.co.uk>
This fixes the two issues Aneesh reported (failed branch deletion,
leftover config stuff), and adds a test. The test is added after the
fixes this time, so the test suite passes at every step.
Also available from
git://repo.or.cz/stgit/kha.git safe
---
Karl Hasselström (4):
Add simple test for "stg branch --delete"
Properly remove all config for a deleted branch
Don't try to delete the branch twice
Don't special-case the "master" branch during branch delete
stgit/commands/branch.py | 10 +---------
stgit/config.py | 7 +++++++
stgit/stack.py | 9 ++-------
t/t1005-branch-delete.sh | 29 +++++++++++++++++++++++++++++
4 files changed, 39 insertions(+), 16 deletions(-)
create mode 100755 t/t1005-branch-delete.sh
--
Karl Hasselström, kha@treskal.com
www.treskal.com/kalle
^ permalink raw reply
* Re: [PATCH] Allow shell scripts to run with non-Bash /bin/sh
From: Junio C Hamano @ 2007-09-22 8:32 UTC (permalink / raw)
To: Eygene Ryabinkin; +Cc: git
In-Reply-To: <20070922035434.GA99140@void.codelabs.ru>
Eygene Ryabinkin <rea-git@codelabs.ru> writes:
> OK, you're right. Especially if /bin/sh from Solaris and OpenBSD
> are working and they are not Bash. But I would not tell that
> the shell is broken now -- I had not seen the POSIX specification.
> Does it specifies how the shell should work in this case?
I have always been assuming it to be the case (this construct is
not my invention but is an old school idiom I just inherited
from my mentor) and never looked at the spec recently, but I
re-read it just to make sure. The answer is yes.
Visit http://www.opengroup.org/onlinepubs/000095399/ and follow
"Shell and Utilities volume (XCU)" and then "Case conditional
construct".
Exit Status
The exit status of case shall be zero if no patterns are
matched. Otherwise, the exit status shall be the exit status of
the last command executed in the compound-list.
So, as David suggests, if
false
case Ultra in
Super) false ;;
Hyper) true ;;
esac && echo case returned ok
does not say "case returned ok", then the shell has a bit of
problem.
^ permalink raw reply
* Re: [PATCH] Allow shell scripts to run with non-Bash /bin/sh
From: Vineet Kumar @ 2007-09-22 7:34 UTC (permalink / raw)
To: git
In-Reply-To: <7vd4wbgp9t.fsf@gitster.siamese.dyndns.org>
* Junio C Hamano (gitster@pobox.com) [070921 23:58]:
> David Kastrup <dak@gnu.org> writes:
>
> > Eygene Ryabinkin <rea-git@codelabs.ru> writes:
> >
> >>> That is, what does the shell say if you do this?
> >>>
> >>> case Ultra in
> >>> Super)
> >>> false ;;
> >>> Hyper)
> >>> true ;;
> >>> esac &&
> >>> echo case returned ok
> >>
> >> It says 'case returned ok', so I will try to understand why it
> >> works here and does not work in the 'while' construct.
> >
> > What you actually need to do is
> >
> > false
> > case Ultra in
> > Super)
> > false ;;
> > Hyper)
> > true ;;
> > esac && echo case returned ok
>
> AHHHHHH.
>
> Is "case" supposed to be transparent?
That doesn't seem to be the case (no pun intended) on either bash or
dash. Here's what I tested on bash (apologies for the long lines; these
are verbatim pastes from my shell):
vineet@sprocket:~$ false
vineet@sprocket:~$ case Super in Super) echo super ; false ;; Hyper) echo hyper ; true ;; esac && echo case returned ok
super
vineet@sprocket:~$ false
vineet@sprocket:~$ case Hyper in Super) echo super ; false ;; Hyper) echo hyper ; true ;; esac && echo case returned ok
hyper
case returned ok
vineet@sprocket:~$ false
vineet@sprocket:~$ case Ultra in Super) echo super ; false ;; Hyper) echo hyper ; true ;; esac && echo case returned ok
case returned ok
vineet@sprocket:~$
and on dash:
vineet@sprocket:~$ dash
$ false
$ case Super in Super) echo super ; false ;; Hyper) echo hyper ; true ;; esac && echo case returned ok
super
$ false
$ case Hyper in Super) echo super ; false ;; Hyper) echo hyper ; true ;; esac && echo case returned ok
hyper
case returned ok
$ false
$ case Ultra in Super) echo super ; false ;; Hyper) echo hyper ; true ;; esac && echo case returned ok
case returned ok
$
So it seems like a "case" statement isn't special; it returns a status
like any other statement.
Vineet
--
http://www.doorstop.net/
^ permalink raw reply
* fromcvs installation [was: cvsimport bug on branches [was: conversion to git]]
From: Steffen Prohaska @ 2007-09-22 8:07 UTC (permalink / raw)
To: Robin Rosenberg
Cc: Johannes Schindelin, Git Mailing List,
Simon 'corecode' Schubert
In-Reply-To: <200709220116.26369.robin.rosenberg.lists@dewire.com>
On Sep 22, 2007, at 1:16 AM, Robin Rosenberg wrote:
> fredag 21 september 2007 skrev Johannes Schindelin:
>> No, it's yet another dependency. And the quality of the code still
>> depends on the programmer, not the language.
>
> I think I can agree there, on both counts. But, if you want a good
> incremental
> CVS importer and have access to the rcs files, that's the one there
> is.
>
> git-cvsimport has a dependency on cvsps, which isn't included. You
> have to
> to look it up yourself chooing among a dozen unequally bad versions.
> Installing ruby isn't any harder.
>
> The dependency excludes it from being included with Git, but it
> does not
> disqualify it as a tool on it's own.
Nonetheless a more detailed description how to install fromcvs
would be helpful. I remember it was not obvious to me.
The README of fromcvs only says
'''
Prerequisites:
- ruby (1.8.5 known working)
- fromcvs, <http://ww2.fs.ei.tum.de/~corecode/hg/fromcvs>
- rcsparse, <http://ww2.fs.ei.tum.de/~corecode/hg/rcsparse> (ruby
module)
- Ruby/RBTree, <http://raa.ruby-lang.org/project/ruby-rbtree/>
- for git: git-fast-import, part of git 1.5
- for db/commitset: sqlite3 + sqlite3-ruby (available as gem)
'''
I didn't use ruby before and had no idea how to install a ruby module
or what 'available as gem' means. And by the way, it was not obvious
for me that I can download the tip of the mercurial branch by clicking
on the 'gz' link at the top of the page.
I think a step by step explanation how to proceed would have helped me.
Steffen
^ permalink raw reply
* Re: [PATCH] Allow shell scripts to run with non-Bash /bin/sh
From: Junio C Hamano @ 2007-09-22 6:58 UTC (permalink / raw)
To: David Kastrup; +Cc: git
In-Reply-To: <86tzpnwdha.fsf@lola.quinscape.zz>
David Kastrup <dak@gnu.org> writes:
> Eygene Ryabinkin <rea-git@codelabs.ru> writes:
>
>>> That is, what does the shell say if you do this?
>>>
>>> case Ultra in
>>> Super)
>>> false ;;
>>> Hyper)
>>> true ;;
>>> esac &&
>>> echo case returned ok
>>
>> It says 'case returned ok', so I will try to understand why it
>> works here and does not work in the 'while' construct.
>
> What you actually need to do is
>
> false
> case Ultra in
> Super)
> false ;;
> Hyper)
> true ;;
> esac && echo case returned ok
AHHHHHH.
Is "case" supposed to be transparent?
^ permalink raw reply
* Re: [PATCH] Allow shell scripts to run with non-Bash /bin/sh
From: Junio C Hamano @ 2007-09-22 6:54 UTC (permalink / raw)
To: Eygene Ryabinkin; +Cc: git
In-Reply-To: <20070922035434.GA99140@void.codelabs.ru>
Eygene Ryabinkin <rea-git@codelabs.ru> writes:
> By the way, my FreeBSD is 7-CURRENT, but I'll test on 6-STABLE
> and perhaps on 4-STABLE on Monday.
> ...
>> That is, what does the shell say if you do this?
>>
>> case Ultra in
>> Super)
>> false ;;
>> Hyper)
>> true ;;
>> esac &&
>> echo case returned ok
>
> It says 'case returned ok', so I will try to understand why it
> works here and does not work in the 'while' construct.
I vaguely recall somebody else had exactly this issue and he
concluded that the shell was busted. I do not recall the
details of the story but interestingly, if he did something that
accesses "$#" before the problematic "while case $# in ..." the
shell behaved for him in his experiments.
Just to make sure you do not misunderstand me, I am not trying
to be difficult. I am trying to assess (1) if it is sensible to
support that broken shell, and (2) if so what the exact breakage
is, especially because as the above shows the breakage does not
look like what your "fix" literally suggests, and what is
involved in working it around.
Also by my comment about "/bin/sh and bash not being the only
shells available on FreeBSD", I did not mean that you should
change your /bin/sh. You can build git with SHELL_PATH make
varilable pointing at a non-broken shell, which does not have to
be installed as /bin/sh.
^ permalink raw reply
* [PATCH] Allow gitk to start on Cygwin with native Win32 Tcl/Tk
From: Shawn O. Pearce @ 2007-09-22 5:04 UTC (permalink / raw)
To: Junio C Hamano, Paul Mackerras; +Cc: git
If TCLTK_PATH points at a pure Win32 Tcl/Tk implementation but you
are running git (and thus gitk) from within Cygwin the value of
$0 is a UNIX style Cygwin path which the native Tcl/Tk is unable
to open and parse. In such a situation we need to switch to using
the Windows style path by running $0 through cygpath.
This doesn't have a negative impact when using the Cygwin based
Tcl/Tk build as that is still close enough to a native Win32
application that it can read the Windows style path when sourcing
gitk. On any other platform we don't want gitk to do anything
different so we keep argv0=$0.
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
---
Yes, I admit this is an odd patch. I can certainly carry it in
my own tree (I already carry some other patches) but I wonder if
we shouldn't include it as some users may actually try to do this,
just like I did. Latest git-gui `master` already has changes to its
Makefile and shell startup boilerplate to handle this weird case.
Makefile | 6 +++++-
gitk | 3 ++-
2 files changed, 7 insertions(+), 2 deletions(-)
diff --git a/Makefile b/Makefile
index 0055eef..4fc6eb3 100644
--- a/Makefile
+++ b/Makefile
@@ -386,6 +386,7 @@ EXTLIBS =
#
# Platform specific tweaks
#
+gitk_argv0 := $$0
# We choose to avoid "if .. else if .. else .. endif endif"
# because maintaining the nesting to match is a pain. If
@@ -443,6 +444,7 @@ ifeq ($(uname_O),Cygwin)
NO_MMAP = YesPlease
NO_IPV6 = YesPlease
X = .exe
+ gitk_argv0 := `cygpath --windows --absolute "$(gitk_argv0)"`
endif
ifeq ($(uname_S),FreeBSD)
NEEDS_LIBICONV = YesPlease
@@ -763,7 +765,9 @@ strip: $(PROGRAMS) git$X
gitk-wish: gitk GIT-GUI-VARS
$(QUIET_GEN)$(RM) $@ $@+ && \
- sed -e '1,3s|^exec .* "$$0"|exec $(subst |,'\|',$(TCLTK_PATH_SQ)) "$$0"|' <gitk >$@+ && \
+ sed -e '1,30s|^argv0=$$0|argv0=$(gitk_argv0)|' \
+ -e '1,4s|^exec .* "$$argv0"|exec $(subst |,'\|',$(TCLTK_PATH_SQ)) "$$argv0"|' \
+ <gitk >$@+ && \
chmod +x $@+ && \
mv -f $@+ $@
diff --git a/gitk b/gitk
index 300fdce..2366911 100755
--- a/gitk
+++ b/gitk
@@ -1,6 +1,7 @@
#!/bin/sh
# Tcl ignores the next line -*- tcl -*- \
-exec wish "$0" -- "$@"
+argv0=$0; \
+exec wish "$argv0" -- "$@"
# Copyright (C) 2005-2006 Paul Mackerras. All rights reserved.
# This program is free software; it may be used, copied, modified
--
1.5.3.2.1036.gcd14a
^ permalink raw reply related
* Re: [PATCH] Allow shell scripts to run with non-Bash /bin/sh
From: David Kastrup @ 2007-09-22 4:06 UTC (permalink / raw)
To: git
In-Reply-To: <20070922035434.GA99140@void.codelabs.ru>
Eygene Ryabinkin <rea-git@codelabs.ru> writes:
>> That is, what does the shell say if you do this?
>>
>> case Ultra in
>> Super)
>> false ;;
>> Hyper)
>> true ;;
>> esac &&
>> echo case returned ok
>
> It says 'case returned ok', so I will try to understand why it
> works here and does not work in the 'while' construct.
What you actually need to do is
false
case Ultra in
Super)
false ;;
Hyper)
true ;;
esac && echo case returned ok
--
David Kastrup
^ permalink raw reply
* Re: [PATCH] Allow shell scripts to run with non-Bash /bin/sh
From: Eygene Ryabinkin @ 2007-09-22 3:54 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <7v8x6zinjf.fsf@gitster.siamese.dyndns.org>
Junio, good day.
Fri, Sep 21, 2007 at 04:52:52PM -0700, Junio C Hamano wrote:
> > Option parsing in the Git shell scripts uses the construct 'while
> > case "$#" in 0) break ;; esac; do ... done'. This is neat, because
> > it needs no external commands invocation. But in the case when
> > /bin/sh is not GNU Bash (for example, on FreeBSD) this cycle will
> > not be executed at all.
>
> I do not doubt that "while case $# in 0) break ;; esac" does not
> work for your shell. But I think the above comment is grossly
> misleading.
>
> Don't mention bash there. You sound as if you are blaming
> bashism, but the thing is, your shell is simply broken.
OK, you're right. Especially if /bin/sh from Solaris and OpenBSD
are working and they are not Bash. But I would not tell that
the shell is broken now -- I had not seen the POSIX specification.
Does it specifies how the shell should work in this case?
> You have other choices than bash on BSD don't you?
Did not understand the question, sorry. The thing is that
FreeBSD has /bin/sh that is derived from the original Berkeley
shell. And it is desirable to have it working with Git
script, since I don't want to make bash (or whatever shell
that is not /bin/sh) a dependency for the port.
> My quick test shows that ksh, pdksh and dash seem to work
> correctly. This idiom is what I picked up around late 80's from
> somebody, and kept using on many variants of Unices. I would
> find quite surprising that something that claims to be a shell
> does not work correctly. Even /bin/sh that comes with Solaris
> seems to work correctly, which should tell you something.
>
> OpenBSD's /bin/sh seems to be Ok; I do not know whose shell they
> use, but it seems to be hard-linked to /bin/ksh which is pdksh.
OK, I think I need to find out why FreeBSD's /bin/sh behaves
like this, because the test you propose on your next message
works. See below.
By the way, my FreeBSD is 7-CURRENT, but I'll test on 6-STABLE
and perhaps on 4-STABLE on Monday.
Fri, Sep 21, 2007 at 07:33:21PM -0700, Junio C Hamano wrote:
> I am assuming that this works around _a_ bug in that /bin/sh; I
> would make sure I understand the nature of the bug. Is it Ok to
> understand that with that shell, after this construct runs:
>
> case <some word> in
> <case arm #1>)
> something ;;
> <case arm #2>)
> something else ;;
> esac
>
> the status from the whole case statement is false, when <some word>
> does not match any of the glob patterns listed in any of the case arm?
>
> That is, what does the shell say if you do this?
>
> case Ultra in
> Super)
> false ;;
> Hyper)
> true ;;
> esac &&
> echo case returned ok
It says 'case returned ok', so I will try to understand why it
works here and does not work in the 'while' construct.
Thanks for the pointer!
--
Eygene
^ permalink raw reply
* Re: Git as a filesystem
From: Sam Vilain @ 2007-09-22 3:09 UTC (permalink / raw)
To: Martin Langhoff
Cc: Dmitry Potapov, Peter Stahlir, Karl Hasselström,
Johannes Schindelin, git
In-Reply-To: <46a038f90709211656n5b23783eu330e8b655cd42aa8@mail.gmail.com>
Martin Langhoff wrote:
> On 9/22/07, Dmitry Potapov <dpotapov@gmail.com> wrote:
>
>> used to create the original file. So, if you put any .deb file in such
>> a system, you will get back a different .deb file (with a different SHA1).
>> So, aside high CPU and memory requirements, this system cannot work in
>> principle unless all users have exactly the same version of a compressor.
>>
>
> Was thinking the same - compression machinery, ordering of the files,
> everything. It'd be a nightmare to ensure you get back the same .deb,
> without a single different bit.
>
> Debian packaging toolchain could be reworked to use a more GIT-like
> approach - off the top of my head, at least
>
> - signing/validating the "tree" of the package rather than the
> completed package could allow the savings in distribution you mention,
> decouple the signing from the compression, and simplify things like
> debdiff
>
> - git or git-like strategies for source packages
>
Nightmare indeed. I actually wrote a proof of concept for this idea for
gzip.
http://git.catalyst.net.nz/gw?p=git.git;a=shortlog;h=archive-blobs
(see also
http://planet.catalyst.net.nz/blog/2006/07/17/samv/xteddy_caught_consuming_rampant_amounts_of_disk_space)
I usually warn people that this undertaking is "slightly insane".
My implementation was designed to be called like "git-hash-object".
What it did was look at the input stream, and detect quickly whether it
looked like a gzip stream. If it was, it would decompress it and then
try to compress the first few blocks using different compression
libraries and settings to determine what settings were used. If it
could find the right settings for the first meg or so, then it would
bank on the rest being identical as well, record which compressor and
what settings were used and write the uncompressed object, as well as
the information needed to reconstruct the gzip header, to a new type of
object called an "archive" object. If the stream could not be
reproduced then it would save the raw stream instead. For something
like a Debian archive, it is very likely that all compressed streams
will be reproducible, because they will almost all be compressed using
the same implementation of gzip.
For tar and .ar files, this can be slightly more deterministic of
course. It doesn't even need to be particularly savvy of what all the
fields are - just locate the files in the .tar, write out a tree, and
then write a TOC that lists tree entries and contains any extra data (ie
headers, etc).
In hindsight, making a new object type was probably a mistake. If I
were to re-undertake this I would not go down that path, though I'd
certainly consider using tag objects for the extra data, and throwing
them in the tree like submodules. It would also be essential in a
"real" solution to bundle reference copies of the zlib and gzip
compressors (yes, their output streams differ with longer inputs and
even some short ones).
Sam.
^ permalink raw reply
* Re: [PATCH] Allow shell scripts to run with non-Bash /bin/sh
From: Junio C Hamano @ 2007-09-22 2:33 UTC (permalink / raw)
To: Eygene Ryabinkin; +Cc: git
In-Reply-To: <20070921214346.GF97288@void.codelabs.ru>
Eygene Ryabinkin <rea-git@codelabs.ru> writes:
> Good day.
>
> I had found that FreeBSD's /bin/sh refuses to work with git 1.5.3.2.
> correctly: no flags are recognized.
> @@ -109,7 +109,7 @@ dotest=.dotest sign= utf8=t keep= skip= interactive= resolved= binary=
> resolvemsg= resume=
> git_apply_opt=
>
> -while case "$#" in 0) break;; esac
> +while case "$#" in 0) break;; *) : ;; esac
> do
I am assuming that this works around _a_ bug in that /bin/sh; I
would make sure I understand the nature of the bug. Is it Ok to
understand that with that shell, after this construct runs:
case <some word> in
<case arm #1>)
something ;;
<case arm #2>)
something else ;;
esac
the status from the whole case statement is false, when <some word>
does not match any of the glob patterns listed in any of the case arm?
That is, what does the shell say if you do this?
case Ultra in
Super)
false ;;
Hyper)
true ;;
esac &&
echo case returned ok
The reason I ask is because
while case $# in 0) ... esac
do
...
done
is not the only place the status from "case" itself matters in
our scripts. There are places that do
something &&
case ... in
...
esac &&
something else
and we would need to add no-op match-everything arm to all of
such case statements in our scripts.
Besides test scripts, there is one in git-ls-remote.sh which you
seem to have missed.
^ permalink raw reply
* Re: Git as a filesystem
From: Eric Wong @ 2007-09-22 2:06 UTC (permalink / raw)
To: Johannes Schindelin; +Cc: Nicolas Pitre, Peter Stahlir, git
In-Reply-To: <Pine.LNX.4.64.0709220040450.28395@racer.site>
Johannes Schindelin <Johannes.Schindelin@gmx.de> wrote:
> Hi,
Hi,
> On Fri, 21 Sep 2007, Eric Wong wrote:
> >
> > On a similar note, has anybody experimented with using git to
> > store maildirs or news spools? I'd imagine the quoted portions of
> > most message threads could be delta-compressed quite efficiently.
>
> I store all my mail in a git repository. Works beautifully. Except that
> the buffers on my laptop are constantly full :-( So a simple commit takes
> some waiting.
>
> Should be no issue on normal (desktop) machines.
D'oh. I already have maildir performance problems on my laptop.
I wonder how well only having an index and no commits (no versioning),
and manual packing with pack-objects would work. Packing could be
optimized to order objects based on the Message-Id, References, and
In-Reply-To headers, too.
--
Eric Wong
^ permalink raw reply
* [PATCH] git-svn: don't attempt to spawn pager if we don't want one
From: Eric Wong @ 2007-09-22 1:48 UTC (permalink / raw)
To: Junio C Hamano; +Cc: Chris Moore, git
In-Reply-To: <a9691ee20709211640q63881718k75ebf416bf5e217f@mail.gmail.com>
Even though config_pager() unset the $pager variable, we were
blindly calling exec() on it through run_pager().
Noticed-by: Chris Moore <christopher.ian.moore@gmail.com>
Signed-off-by: Eric Wong <normalperson@yhbt.net>
---
Chris Moore <christopher.ian.moore@gmail.com> wrote:
> I run my git commands inside an Emacs *shell* buffer, so I don't want
> it running 'less' all the time. I export GIT_PAGER=cat to stop it.
>
> I just tried a "git-svn log" and it failed:
>
> $ GIT_PAGER=cat git-svn log
> Use of uninitialized value in exec at /usr/bin/git-svn line 3451.
> Use of uninitialized value in concatenation (.) or string at
> /usr/bin/git-svn line 3451.
> Can't run pager: Illegal seek ()
>
> I don't get a shell prompt back. It just hangs.
>
> This is on ubuntu feisty with the ubuntu-backport repositories enabled:
>
> ii git-core 1.5.2.5-2~feisty1
> ii git-svn 1.5.2.5-2~feisty1
git-svn.perl | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/git-svn.perl b/git-svn.perl
index 288d32c..484b057 100755
--- a/git-svn.perl
+++ b/git-svn.perl
@@ -3578,7 +3578,7 @@ sub config_pager {
}
sub run_pager {
- return unless -t *STDOUT;
+ return unless -t *STDOUT && defined $pager;
pipe my $rfd, my $wfd or return;
defined(my $pid = fork) or ::fatal "Can't fork: $!\n";
if (!$pid) {
--
Eric Wong
^ permalink raw reply related
* [RFC] Add git-rev-list --not-(author|committer|grep)!=pattern
From: Bart Trojanowski @ 2007-09-22 1:38 UTC (permalink / raw)
To: Junio C Hamano, Johannes Schindelin; +Cc: git
In-Reply-To: <Pine.LNX.4.64.0709202252570.28395@racer.site>
Hi Johannes, Junio,
I have worked out what I would like to see for git-log and friends. It
addresses one of the requirements which was raised by Johannes.
* Johannes Schindelin <Johannes.Schindelin@gmx.de> [070920 06:34]:
> IMHO this is only half a solution. Some of us want to say "git log
> --grep=this --but-not-(in-the-whole-message) --grep=that".
The way in which you get that information is:
git-log --all-match \
--grep=Merge \
--not-committer=gitster \
--author!=Shawn
I have tested it with and without --all-match and seems to work as I
would expect. git-grep -v is still broken, but I will submit that in
another patch.
I plan on removing opt->invert_final_result unless you guys thing it can
be used for something else.
This is my first crack at it, and I would like to get some feedback on
the direction I've taken. I plan on adding test cases before I submit
the final patch.
Thanks for reviewing.
-Bart
----8<----
>From e584ed4399e24bcd21991d1a9edc5e33f22a4f0c Mon Sep 17 00:00:00 2001
From: Bart Trojanowski <bart@jukie.net>
Date: Fri, 21 Sep 2007 11:24:37 -0400
Subject: [PATCH] Add git-rev-list --not-(author|committer|grep)!=pattern
This patch adds the concept of negative grep patterns, which only
generate a grepping hit when the pattern did not match any lines
in the whole file (or buffer).
This makes it possible to run
git-rev-list --grep=foo --not-committer=bar
git-rev-list --all-match --grep=foo --not-author=bar
As with regular git-rev-list filtering, the default is an inclusive
filter. So the first line matches those revisions that either have
foo in the message, or do not have bar as the comitter. The second
form locates all revisions that contain foo in the message, but not
bar as the author.
The --not-* options have short forms:
git-rev-list --grep!=bar
git-rev-list --committer!=bar
git-rev-list --author!=bar
...which is provided by a invertible_prefix_cmp() util function which
could be used for other --not-*=<arg> options in the future.
Signed-off-by: Bart Trojanowski <bart@jukie.net>
---
Documentation/git-rev-list.txt | 20 ++++++++++++
builtin-grep.c | 16 +++++-----
git-compat-util.h | 42 +++++++++++++++++++++++++
grep.c | 65 +++++++++++++++++++++++++++++++++++----
grep.h | 10 +++++-
revision.c | 36 +++++++++++++++-------
6 files changed, 160 insertions(+), 29 deletions(-)
diff --git a/Documentation/git-rev-list.txt b/Documentation/git-rev-list.txt
index 7cd0e89..326495d 100644
--- a/Documentation/git-rev-list.txt
+++ b/Documentation/git-rev-list.txt
@@ -27,6 +27,8 @@ SYNOPSIS
[ \--cherry-pick ]
[ \--encoding[=<encoding>] ]
[ \--(author|committer|grep)=<pattern> ]
+ [ \--not-(author|committer|grep)=<pattern> ]
+ [ \--all-match ]
[ \--regexp-ignore-case | \-i ]
[ \--extended-regexp | \-E ]
[ \--date={local|relative|default|iso|rfc|short} ]
@@ -229,6 +231,18 @@ limiting may be applied.
Limit the commits output to ones with log message that
matches the specified pattern (regular expression).
+--not-author='pattern', --not-committer='pattern', --not-grep='pattern'::
+
+ When filtering the commits based on log message (`--not-grep`)
+ or people (`--not-author` and `--not-committer`), show commits that
+ do not match the criteria specified.
+
+--all-match::
+
+ Display commits which match all criteria; default is to show
+ commits that match at least one of `--grep`, `--committer`, and
+ `--author`.
+
-i, --regexp-ignore-case::
Match the regexp limiting patterns without regard to letters case.
@@ -238,6 +252,12 @@ limiting may be applied.
Consider the limiting patterns to be extended regular expressions
instead of the default basic regular expressions.
+--invert-match::
+
+ When filtering the commits based on log message (`--grep`) or people
+ (`--author` and `--committer`), show commits that do not match the
+ criteria.
+
--remove-empty::
Stop when a given path disappears from the tree.
diff --git a/builtin-grep.c b/builtin-grep.c
index c7b45c4..90bc6f8 100644
--- a/builtin-grep.c
+++ b/builtin-grep.c
@@ -547,7 +547,7 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
}
if (!strcmp("-v", arg) ||
!strcmp("--invert-match", arg)) {
- opt.invert = 1;
+ opt.invert_line_match = 1;
continue;
}
if (!strcmp("-E", arg) ||
@@ -651,7 +651,7 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
continue;
append_grep_pattern(&opt, xstrdup(buf),
argv[1], ++lno,
- GREP_PATTERN);
+ GREP_PATTERN, 0);
}
fclose(patterns);
argv++;
@@ -660,24 +660,24 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
}
if (!strcmp("--not", arg)) {
append_grep_pattern(&opt, arg, "command line", 0,
- GREP_NOT);
+ GREP_NOT, 0);
continue;
}
if (!strcmp("--and", arg)) {
append_grep_pattern(&opt, arg, "command line", 0,
- GREP_AND);
+ GREP_AND, 0);
continue;
}
if (!strcmp("--or", arg))
continue; /* no-op */
if (!strcmp("(", arg)) {
append_grep_pattern(&opt, arg, "command line", 0,
- GREP_OPEN_PAREN);
+ GREP_OPEN_PAREN, 0);
continue;
}
if (!strcmp(")", arg)) {
append_grep_pattern(&opt, arg, "command line", 0,
- GREP_CLOSE_PAREN);
+ GREP_CLOSE_PAREN, 0);
continue;
}
if (!strcmp("--all-match", arg)) {
@@ -688,7 +688,7 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
if (1 < argc) {
append_grep_pattern(&opt, argv[1],
"-e option", 0,
- GREP_PATTERN);
+ GREP_PATTERN, 0);
argv++;
argc--;
continue;
@@ -711,7 +711,7 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
/* First unrecognized non-option token */
if (!opt.pattern_list) {
append_grep_pattern(&opt, arg, "command line", 0,
- GREP_PATTERN);
+ GREP_PATTERN, 0);
break;
}
else {
diff --git a/git-compat-util.h b/git-compat-util.h
index 1bfbdeb..db1c9d4 100644
--- a/git-compat-util.h
+++ b/git-compat-util.h
@@ -362,6 +362,48 @@ static inline int prefixcmp(const char *str, const char *prefix)
return strncmp(str, prefix, strlen(prefix));
}
+static inline int invertible_prefix_cmp(const char *str, const char *prefix,
+ const char **pattern, int *inverted)
+{
+ int prefix_len = strlen(prefix);
+ int rc;
+
+ *inverted = 0;
+ *pattern = str + prefix_len;
+
+ rc = strncmp(str, prefix, prefix_len-1);
+ if (rc)
+ goto try_alternate_form;
+
+ if (prefix[prefix_len-1] != '=')
+ return strncmp(str, prefix, strlen(prefix));
+
+ if (str[prefix_len-1] == '=')
+ return 0;
+
+ if (str[prefix_len-1] != '!'
+ || str[prefix_len] != '=')
+ return 1;
+
+ *inverted = 1;
+ (*pattern) ++;
+ return 0;
+
+try_alternate_form:
+ if (prefix[0]!='-' || prefix[1]!='-')
+ return rc;
+
+ if (strncmp (str, "--not-", 6))
+ return rc;
+
+ if (strncmp (str+6, prefix+2, prefix_len-2))
+ return rc;
+
+ *inverted = 1;
+ (*pattern) += 4;
+ return 0;
+}
+
static inline int strtoul_ui(char const *s, int base, unsigned int *result)
{
unsigned long ul;
diff --git a/grep.c b/grep.c
index f67d671..877f0ed 100644
--- a/grep.c
+++ b/grep.c
@@ -3,12 +3,16 @@
#include "xdiff-interface.h"
void append_grep_pattern(struct grep_opt *opt, const char *pat,
- const char *origin, int no, enum grep_pat_token t)
+ const char *origin, int no, enum grep_pat_token t,
+ int is_negative)
{
struct grep_pat *p = xcalloc(1, sizeof(*p));
p->pattern = pat;
p->origin = origin;
p->no = no;
+ p->is_negative = !!is_negative;
+ if (p->is_negative)
+ opt->extended = 1;
p->token = t;
*opt->pattern_tail = p;
opt->pattern_tail = &p->next;
@@ -253,10 +257,30 @@ static int match_one_pattern(struct grep_opt *opt, struct grep_pat *p, char *bol
int at_true_bol = 1;
regmatch_t pmatch[10];
+ if (ctx == GREP_CONTEXT_FINALIZE)
+ return p->is_negative
+ ? !p->did_match
+ : p->did_match;
+
+ if (ctx == GREP_CONTEXT_INITIALIZE) {
+ p->did_match = 0;
+ return 0;
+ }
+
if ((p->token != GREP_PATTERN) &&
((p->token == GREP_PATTERN_HEAD) != (ctx == GREP_CONTEXT_HEAD)))
return 0;
+ /* Shallow searches can stop matching lines early and just reuse the
+ * previous match result because we are only interested if there was
+ * at least one match. For positive matches, we return 1 because once
+ * we match the result will always be successful; conversely, for
+ * negative matches once the base patter was found the result will
+ * always be 0.
+ */
+ if (opt->shallow && p->did_match)
+ return !p->is_negative;
+
again:
if (!opt->fixed) {
regex_t *exp = &p->regexp;
@@ -298,6 +322,15 @@ static int match_one_pattern(struct grep_opt *opt, struct grep_pat *p, char *bol
goto again;
}
}
+
+ if (hit)
+ p->did_match = 1;
+
+ /* a negative pattern cannot match until the very end when we know
+ * there have been no matches on any of the lines */
+ if (p->is_negative)
+ return 0;
+
return hit;
}
@@ -382,6 +415,10 @@ static int grep_buffer_1(struct grep_opt *opt, const char *name,
unsigned count = 0;
enum grep_context ctx = GREP_CONTEXT_HEAD;
+ /* Reset flags in all grep_pat objects
+ */
+ match_line (opt, NULL, NULL, GREP_CONTEXT_INITIALIZE, collect_hits);
+
if (buffer_is_binary(buf, size)) {
switch (opt->binary) {
case GREP_BINARY_DEFAULT:
@@ -414,6 +451,14 @@ static int grep_buffer_1(struct grep_opt *opt, const char *name,
hit = match_line(opt, bol, eol, ctx, collect_hits);
*eol = ch;
+ /* on the last line we can determine the hit of negative
+ * patterns
+ */
+ if (left < 2) {
+ hit = match_line (opt, NULL, NULL, GREP_CONTEXT_FINALIZE, collect_hits);
+ }
+
+
if (collect_hits)
goto next_line;
@@ -421,7 +466,7 @@ static int grep_buffer_1(struct grep_opt *opt, const char *name,
* that do not have either, so inversion should
* be done outside.
*/
- if (opt->invert)
+ if (opt->invert_line_match)
hit = !hit;
if (opt->unmatch_name_only) {
if (hit)
@@ -545,12 +590,16 @@ static int chk_hit_marker(struct grep_expr *x)
int grep_buffer(struct grep_opt *opt, const char *name, char *buf, unsigned long size)
{
+ int result;
+
/*
* we do not have to do the two-pass grep when we do not check
* buffer-wide "all-match".
*/
- if (!opt->all_match)
- return grep_buffer_1(opt, name, buf, size, 0);
+ if (!opt->all_match) {
+ result = grep_buffer_1(opt, name, buf, size, 0);
+ goto done;
+ }
/* Otherwise the toplevel "or" terms hit a bit differently.
* We first clear hit markers from them.
@@ -558,8 +607,10 @@ int grep_buffer(struct grep_opt *opt, const char *name, char *buf, unsigned long
clr_hit_marker(opt->pattern_expression);
grep_buffer_1(opt, name, buf, size, 1);
- if (!chk_hit_marker(opt->pattern_expression))
- return 0;
+ result = 0;
+ if (chk_hit_marker(opt->pattern_expression))
+ result = grep_buffer_1(opt, name, buf, size, 0);
- return grep_buffer_1(opt, name, buf, size, 0);
+done:
+ return opt->invert_final_result ? !result : result;
}
diff --git a/grep.h b/grep.h
index d252dd2..adb5b94 100644
--- a/grep.h
+++ b/grep.h
@@ -13,14 +13,18 @@ enum grep_pat_token {
};
enum grep_context {
+ GREP_CONTEXT_INITIALIZE,
GREP_CONTEXT_HEAD,
GREP_CONTEXT_BODY,
+ GREP_CONTEXT_FINALIZE,
};
struct grep_pat {
struct grep_pat *next;
const char *origin;
int no;
+ unsigned is_negative:1;
+ unsigned did_match:1;
enum grep_pat_token token;
const char *pattern;
regex_t regexp;
@@ -53,8 +57,10 @@ struct grep_opt {
int prefix_length;
regex_t regexp;
unsigned linenum:1;
- unsigned invert:1;
+ unsigned invert_line_match:1;
+ unsigned invert_final_result:1;
unsigned status_only:1;
+ unsigned shallow:1; // stop testing patterns after hit
unsigned name_only:1;
unsigned unmatch_name_only:1;
unsigned count:1;
@@ -73,7 +79,7 @@ struct grep_opt {
unsigned post_context;
};
-extern void append_grep_pattern(struct grep_opt *opt, const char *pat, const char *origin, int no, enum grep_pat_token t);
+extern void append_grep_pattern(struct grep_opt *opt, const char *pat, const char *origin, int no, enum grep_pat_token t, int is_negative);
extern void compile_grep_patterns(struct grep_opt *opt);
extern void free_grep_patterns(struct grep_opt *opt);
extern int grep_buffer(struct grep_opt *opt, const char *name, char *buf, unsigned long size);
diff --git a/revision.c b/revision.c
index 33d092c..721ef52 100644
--- a/revision.c
+++ b/revision.c
@@ -827,20 +827,23 @@ int handle_revision_arg(const char *arg, struct rev_info *revs,
return 0;
}
-static void add_grep(struct rev_info *revs, const char *ptn, enum grep_pat_token what)
+static void add_grep(struct rev_info *revs, const char *ptn, int is_negative,
+ enum grep_pat_token what)
{
if (!revs->grep_filter) {
struct grep_opt *opt = xcalloc(1, sizeof(*opt));
opt->status_only = 1;
+ opt->shallow = 1;
opt->pattern_tail = &(opt->pattern_list);
opt->regflags = REG_NEWLINE;
revs->grep_filter = opt;
}
append_grep_pattern(revs->grep_filter, ptn,
- "command line", 0, what);
+ "command line", 0, what, is_negative);
}
-static void add_header_grep(struct rev_info *revs, const char *field, const char *pattern)
+static void add_header_grep(struct rev_info *revs, const char *field,
+ const char *pattern, int is_negative)
{
char *pat;
const char *prefix;
@@ -855,12 +858,13 @@ static void add_header_grep(struct rev_info *revs, const char *field, const char
pattern++;
}
sprintf(pat, "^%s %s%s", field, prefix, pattern);
- add_grep(revs, pat, GREP_PATTERN_HEAD);
+ add_grep(revs, pat, is_negative, GREP_PATTERN_HEAD);
}
-static void add_message_grep(struct rev_info *revs, const char *pattern)
+static void add_message_grep(struct rev_info *revs, const char *pattern,
+ int is_negative)
{
- add_grep(revs, pattern, GREP_PATTERN_BODY);
+ add_grep(revs, pattern, is_negative, GREP_PATTERN_BODY);
}
static void add_ignore_packed(struct rev_info *revs, const char *name)
@@ -887,6 +891,8 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch
int left = 1;
int all_match = 0;
int regflags = 0;
+ int inverted;
+ const char *pattern;
/* First, search for "--" */
seen_dashdash = 0;
@@ -1160,16 +1166,21 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch
/*
* Grepping the commit log
*/
- if (!prefixcmp(arg, "--author=")) {
- add_header_grep(revs, "author", arg+9);
+ if (!invertible_prefix_cmp(arg, "--author=",
+ &pattern, &inverted)) {
+ add_header_grep(revs, "author", pattern,
+ inverted);
continue;
}
- if (!prefixcmp(arg, "--committer=")) {
- add_header_grep(revs, "committer", arg+12);
+ if (!invertible_prefix_cmp(arg, "--committer=",
+ &pattern, &inverted)) {
+ add_header_grep(revs, "committer", pattern,
+ inverted);
continue;
}
- if (!prefixcmp(arg, "--grep=")) {
- add_message_grep(revs, arg+7);
+ if (!invertible_prefix_cmp (arg, "--grep=",
+ &pattern, &inverted)) {
+ add_message_grep(revs, pattern, inverted);
continue;
}
if (!strcmp(arg, "--extended-regexp") ||
@@ -1385,6 +1396,7 @@ static int commit_match(struct commit *commit, struct rev_info *opt)
{
if (!opt->grep_filter)
return 1;
+
return grep_buffer(opt->grep_filter,
NULL, /* we say nothing, not even filename */
commit->buffer, strlen(commit->buffer));
--
1.5.3.1.154.g734e65
^ permalink raw reply related
* [PATCH 5/5] git-merge: add --ff and --no-ff options
From: Lars Hjemli @ 2007-09-22 0:33 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <1190421186-21784-5-git-send-email-hjemli@gmail.com>
These new options can be used to control the policy for fast-forward
merges: --ff allows it (this is the default) while --no-ff will create
a merge commit.
Signed-off-by: Lars Hjemli <hjemli@gmail.com>
---
Documentation/merge-options.txt | 9 +++++++++
git-merge.sh | 20 +++++++++++++++-----
t/t7600-merge.sh | 18 ++++++++++++++++++
3 files changed, 42 insertions(+), 5 deletions(-)
diff --git a/Documentation/merge-options.txt b/Documentation/merge-options.txt
index 9be90b5..b6c4dc4 100644
--- a/Documentation/merge-options.txt
+++ b/Documentation/merge-options.txt
@@ -23,6 +23,15 @@
top of the current branch whose effect is the same as
merging another branch (or more in case of an octopus).
+--no-ff::
+ Generate a merge commit even if the merge resolved as a
+ fast-forward.
+
+--ff::
+ Do not generate a merge commit if the merge resolved as
+ a fast-forward, only update the branch pointer. This is
+ the default behavior of git-merge.
+
-s <strategy>, \--strategy=<strategy>::
Use the given merge strategy; can be supplied more than
once to specify them in the order they should be tried.
diff --git a/git-merge.sh b/git-merge.sh
index 73ff130..daa95a1 100755
--- a/git-merge.sh
+++ b/git-merge.sh
@@ -3,7 +3,7 @@
# Copyright (c) 2005 Junio C Hamano
#
-USAGE='[-n] [--summary] [--[no-]commit] [--squash] [-s <strategy>] [-m=<merge-message>] <commit>+'
+USAGE='[-n] [--summary] [--[no-]commit] [--squash] [--[no-]ff] -s <strategy>] [-m=<merge-message>] <commit>+'
SUBDIRECTORY_OK=Yes
. git-sh-setup
@@ -127,11 +127,15 @@ parse_option () {
--summary)
show_diffstat=t ;;
--sq|--squ|--squa|--squas|--squash)
- squash=t no_commit=t ;;
+ allow_fast_forward=t squash=t no_commit=t ;;
--c|--co|--com|--comm|--commi|--commit)
- squash= no_commit= ;;
+ allow_fast_forward=t squash= no_commit= ;;
--no-c|--no-co|--no-com|--no-comm|--no-commi|--no-commit)
- squash= no_commit=t ;;
+ allow_fast_forward=t squash= no_commit=t ;;
+ --ff)
+ allow_fast_forward=t squash= no_commit= ;;
+ --no-ff)
+ allow_fast_forward=false squash= no_commit= ;;
-s=*|--s=*|--st=*|--str=*|--stra=*|--strat=*|--strate=*|\
--strateg=*|--strategy=*|\
-s|--s|--st|--str|--stra|--strat|--strate|--strateg|--strategy)
@@ -470,7 +474,13 @@ done
# auto resolved the merge cleanly.
if test '' != "$result_tree"
then
- parents=$(git show-branch --independent "$head" "$@" | sed -e 's/^/-p /')
+ if test "$allow_fast_forward" = "t"
+ then
+ parents=$(git show-branch --independent "$head" "$@")
+ else
+ parents=$(git rev-parse "$head" "$@")
+ fi
+ parents=$(echo "$parents" | sed -e 's/^/-p /')
result_commit=$(printf '%s\n' "$merge_msg" | git commit-tree $result_tree $parents) || exit
finish "$result_commit" "Merge made by $wt_strategy."
dropsave
diff --git a/t/t7600-merge.sh b/t/t7600-merge.sh
index 75b0ee4..6e16a28 100755
--- a/t/t7600-merge.sh
+++ b/t/t7600-merge.sh
@@ -393,4 +393,22 @@ test_expect_success 'merge c1 with c2 (override --squash)' '
test "$c2" = "$(git rev-parse HEAD^2)"
'
+test_expect_success 'merge c0 with c1 (no-ff)' '
+ git reset --hard c0 &&
+ git merge --no-ff c1 &&
+ test "$c0" = "$(git rev-parse HEAD^1)" &&
+ test "$c1" = "$(git rev-parse HEAD^2)"
+'
+
+test_debug 'gitk --all'
+
+test_expect_success 'merge c0 with c1 (ff overrides no-ff)' '
+ git reset --hard c0 &&
+ git config branch.master.mergeoptions "--no-ff" &&
+ git merge --ff c1 &&
+ test "$c1" = "$(git rev-parse HEAD)"
+'
+
+test_debug 'gitk --all'
+
test_done
--
1.5.3.2.82.g75c8d
^ permalink raw reply related
* [PATCH 1/5] Add test-script for git-merge porcelain
From: Lars Hjemli @ 2007-09-22 0:33 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <1190421186-21784-1-git-send-email-hjemli@gmail.com>
This test-script tries to excercise the porcelainish aspects of git-merge.
Signed-off-by: Lars Hjemli <hjemli@gmail.com>
---
t/t7600-merge.sh | 317 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 317 insertions(+), 0 deletions(-)
create mode 100755 t/t7600-merge.sh
diff --git a/t/t7600-merge.sh b/t/t7600-merge.sh
new file mode 100755
index 0000000..9e58636
--- /dev/null
+++ b/t/t7600-merge.sh
@@ -0,0 +1,317 @@
+#!/bin/sh
+#
+# Copyright (c) 2007 Lars Hjemli
+#
+
+test_description='git-merge
+
+Testing basic merge operations/option parsing.'
+
+. ./test-lib.sh
+
+test_expect_success 'setup' '
+ echo "
+1
+2
+3
+4
+5
+6
+7
+8
+9
+" > file &&
+ git add file &&
+ git commit -m "commit 0" &&
+ git tag c0 &&
+ c0=$(git rev-parse HEAD) &&
+ echo "
+1 X
+2
+3
+4
+5
+6
+7
+8
+9
+" > file &&
+ git add file &&
+ git commit -m "commit 1" &&
+ git tag c1 &&
+ c1=$(git rev-parse HEAD) &&
+ git reset --hard "$c0" &&
+ echo "
+1
+2
+3
+4
+5 X
+6
+7
+8
+9
+" > file &&
+ git add file &&
+ git commit -m "commit 2" &&
+ git tag c2 &&
+ c2=$(git rev-parse HEAD) &&
+ git reset --hard "$c0" &&
+ echo "
+1
+2
+3
+4
+5
+6
+7
+8
+9 X
+" > file &&
+ git add file &&
+ git commit -m "commit 3" &&
+ git tag c3 &&
+ c3=$(git rev-parse HEAD)
+ git reset --hard "$c0"
+'
+
+test_debug 'gitk --all'
+
+test_expect_success 'test option parsing' '
+ if git merge -$ c1
+ then
+ echo "[OOPS] -$ accepted"
+ false
+ fi &&
+ if git merge --no-such c1
+ then
+ echo "[OOPS] --no-such accepted"
+ false
+ fi &&
+ if git merge -s foobar c1
+ then
+ echo "[OOPS] -s foobar accepted"
+ false
+ fi &&
+ if git merge -s=foobar c1
+ then
+ echo "[OOPS] -s=foobar accepted"
+ false
+ fi &&
+ if git merge -m
+ then
+ echo "[OOPS] missing commit msg accepted"
+ false
+ fi &&
+ if git merge
+ then
+ echo "[OOPS] missing commit references accepted"
+ false
+ fi
+'
+
+test_expect_success 'merge c0 with c1' '
+ git reset --hard c0 &&
+ git merge c1 &&
+ test "$c1" = "$(git rev-parse HEAD)"
+'
+
+test_debug 'gitk --all'
+
+test_expect_success 'verify merge result' '
+ echo "
+1 X
+2
+3
+4
+5
+6
+7
+8
+9
+" > result.1 &&
+ cmp -s file result.1
+'
+
+test_expect_success 'merge c1 with c2' '
+ git reset --hard c1 &&
+ git merge c2 &&
+ test "$c1" = "$(git rev-parse HEAD^1)" &&
+ test "$c2" = "$(git rev-parse HEAD^2)"
+'
+
+test_debug 'gitk --all'
+
+test_expect_success 'verify merge result' '
+ echo "
+1 X
+2
+3
+4
+5 X
+6
+7
+8
+9
+" > result.1-5 &&
+ cmp -s file result.1-5
+'
+
+test_expect_success 'merge c1 with c2 and c3' '
+ git reset --hard c1 &&
+ git merge c2 c3 &&
+ test "$c1" = "$(git rev-parse HEAD^1)" &&
+ test "$c2" = "$(git rev-parse HEAD^2)" &&
+ test "$c3" = "$(git rev-parse HEAD^3)"
+'
+
+test_debug 'gitk --all'
+
+test_expect_success 'verify merge result' '
+ echo "
+1 X
+2
+3
+4
+5 X
+6
+7
+8
+9 X
+" > result.1-5-9 &&
+ cmp -s file result.1-5-9
+'
+
+test_expect_success 'merge c0 with c1 (no-commit)' '
+ git reset --hard c0 &&
+ git merge --no-commit c1 &&
+ if test "$c1" != "$(git rev-parse HEAD)"
+ then
+ echo "[OOPS] fast-forward not performed"
+ false
+ fi &&
+ if ! cmp -s file result.1
+ then
+ echo "[OOPS] merge result is wrong"
+ false
+ fi
+'
+
+test_debug 'gitk --all'
+
+test_expect_success 'merge c1 with c2 (no-commit)' '
+ git reset --hard c1 &&
+ git merge --no-commit c2 &&
+ if test "$c1" != "$(git rev-parse HEAD)"
+ then
+ echo "[OOPS] HEAD changed"
+ false
+ fi &&
+ if ! cmp -s file result.1-5
+ then
+ echo "[OOPS] merge result is wrong"
+ false
+ fi &&
+ if test "$c2" != "$(cat .git/MERGE_HEAD)"
+ then
+ echo "[OOPS] MERGE_HEAD is wrong"
+ false
+ fi
+'
+
+test_debug 'gitk --all'
+
+test_expect_success 'merge c1 with c2 and c3 (no-commit)' '
+ git reset --hard c1 &&
+ git merge --no-commit c2 c3 &&
+ if test "$c1" != "$(git rev-parse HEAD)"
+ then
+ echo "[OOPS] HEAD changed"
+ false
+ fi &&
+ if ! cmp -s file result.1-5-9
+ then
+ echo "[OOPS] merge result is wrong"
+ false
+ fi &&
+ if ! grep -q "$c2" .git/MERGE_HEAD
+ then
+ echo "[OOPS] c2 not in MERGE_HEAD"
+ false
+ fi &&
+ if ! grep -q "$c3" .git/MERGE_HEAD
+ then
+ echo "[OOPS] c3 not in MERGE_HEAD"
+ false
+ fi
+'
+
+test_debug 'gitk --all'
+
+test_expect_success 'merge c0 with c1 (squash)' '
+ git reset --hard c0 &&
+ git merge --squash c1 &&
+ if test "$c0" != "$(git rev-parse HEAD)"
+ then
+ echo "[OOPS] HEAD changed"
+ false
+ fi &&
+ if ! cmp -s file result.1
+ then
+ echo "[OOPS] merge result is wrong"
+ false
+ fi &&
+ if test -f .git/MERGE_HEAD
+ then
+ echo "[OOPS] MERGE_HEAD exists"
+ false
+ fi
+'
+
+test_debug 'gitk --all'
+
+test_expect_success 'merge c1 with c2 (squash)' '
+ git reset --hard c1 &&
+ git merge --squash c2 &&
+ if test "$c1" != "$(git rev-parse HEAD)"
+ then
+ echo "[OOPS] new commit created"
+ false
+ fi &&
+ if ! cmp -s file result.1-5
+ then
+ echo "[OOPS] merge result is wrong"
+ false
+ fi &&
+ if test -f .git/MERGE_HEAD
+ then
+ echo "[OOPS] MERGE_HEAD exists"
+ false
+ fi
+'
+
+test_debug 'gitk --all'
+
+test_expect_success 'merge c1 with c2 and c3 (squash)' '
+ git reset --hard c1 &&
+ git merge --squash c2 c3 &&
+ if test "$c1" != "$(git rev-parse HEAD)"
+ then
+ echo "[OOPS] HEAD changed"
+ false
+ fi &&
+ if ! cmp -s file result.1-5-9
+ then
+ echo "[OOPS] merge result is wrong"
+ false
+ fi &&
+ if test -f .git/MERGE_HEAD
+ then
+ echo "[OOPS] MERGE_HEAD exists"
+ false
+ fi
+'
+
+test_debug 'gitk --all'
+
+test_done
--
1.5.3.2.82.g75c8d
^ permalink raw reply related
* [PATCH 3/5] git-merge: add support for branch.<name>.mergeoptions
From: Lars Hjemli @ 2007-09-22 0:33 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <1190421186-21784-3-git-send-email-hjemli@gmail.com>
This enables per branch configuration of merge options. Currently, the most
useful options to specify per branch are --squash, --summary/--no-summary
and possibly --strategy, but all options are supported.
Note: Options containing whitespace will _not_ be handled correctly. Luckily,
the only option which can include whitespace is --message and it doesn't
make much sense to give that option a default value.
Signed-off-by: Lars Hjemli <hjemli@gmail.com>
---
Documentation/config.txt | 6 ++++
Documentation/git-merge.txt | 4 +++
git-merge.sh | 16 +++++++++++
t/t7600-merge.sh | 63 +++++++++++++++++++++++++++++++++++++++++++
4 files changed, 89 insertions(+), 0 deletions(-)
diff --git a/Documentation/config.txt b/Documentation/config.txt
index 015910f..d3c25f3 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -337,6 +337,12 @@ branch.<name>.merge::
branch.<name>.merge to the desired branch, and use the special setting
`.` (a period) for branch.<name>.remote.
+branch.<name>.mergeoptions::
+ Sets default options for merging into branch <name>. The syntax and
+ supported options are equal to that of gitlink:git-merge[1], but
+ option values containing whitespace characters are currently not
+ supported.
+
clean.requireForce::
A boolean to make git-clean do nothing unless given -f or -n. Defaults
to false.
diff --git a/Documentation/git-merge.txt b/Documentation/git-merge.txt
index 144bc16..b1771a1 100644
--- a/Documentation/git-merge.txt
+++ b/Documentation/git-merge.txt
@@ -58,6 +58,10 @@ merge.verbosity::
above outputs debugging information. The default is level 2.
Can be overriden by 'GIT_MERGE_VERBOSITY' environment variable.
+branch.<name>.mergeoptions::
+ Sets default options for merging into branch <name>. The syntax and
+ supported options are equal to that of git-merge, but option values
+ containing whitespace characters are currently not supported.
HOW MERGE WORKS
---------------
diff --git a/git-merge.sh b/git-merge.sh
index a3ef676..39a24ac 100755
--- a/git-merge.sh
+++ b/git-merge.sh
@@ -168,9 +168,25 @@ parse_option () {
args_left="$#"
}
+parse_config () {
+ while test "$#" != "0"
+ do
+ parse_option "$@" || usage
+ while test $args_left -lt $#
+ do
+ shift
+ done
+ done
+}
+
case "$#" in 0) usage ;; esac
have_message=
+
+branch=$(git-symbolic-ref HEAD | sed -e 's|^refs/heads/||')
+mergeopts=$(git config "branch.$branch.mergeoptions")
+parse_config $mergeopts
+
while parse_option "$@"
do
while test $args_left -lt $#
diff --git a/t/t7600-merge.sh b/t/t7600-merge.sh
index 9e58636..e99b5d9 100755
--- a/t/t7600-merge.sh
+++ b/t/t7600-merge.sh
@@ -314,4 +314,67 @@ test_expect_success 'merge c1 with c2 and c3 (squash)' '
test_debug 'gitk --all'
+test_expect_success 'merge c1 with c2 (no-commit in config)' '
+ git reset --hard c1 &&
+ git config branch.master.mergeoptions "--no-commit" &&
+ git merge c2 &&
+ if test "$c1" != "$(git rev-parse HEAD)"
+ then
+ echo "[OOPS] HEAD changed"
+ false
+ fi &&
+ if ! cmp -s file result.1-5
+ then
+ echo "[OOPS] merge result is wrong"
+ false
+ fi &&
+ if test "$c2" != "$(cat .git/MERGE_HEAD)"
+ then
+ echo "[OOPS] MERGE_HEAD is wrong"
+ false
+ fi
+'
+
+test_expect_success 'merge c1 with c2 (squash in config)' '
+ git reset --hard c1 &&
+ git config branch.master.mergeoptions "--squash" &&
+ git merge c2 &&
+ if test "$c1" != "$(git rev-parse HEAD)"
+ then
+ echo "[OOPS] new commit created"
+ false
+ fi &&
+ if ! cmp -s file result.1-5
+ then
+ echo "[OOPS] merge result is wrong"
+ false
+ fi &&
+ if test -f .git/MERGE_HEAD
+ then
+ echo "[OOPS] MERGE_HEAD exists"
+ false
+ fi
+'
+
+test_expect_success 'override config option -n' '
+ git reset --hard c1 &&
+ git config branch.master.mergeoptions "-n" &&
+ git merge --summary c2 >diffstat.txt &&
+ if ! grep -e "^ file | \+2 +-$" diffstat.txt
+ then
+ echo "[OOPS] diffstat was not generated"
+ fi
+'
+
+test_expect_success 'override config option --summary' '
+ git reset --hard c1 &&
+ git config branch.master.mergeoptions "--summary" &&
+ git merge -n c2 >diffstat.txt &&
+ if grep -e "^ file | \+2 +-$" diffstat.txt
+ then
+ echo "[OOPS] diffstat was generated"
+ false
+ fi
+'
+
test_done
--
1.5.3.2.82.g75c8d
^ permalink raw reply related
* [PATCH 4/5] git-merge: add support for --commit
From: Lars Hjemli @ 2007-09-22 0:33 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <1190421186-21784-4-git-send-email-hjemli@gmail.com>
This option can be used to override --no-commit and --squash. The change
also introduces slightly different behavior for --no-commit: when specified,
it explicitly overrides --squash.
Signed-off-by: Lars Hjemli <hjemli@gmail.com>
---
Documentation/merge-options.txt | 4 ++++
git-merge.sh | 6 ++++--
t/t7600-merge.sh | 16 ++++++++++++++++
3 files changed, 24 insertions(+), 2 deletions(-)
diff --git a/Documentation/merge-options.txt b/Documentation/merge-options.txt
index d64c259..9be90b5 100644
--- a/Documentation/merge-options.txt
+++ b/Documentation/merge-options.txt
@@ -10,6 +10,10 @@
not autocommit, to give the user a chance to inspect and
further tweak the merge result before committing.
+--commit::
+ Perform the merge and commit the result. This option can
+ be used to override --no-commit and --squash.
+
--squash::
Produce the working tree and index state as if a real
merge happened, but do not actually make a commit or
diff --git a/git-merge.sh b/git-merge.sh
index 39a24ac..73ff130 100755
--- a/git-merge.sh
+++ b/git-merge.sh
@@ -3,7 +3,7 @@
# Copyright (c) 2005 Junio C Hamano
#
-USAGE='[-n] [--summary] [--no-commit] [--squash] [-s <strategy>] [-m=<merge-message>] <commit>+'
+USAGE='[-n] [--summary] [--[no-]commit] [--squash] [-s <strategy>] [-m=<merge-message>] <commit>+'
SUBDIRECTORY_OK=Yes
. git-sh-setup
@@ -128,8 +128,10 @@ parse_option () {
show_diffstat=t ;;
--sq|--squ|--squa|--squas|--squash)
squash=t no_commit=t ;;
+ --c|--co|--com|--comm|--commi|--commit)
+ squash= no_commit= ;;
--no-c|--no-co|--no-com|--no-comm|--no-commi|--no-commit)
- no_commit=t ;;
+ squash= no_commit=t ;;
-s=*|--s=*|--st=*|--str=*|--stra=*|--strat=*|--strate=*|\
--strateg=*|--strategy=*|\
-s|--s|--st|--str|--stra|--strat|--strate|--strateg|--strategy)
diff --git a/t/t7600-merge.sh b/t/t7600-merge.sh
index e99b5d9..75b0ee4 100755
--- a/t/t7600-merge.sh
+++ b/t/t7600-merge.sh
@@ -377,4 +377,20 @@ test_expect_success 'override config option --summary' '
fi
'
+test_expect_success 'merge c1 with c2 (override --no-commit)' '
+ git reset --hard c1 &&
+ git config branch.master.mergeoptions "--no-commit" &&
+ git merge --commit c2 &&
+ test "$c1" = "$(git rev-parse HEAD^1)" &&
+ test "$c2" = "$(git rev-parse HEAD^2)"
+'
+
+test_expect_success 'merge c1 with c2 (override --squash)' '
+ git reset --hard c1 &&
+ git config branch.master.mergeoptions "--squash" &&
+ git merge --commit c2 &&
+ test "$c1" = "$(git rev-parse HEAD^1)" &&
+ test "$c2" = "$(git rev-parse HEAD^2)"
+'
+
test_done
--
1.5.3.2.82.g75c8d
^ permalink raw reply related
* [PATCH 2/5] git-merge: refactor option parsing
From: Lars Hjemli @ 2007-09-22 0:33 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
In-Reply-To: <1190421186-21784-2-git-send-email-hjemli@gmail.com>
Move the option parsing into a separate function as preparation for reuse
by the next commit.
Signed-off-by: Lars Hjemli <hjemli@gmail.com>
---
git-merge.sh | 20 ++++++++++++++------
1 files changed, 14 insertions(+), 6 deletions(-)
diff --git a/git-merge.sh b/git-merge.sh
index 3a01db0..a3ef676 100755
--- a/git-merge.sh
+++ b/git-merge.sh
@@ -119,11 +119,7 @@ merge_name () {
fi
}
-case "$#" in 0) usage ;; esac
-
-have_message=
-while case "$#" in 0) break ;; esac
-do
+parse_option () {
case "$1" in
-n|--n|--no|--no-|--no-s|--no-su|--no-sum|--no-summ|\
--no-summa|--no-summar|--no-summary)
@@ -166,9 +162,21 @@ do
have_message=t
;;
-*) usage ;;
- *) break ;;
+ *) return 1 ;;
esac
shift
+ args_left="$#"
+}
+
+case "$#" in 0) usage ;; esac
+
+have_message=
+while parse_option "$@"
+do
+ while test $args_left -lt $#
+ do
+ shift
+ done
done
if test -z "$show_diffstat"; then
--
1.5.3.2.82.g75c8d
^ permalink raw reply related
* [PATCH 0/5] per branch options for git-merge incl. --no-ff
From: Lars Hjemli @ 2007-09-22 0:33 UTC (permalink / raw)
To: Junio C Hamano; +Cc: git
This patch-series implements support for per branch configuration of
git-merge, using entries (branch.<name>.mergeoptions) in .git/config.
There is also a new option, --no-ff, which can be used to force git-merge
to create merge commits even when the merge was a fast-forward.
Finally, the new optiond --ff and --commit can be used to override
setting specified in .git/config.
Note: patch 1/5 is a resend of the testscript for git-merge, this time
with correct mode bits.
Shortlog:
Add test-script for git-merge porcelain
git-merge: refactor option parsing
git-merge: add support for branch.<name>.mergeoptions
git-merge: add support for --commit
git-merge: add --ff and --no-ff options
Diffstat:
Documentation/config.txt | 6 +
Documentation/git-merge.txt | 4 +
Documentation/merge-options.txt | 13 ++
git-merge.sh | 56 +++++-
t/t7600-merge.sh | 414 +++++++++++++++++++++++++++++++++++++++
5 files changed, 483 insertions(+), 10 deletions(-)
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox