author | Junio C Hamano <gitster@pobox.com> | |
Sun, 17 Aug 2008 17:53:57 +0000 (10:53 -0700) | ||
committer | Junio C Hamano <gitster@pobox.com> | |
Sun, 17 Aug 2008 17:53:57 +0000 (10:53 -0700) |
* ak/p4:
Utilise our new p4_read_pipe and p4_write_pipe wrappers
Add p4 read_pipe and write_pipe wrappers
Put in the two other configuration elements found in the source
Put some documentation in about the parameters that have been added
Move git-p4.syncFromOrigin into a configuration parameters section
Consistently use 'git-p4' for the configuration entries
If the user has configured various parameters, use them.
Switch to using 'p4_build_cmd'
If we are in verbose mode, output what we are about to run (or return)
Add a single command that will be used to construct the 'p4' command
Utilise the new 'p4_system' function.
Have a command that specifically invokes 'p4' (via system)
Utilise the new 'p4_read_pipe_lines' command
Create a specific version of the read_pipe_lines command for p4 invocations
Conflicts:
contrib/fast-import/git-p4
Utilise our new p4_read_pipe and p4_write_pipe wrappers
Add p4 read_pipe and write_pipe wrappers
Put in the two other configuration elements found in the source
Put some documentation in about the parameters that have been added
Move git-p4.syncFromOrigin into a configuration parameters section
Consistently use 'git-p4' for the configuration entries
If the user has configured various parameters, use them.
Switch to using 'p4_build_cmd'
If we are in verbose mode, output what we are about to run (or return)
Add a single command that will be used to construct the 'p4' command
Utilise the new 'p4_system' function.
Have a command that specifically invokes 'p4' (via system)
Utilise the new 'p4_read_pipe_lines' command
Create a specific version of the read_pipe_lines command for p4 invocations
Conflicts:
contrib/fast-import/git-p4
32 files changed:
index 8afb5b253160a9bbd3effeedf97f29e8e40625da..9e2e417ef7666eac1e0bbd518d2b22634969048a 100644 (file)
backwards compatible past these versions, set repack.useDeltaBaseOffset
to false or pack.indexVersion to 1, respectively.
+We used to prevent sample hook scripts shipped in templates/ from
+triggering by default by relying on the fact that we install them as
+unexecutable, but on some filesystems, this approach does not work.
+They are now shipped with ".sample" suffix. If you want to activate
+any of these samples as-is, rename them to drop the ".sample" suffix,
+instead of running "chmod +x" on them. For example, you can rename
+hooks/post-update.sample to hooks/post-update to enable the sample
+hook that runs update-server-info, in order to make repositories
+friendly to dumb protocols (i.e. HTTP).
+
GIT_CONFIG, which was only documented as affecting "git config", but
actually affected all git commands, now only affects "git config".
GIT_LOCAL_CONFIG, also only documented as affecting "git config" and
gangs.
* Sample hook scripts shipped in templates/ are now suffixed with
- *.sample. We used to prevent them from triggering by default by
- relying on the fact that we install them as unexecutable, but on
- some filesystems this approach does not work. Instead of running
- "chmod +x" on them, the users who want to activate these samples
- as-is can now rename them dropping *.sample suffix.
+ *.sample.
* perl's in-place edit (-i) does not work well without backup files on Windows;
some tests are rewritten to cope with this.
* git-diff --check now checks leftover merge conflict markers.
* "git-diff -p" learned to grab a better hunk header lines in
- Pascal/Delphi and Ruby source files, and also pays attention to
+ BibTex, Pascal/Delphi, and Ruby files and also pays attention to
chapter and part boundary in TeX documents.
* When remote side used to have branch 'foo' and git-fetch finds that now
---
exec >/var/tmp/1
-O=v1.6.0-rc2-21-g0bb3a0b
+O=v1.6.0-rc3
echo O=$(git describe refs/heads/master)
git shortlog --no-merges $O..refs/heads/master ^refs/heads/maint
index b8ec01c923a8bdb8614f5c5700a7fda603365e8b..676c39bb8436f35e1471b8dd50fd888ae1ac5c6b 100644 (file)
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
can be overridden by the `\--max-pack-size` option of
linkgit:git-repack[1].
+pager.<cmd>::
+ Allows to set your own pager preferences for each command, overriding
+ the default. If `\--pager` or `\--no-pager` is specified on the command
+ line, it takes precedence over this option.
+
pull.octopus::
The default merge strategy to use when pulling multiple branches
at once.
index c45c53ec2404725394563a9fba40f31cd314adb2..b9c6fac7483dbefba0afb60a76ac0362aa390a6d 100644 (file)
--- a/Documentation/git-am.txt
+++ b/Documentation/git-am.txt
--------
[verse]
'git am' [--signoff] [--keep] [--utf8 | --no-utf8]
- [--3way] [--interactive] [--binary]
+ [--3way] [--interactive]
[--whitespace=<option>] [-C<n>] [-p<n>]
[<mbox> | <Maildir>...]
'git am' (--skip | --resolved | --abort)
it is supposed to apply to, and we have those blobs
available locally.
--b::
---binary::
- Pass `--allow-binary-replacement` flag to 'git-apply'
- (see linkgit:git-apply[1]).
-
--whitespace=<option>::
This flag is passed to the 'git-apply' (see linkgit:git-apply[1])
program that applies
index 010d9e432231f41a179023df2e85610583b572cf..adb4ea7b1b6c70fb6fc2486487ef34ed280ec015 100644 (file)
to any configured headers, and may be used multiple times.
--cover-letter::
- Generate a cover letter template. You still have to fill in
- a description, but the shortlog and the diffstat will be
- generated for you.
+ In addition to the patches, generate a cover letter file
+ containing the shortlog and the overall diffstat. You can
+ fill in a description in the file before sending it out.
--suffix=.<sfx>::
Instead of using `.patch` as the suffix for generated
index 7d50d74cc9a945f0dd82b0c26509bf0392eff837..49e2296a24825b2ea3a0976ff9073e7b44e976d8 100644 (file)
SYNOPSIS
--------
[verse]
-'git stash' list
-'git stash' (show | apply | drop | pop ) [<stash>]
+'git stash' list [<options>]
+'git stash' (show | drop | pop ) [<stash>]
+'git stash' apply [--index] [<stash>]
'git stash' branch <branchname> [<stash>]
-'git stash' [save [<message>]]
+'git stash' [save [--keep-index] [<message>]]
'git stash' clear
+'git stash' create
DESCRIPTION
-----------
of the current working tree state. When no `<stash>` is given,
`stash@\{0}` is assumed. See also `apply`.
+create::
+
+ Create a stash (which is a regular commit object) and return its
+ object name, without storing it anywhere in the ref namespace.
+
DISCUSSION
----------
index d7b41142d2c843bc5460f03c73c609b1c53ff4a6..db16b0ca5b8146361a379de894a1394e0950fd38 100644 (file)
There are a few built-in patterns to make this easier, and `tex`
is one of them, so you do not have to write the above in your
configuration file (you still need to enable this with the
-attribute mechanism, via `.gitattributes`). Another built-in
-pattern is defined for `java` that defines a pattern suitable
-for program text in Java language.
+attribute mechanism, via `.gitattributes`). The following built in
+patterns are available:
+
+- `bibtex` suitable for files with BibTeX coded references.
+
+- `java` suitable for source code in the Java lanugage.
+
+- `pascal` suitable for source code in the Pascal/Delphi language.
+
+- `ruby` suitable for source code in the Ruby language.
+
+- `tex` suitable for source code for LaTeX documents.
Performing a three-way merge
index 49179b0a00fad1ecda1fdf0537ccbce77f5fc494..a417e592ac6a7ed72186dcfc241592ccdc25c9d2 100644 (file)
[NOTE]
If you plan to publish this repository to be accessed over http,
-you should do `chmod +x my-git.git/hooks/post-update` at this
-point. This makes sure that every time you push into this
+you should do `mv my-git.git/hooks/post-update.sample
+my-git.git/hooks/post-update` at this point.
+This makes sure that every time you push into this
repository, `git update-server-info` is run.
Your "public repository" is now ready to accept your changes.
If other people are pulling from your repository over dumb
transport protocols (HTTP), you need to keep this repository
'dumb transport friendly'. After `git init`,
-`$GIT_DIR/hooks/post-update` copied from the standard templates
-would contain a call to 'git-update-server-info' but the
-`post-update` hook itself is disabled by default -- enable it
-with `chmod +x post-update`. This makes sure 'git-update-server-info'
-keeps the necessary files up-to-date.
+`$GIT_DIR/hooks/post-update.sample` copied from the standard templates
+would contain a call to 'git-update-server-info'
+but you need to manually enable the hook with
+`mv post-update.sample post-update`. This makes sure
+'git-update-server-info' keeps the necessary files up-to-date.
3. Push into the public repository from your primary
repository.
index be847217814690f08f5ffeb8f4d508d0abfacf15..735cf07b20e17e29d96f701d97768ae610aea590 100644 (file)
--parents::
- Print the parents of the commit.
+ Print the parents of the commit. Also enables parent
+ rewriting, see 'History Simplification' below.
--children::
- Print the children of the commit.
+ Print the children of the commit. Also enables parent
+ rewriting, see 'History Simplification' below.
ifdef::git-rev-list[]
--timestamp::
o---x---a---a branch A
-----------------------------------------------------------------------
+
-you would get an output line this:
+you would get an output like this:
+
-----------------------------------------------------------------------
$ git rev-list --left-right --boundary --pretty=oneline A...B
This implies the '--topo-order' option by default, but the
'--date-order' option may also be specified.
+ifndef::git-rev-list[]
Diff Formatting
~~~~~~~~~~~~~~~
-t::
Show the tree objects in the diff output. This implies '-r'.
+endif::git-rev-list[]
Commit Limiting
~~~~~~~~~~~~~~~
Stop when a given path disappears from the tree.
---full-history::
-
- Show also parts of history irrelevant to current state of a given
- path. This turns off history simplification, which removed merges
- which didn't change anything at all at some child. It will still actually
- simplify away merges that didn't change anything at all into either
- child.
-
--no-merges::
Do not print commits with more than one parent.
Output uninteresting commits at the boundary, which are usually
not shown.
+--
+
+History Simplification
+~~~~~~~~~~~~~~~~~~~~~~
+
+When optional paths are given, 'git-rev-list' simplifies commits with
+various strategies, according to the options you have selected.
+
+Suppose you specified `foo` as the <paths>. We shall call commits
+that modify `foo` !TREESAME, and the rest TREESAME. (In a diff
+filtered for `foo`, they look different and equal, respectively.)
+
+In the following, we will always refer to the same example history to
+illustrate the differences between simplification settings. We assume
+that you are filtering for a file `foo` in this commit graph:
+-----------------------------------------------------------------------
+ .-A---M---N---O---P
+ / / / / /
+ I B C D E
+ \ / / / /
+ `-------------'
+-----------------------------------------------------------------------
+The horizontal line of history A--P is taken to be the first parent of
+each merge. The commits are:
+
+* `I` is the initial commit, in which `foo` exists with contents
+ "asdf", and a file `quux` exists with contents "quux". Initial
+ commits are compared to an empty tree, so `I` is !TREESAME.
+
+* In `A`, `foo` contains just "foo".
+
+* `B` contains the same change as `A`. Its merge `M` is trivial and
+ hence TREESAME to all parents.
+
+* `C` does not change `foo`, but its merge `N` changes it to "foobar",
+ so it is not TREESAME to any parent.
+
+* `D` sets `foo` to "baz". Its merge `O` combines the strings from
+ `N` and `D` to "foobarbaz"; i.e., it is not TREESAME to any parent.
+
+* `E` changes `quux` to "xyzzy", and its merge `P` combines the
+ strings to "quux xyzzy". Despite appearing interesting, `P` is
+ TREESAME to all parents.
+
+'rev-list' walks backwards through history, including or excluding
+commits based on whether '\--full-history' and/or parent rewriting
+(via '\--parents' or '\--children') are used. The following settings
+are available.
+
+Default mode::
+
+ Commits are included if they are not TREESAME to any parent
+ (though this can be changed, see '\--sparse' below). If the
+ commit was a merge, and it was TREESAME to one parent, follow
+ only that parent. (Even if there are several TREESAME
+ parents, follow only one of them.) Otherwise, follow all
+ parents.
++
+This results in:
++
+-----------------------------------------------------------------------
+ .-A---N---O
+ / /
+ I---------D
+-----------------------------------------------------------------------
++
+Note how the rule to only follow the TREESAME parent, if one is
+available, removed `B` from consideration entirely. `C` was
+considered via `N`, but is TREESAME. Root commits are compared to an
+empty tree, so `I` is !TREESAME.
++
+Parent/child relations are only visible with --parents, but that does
+not affect the commits selected in default mode, so we have shown the
+parent lines.
+
+--full-history without parent rewriting::
+
+ This mode differs from the default in one point: always follow
+ all parents of a merge, even if it is TREESAME to one of them.
+ Even if more than one side of the merge has commits that are
+ included, this does not imply that the merge itself is! In
+ the example, we get
++
+-----------------------------------------------------------------------
+ I A B N D O
+-----------------------------------------------------------------------
++
+`P` and `M` were excluded because they are TREESAME to a parent. `E`,
+`C` and `B` were all walked, but only `B` was !TREESAME, so the others
+do not appear.
++
+Note that without parent rewriting, it is not really possible to talk
+about the parent/child relationships between the commits, so we show
+them disconnected.
+
+--full-history with parent rewriting::
+
+ Ordinary commits are only included if they are !TREESAME
+ (though this can be changed, see '\--sparse' below).
++
+Merges are always included. However, their parent list is rewritten:
+Along each parent, prune away commits that are not included
+themselves. This results in
++
+-----------------------------------------------------------------------
+ .-A---M---N---O---P
+ / / / / /
+ I B / D /
+ \ / / / /
+ `-------------'
+-----------------------------------------------------------------------
++
+Compare to '\--full-history' without rewriting above. Note that `E`
+was pruned away because it is TREESAME, but the parent list of P was
+rewritten to contain `E`'s parent `I`. The same happened for `C` and
+`N`. Note also that `P` was included despite being TREESAME.
+
+In addition to the above settings, you can change whether TREESAME
+affects inclusion:
+
--dense::
+
+ Commits that are walked are included if they are not TREESAME
+ to any parent.
+
--sparse::
-When optional paths are given, the default behaviour ('--dense') is to
-only output commits that changes at least one of them, and also ignore
-merges that do not touch the given paths.
+ All commits that are walked are included.
++
+Note that without '\--full-history', this still simplifies merges: if
+one of the parents is TREESAME, we follow only that one, so the other
+sides of the merge are never walked.
-Use the '--sparse' flag to makes the command output all eligible commits
-(still subject to count and age limitation), but apply merge
-simplification nevertheless.
ifdef::git-rev-list[]
+Bisection Helpers
+~~~~~~~~~~~~~~~~~
+
--bisect::
Limit output to the one commit object which is roughly halfway between
`--bisect-vars` had been used alone.
endif::git-rev-list[]
---
Commit Ordering
~~~~~~~~~~~~~~~
index e99921108e20f50e4c3f5d0e4beec37fbdf648f9..08d1310bf5fc5590ada1ee5b2af77d361ff4d874 100644 (file)
$ mv proj.git /home/you/public_html/proj.git
$ cd proj.git
$ git --bare update-server-info
-$ chmod a+x hooks/post-update
+$ mv hooks/post-update.sample hooks/post-update
-------------------------------------------------
(For an explanation of the last two lines, see
diff --git a/Makefile b/Makefile
index 90c5a131be24463183a1f21cf3bf337ef00dd67c..53ab4b55369652ecbcbd7b2655a9dfc6aeb08336 100644 (file)
--- a/Makefile
+++ b/Makefile
all:: shell_compatibility_test $(ALL_PROGRAMS) $(BUILT_INS) $(OTHER_PROGRAMS) GIT-BUILD-OPTIONS
ifneq (,$X)
- $(foreach p,$(patsubst %$X,%,$(filter %$X,$(ALL_PROGRAMS) $(BUILT_INS) git$X)), $(RM) '$p';)
+ $(foreach p,$(patsubst %$X,%,$(filter %$X,$(ALL_PROGRAMS) $(BUILT_INS) git$X)), test '$p' -ef '$p$X' || $(RM) '$p';)
endif
all::
index 78189c1b7bca120d896bab7a6160da1f436b4ff1..158b91284147d50a24d6dadaa7c5085cf0b7cb55 100755 (executable)
return 1
}
-__git_whitespacelist="nowarn warn error error-all strip"
+__git_whitespacelist="nowarn warn error error-all fix"
_git_am ()
{
return
;;
esac
- __gitcomp "$(__git_all_commands)"
+ __gitcomp "$(__git_all_commands)
+ attributes cli core-tutorial cvs-migration
+ diffcore gitk glossary hooks ignore modules
+ repository-layout tutorial tutorial-2
+ "
}
_git_init ()
--decorate --diff-filter=
--color-words --walk-reflogs
--parents --children --full-history
+ --merge
"
return
;;
__gitcomp "$(__git_refs)"
}
+_git_mergetool ()
+{
+ local cur="${COMP_WORDS[COMP_CWORD]}"
+ case "$cur" in
+ --tool=*)
+ __gitcomp "
+ kdiff3 tkdiff meld xxdiff emerge
+ vimdiff gvimdiff ecmerge opendiff
+ " "" "${cur##--tool=}"
+ return
+ ;;
+ --*)
+ __gitcomp "--tool="
+ return
+ ;;
+ esac
+ COMPREPLY=()
+}
+
_git_merge_base ()
{
__gitcomp "$(__git_refs)"
ls-remote) _git_ls_remote ;;
ls-tree) _git_ls_tree ;;
merge) _git_merge;;
+ mergetool) _git_mergetool;;
merge-base) _git_merge_base ;;
mv) _git_mv ;;
name-rev) _git_name_rev ;;
index 12fa9d3fd81ce83f53f36178bc3111edddfd2173..f9865b444fdf8b21211b04e9dba2999dd90cbc23 100755 (executable)
print real_cmd
return real_cmd
+def chdir(dir):
+ if os.name == 'nt':
+ os.environ['PWD']=dir
+ os.chdir(dir)
+
def die(msg):
if verbose:
raise Exception(msg)
print "Perforce checkout for depot path %s located at %s" % (self.depotPath, self.clientPath)
self.oldWorkingDirectory = os.getcwd()
- os.chdir(self.clientPath)
+ chdir(self.clientPath)
print "Syncronizing p4 checkout..."
p4_system("sync ...")
if len(commits) == 0:
print "All changes applied!"
- os.chdir(self.oldWorkingDirectory)
+ chdir(self.oldWorkingDirectory)
sync = P4Sync()
sync.run([])
print "Importing from %s into %s" % (', '.join(depotPaths), self.cloneDestination)
if not os.path.exists(self.cloneDestination):
os.makedirs(self.cloneDestination)
- os.chdir(self.cloneDestination)
+ chdir(self.cloneDestination)
system("git init")
self.gitdir = os.getcwd() + "/.git"
if not P4Sync.run(self, depotPaths):
if os.path.exists(cmd.gitdir):
cdup = read_pipe("git rev-parse --show-cdup").strip()
if len(cdup) > 0:
- os.chdir(cdup);
+ chdir(cdup);
if not isValidGitDir(cmd.gitdir):
if isValidGitDir(cmd.gitdir + "/.git"):
diff --git a/daemon.c b/daemon.c
index 4540e8df5ab8bc8ff66549144d7db2928e12199b..8dcde73200d1ddbc0dec0dbfdc2f4ff15047abd9 100644 (file)
--- a/daemon.c
+++ b/daemon.c
}
break;
}
+ signal(SIGCHLD, child_handler);
}
static int set_reuse_addr(int sockfd)
index 8746c60b9cb634bf78911c34cad1ba5a1f93d5ec..bf5d5f15a3b54f1e1a0a2068990e899fd869d435 100644 (file)
--- a/diff.c
+++ b/diff.c
"\\|"
"^\\(.*=[ \t]*\\(class\\|record\\).*\\)$"
},
+ { "bibtex", "\\(@[a-zA-Z]\\{1,\\}[ \t]*{\\{0,1\\}[ \t]*[^ \t\"@',\\#}{~%]*\\).*$" },
{ "tex", "^\\(\\\\\\(\\(sub\\)*section\\|chapter\\|part\\)\\*\\{0,1\\}{.*\\)$" },
{ "ruby", "^\\s*\\(\\(class\\|module\\|def\\)\\s.*\\)$" },
};
ecb.priv = &data;
xdi_diff(&mf1, &mf2, &xpp, &xecfg, &ecb);
- if (data.trailing_blanks_start) {
+ if ((data.ws_rule & WS_TRAILING_SPACE) &&
+ data.trailing_blanks_start) {
fprintf(o->file, "%s:%d: ends with blank lines.\n",
data.filename, data.trailing_blanks_start);
data.status = 1; /* report errors */
index 29d1d5ba31def46ba8b55905dc60773cc6cc167e..109e05b01346ac13296dfbcfa2355a43d97731cd 100644 (file)
--- a/dir.c
+++ b/dir.c
static inline int special_char(unsigned char c1)
{
- return !c1 || c1 == '*' || c1 == '[' || c1 == '?';
+ return !c1 || c1 == '*' || c1 == '[' || c1 == '?' || c1 == '\\';
}
/*
diff --git a/git-am.sh b/git-am.sh
index 8f91a97eb3a07908b35de086d555822c928fd2e9..aa602618e6caedbfdd2d54ad4bb8375356cc55f6 100755 (executable)
--- a/git-am.sh
+++ b/git-am.sh
--
d,dotest= (removed -- do not use)
i,interactive run interactively
-b,binary pass --allow-binary-replacement to git-apply
+b,binary (historical option -- no-op)
3,3way allow fall back on 3way merging if needed
s,signoff add a Signed-off-by line to the commit message
u,utf8 recode into utf8 (default)
echo Using index info to reconstruct a base tree...
if GIT_INDEX_FILE="$dotest/patch-merge-tmp-index" \
- git apply $binary --cached <"$dotest/patch"
+ git apply --cached <"$dotest/patch"
then
mv "$dotest/patch-merge-base+" "$dotest/patch-merge-base"
mv "$dotest/patch-merge-tmp-index" "$dotest/patch-merge-index"
prec=4
dotest="$GIT_DIR/rebase-apply"
-sign= utf8=t keep= skip= interactive= resolved= binary= rebasing= abort=
+sign= utf8=t keep= skip= interactive= resolved= rebasing= abort=
resolvemsg= resume=
git_apply_opt=
-i|--interactive)
interactive=t ;;
-b|--binary)
- binary=t ;;
+ : ;;
-3|--3way)
threeway=t ;;
-s|--signoff)
--abort)
abort=t ;;
--rebasing)
- rebasing=t threeway=t keep=t binary=t ;;
+ rebasing=t threeway=t keep=t ;;
-d|--dotest)
die "-d option is no longer supported. Do not use."
;;
exit 1
}
- # -b, -s, -u, -k and --whitespace flags are kept for the
+ # -s, -u, -k and --whitespace flags are kept for the
# resuming session after a patch failure.
# -3 and -i can and must be given when resuming.
- echo "$binary" >"$dotest/binary"
echo " $ws" >"$dotest/whitespace"
echo "$sign" >"$dotest/sign"
echo "$utf8" >"$dotest/utf8"
fi
esac
-if test "$(cat "$dotest/binary")" = t
-then
- binary=--allow-binary-replacement
-fi
if test "$(cat "$dotest/utf8")" = t
then
utf8=-u
case "$resolved" in
'')
- git apply $git_apply_opt $binary --index "$dotest/patch"
+ git apply $git_apply_opt --index "$dotest/patch"
apply_status=$?
;;
t)
diff --git a/git-bisect.sh b/git-bisect.sh
index 3cac20db79e1e408a321b0e9d272501985a3c49b..97ac600873ebd0dff6310071343403a41a867b8a 100755 (executable)
--- a/git-bisect.sh
+++ b/git-bisect.sh
if test -t 0
then
printf >&2 'Are you sure [Y/n]? '
- case "$(read yesno)" in [Nn]*) exit 1 ;; esac
+ read yesno
+ case "$yesno" in [Nn]*) exit 1 ;; esac
fi
: bisect without good...
;;
index 4e334ba41dad3067394b79c15ebfe610b2d3e178..929d681c4716fa4f6b2947fdb40ad6fbb580bef3 100755 (executable)
}
pick_one_preserving_merges () {
- case "$1" in -n) sha1=$2 ;; *) sha1=$1 ;; esac
+ fast_forward=t
+ case "$1" in
+ -n)
+ fast_forward=f
+ sha1=$2
+ ;;
+ *)
+ sha1=$1
+ ;;
+ esac
sha1=$(git rev-parse $sha1)
if test -f "$DOTEST"/current-commit
die "Cannot write current commit's replacement sha1"
fi
+ echo $sha1 > "$DOTEST"/current-commit
+
# rewrite parents; if none were rewritten, we can fast-forward.
- fast_forward=t
- preserve=t
new_parents=
for p in $(git rev-list --parents -1 $sha1 | cut -d' ' -f2-)
do
if test -f "$REWRITTEN"/$p
then
- preserve=f
new_p=$(cat "$REWRITTEN"/$p)
test $p != $new_p && fast_forward=f
case "$new_parents" in
case $fast_forward in
t)
output warn "Fast forward to $sha1"
- test $preserve = f || echo $sha1 > "$REWRITTEN"/$sha1
+ output git reset --hard $sha1 ||
+ die "Cannot fast forward to $sha1"
;;
f)
test "a$1" = a-n && die "Refusing to squash a merge: $sha1"
output git checkout $first_parent 2> /dev/null ||
die "Cannot move HEAD to $first_parent"
- echo $sha1 > "$DOTEST"/current-commit
case "$new_parents" in
' '*' '*)
# redo merge
diff --git a/git-rebase.sh b/git-rebase.sh
index 412e135c3ae88d76b5bdf3f08083b153da220a95..528b604cd57a774030c5f5830d3d78b5a04454cf 100755 (executable)
--- a/git-rebase.sh
+++ b/git-rebase.sh
done && test -n "$1"
}
+test -f "$GIT_DIR"/rebase-apply/applying &&
+ die 'It looks like git-am is in progress. Cannot rebase.'
+
is_interactive "$@" && exec git-rebase--interactive "$@"
+if test $# -eq 0
+then
+ test -d "$dotest" -o -d "$GIT_DIR"/rebase-apply || usage
+ test -d "$dotest" -o -f "$GIT_DIR"/rebase-apply/rebasing &&
+ die 'A rebase is in progress, try --continue, --skip or --abort.'
+ die "No arguments given and $GIT_DIR/rebase-apply already exists."
+fi
+
while test $# != 0
do
case "$1" in
# Make sure we do not have $GIT_DIR/rebase-apply
if test -z "$do_merge"
then
- if mkdir "$GIT_DIR"/rebase-apply
+ if mkdir "$GIT_DIR"/rebase-apply 2>/dev/null
then
rmdir "$GIT_DIR"/rebase-apply
else
echo >&2 '
-It seems that I cannot create a '"$GIT_DIR"'/rebase-apply directory,
-and I wonder if you are in the middle of patch application or another
+It seems that I cannot create a rebase-apply directory, and
+I wonder if you are in the middle of patch application or another
rebase. If that is not the case, please
rm -fr '"$GIT_DIR"'/rebase-apply
- and run me again. I am stopping in case you still have something
+and run me again. I am stopping in case you still have something
valuable there.'
exit 1
fi
if test -d "$dotest"
then
die "previous rebase directory $dotest still exists." \
- 'try git-rebase < --continue | --abort >'
+ 'Try git rebase (--continue | --abort | --skip)'
fi
fi
diff --git a/git-stash.sh b/git-stash.sh
index 5ad2c4b7a33cf1be24ee85f17c8738ca05b98db0..e15c12abc31c1e4d22bb3943d70a65ddf33abb53 100755 (executable)
--- a/git-stash.sh
+++ b/git-stash.sh
#!/bin/sh
# Copyright (c) 2007, Nanako Shiraishi
-USAGE='[ | save | list | show | apply | clear | drop | pop | create | branch ]'
+dashless=$(basename "$0" | sed -e 's/-/ /')
+USAGE="list [<options>]
+ or: $dashless (show | drop | pop ) [<stash>]
+ or: $dashless apply [--index] [<stash>]
+ or: $dashless branch <branchname> [<stash>]
+ or: $dashless [save [--keep-index] [<message>]]
+ or: $dashless clear"
SUBDIRECTORY_OK=Yes
OPTIONS_SPEC=
diff --git a/git-svn.perl b/git-svn.perl
index 4dc33801a88c63f62a263b5008649b05fc1b9d7d..099fd02b3fcf10b230e8397e695b3b8af8301d5a 100755 (executable)
--- a/git-svn.perl
+++ b/git-svn.perl
my $arg = shift;
my $ref = ref $arg;
my $md5 = Digest::MD5->new();
- if ($ref eq 'GLOB' || $ref eq 'IO::File') {
+ if ($ref eq 'GLOB' || $ref eq 'IO::File' || $ref eq 'File::Temp') {
$md5->addfile($arg) or croak $!;
} elsif ($ref eq 'SCALAR') {
$md5->add($$arg) or croak $!;
}
}
+
my (%LOCKFILES, %INDEX_FILES);
END {
unlink keys %LOCKFILES if %LOCKFILES;
sub apply_textdelta {
my ($self, $fb, $exp) = @_;
- my $fh = IO::File->new_tmpfile;
- $fh->autoflush(1);
+ my $fh = Git::temp_acquire('svn_delta');
# $fh gets auto-closed() by SVN::TxDelta::apply(),
# (but $base does not,) so dup() it for reading in close_file
open my $dup, '<&', $fh or croak $!;
- my $base = IO::File->new_tmpfile;
- $base->autoflush(1);
+ my $base = Git::temp_acquire('git_blob');
if ($fb->{blob}) {
print $base 'link ' if ($fb->{mode_a} == 120000);
my $size = $::_repository->cat_blob($fb->{blob}, $base);
}
}
seek $base, 0, 0 or croak $!;
- $fb->{fh} = $dup;
+ $fb->{fh} = $fh;
$fb->{base} = $base;
- [ SVN::TxDelta::apply($base, $fh, undef, $fb->{path}, $fb->{pool}) ];
+ [ SVN::TxDelta::apply($base, $dup, undef, $fb->{path}, $fb->{pool}) ];
}
sub close_file {
"expected: $exp\n got: $got\n";
}
}
- sysseek($fh, 0, 0) or croak $!;
if ($fb->{mode_b} == 120000) {
- eval {
- sysread($fh, my $buf, 5) == 5 or croak $!;
- $buf eq 'link ' or die "$path has mode 120000",
- " but is not a link";
- };
- if ($@) {
- warn "$@\n";
- sysseek($fh, 0, 0) or croak $!;
- }
- }
+ sysseek($fh, 0, 0) or croak $!;
+ sysread($fh, my $buf, 5) == 5 or croak $!;
- my ($tmp_fh, $tmp_filename) = File::Temp::tempfile(UNLINK => 1);
- my $result;
- while ($result = sysread($fh, my $string, 1024)) {
- my $wrote = syswrite($tmp_fh, $string, $result);
- defined($wrote) && $wrote == $result
- or croak("write $tmp_filename: $!\n");
- }
- defined $result or croak $!;
- close $tmp_fh or croak $!;
+ unless ($buf eq 'link ') {
+ warn "$path has mode 120000",
+ " but is not a link\n";
+ } else {
+ my $tmp_fh = Git::temp_acquire('svn_hash');
+ my $res;
+ while ($res = sysread($fh, my $str, 1024)) {
+ my $out = syswrite($tmp_fh, $str, $res);
+ defined($out) && $out == $res
+ or croak("write ",
+ $tmp_fh->filename,
+ ": $!\n");
+ }
+ defined $res or croak $!;
- close $fh or croak $!;
+ ($fh, $tmp_fh) = ($tmp_fh, $fh);
+ Git::temp_release($tmp_fh, 1);
+ }
+ }
- $hash = $::_repository->hash_and_insert_object($tmp_filename);
- unlink($tmp_filename);
+ $hash = $::_repository->hash_and_insert_object(
+ $fh->filename);
$hash =~ /^[a-f\d]{40}$/ or die "not a sha1: $hash\n";
- close $fb->{base} or croak $!;
+
+ Git::temp_release($fb->{base}, 1);
+ Git::temp_release($fh, 1);
} else {
$hash = $fb->{blob} or die "no blob information\n";
}
} elsif ($m->{mode_b} !~ /755$/ && $m->{mode_a} =~ /755$/) {
$self->change_file_prop($fbat,'svn:executable',undef);
}
- my $fh = IO::File->new_tmpfile or croak $!;
+ my $fh = Git::temp_acquire('git_blob');
if ($m->{mode_b} =~ /^120/) {
print $fh 'link ' or croak $!;
$self->change_file_prop($fbat,'svn:special','*');
my $atd = $self->apply_textdelta($fbat, undef, $pool);
my $got = SVN::TxDelta::send_stream($fh, @$atd, $pool);
die "Checksum mismatch\nexpected: $exp\ngot: $got\n" if ($got ne $exp);
+ Git::temp_release($fh, 1);
$pool->clear;
-
- close $fh or croak $!;
}
sub D {
diff --git a/gitk-git/gitk b/gitk-git/gitk
index d093a39506798c750cc838f0085f6721e0f733a9..087c4ac733be4b788751d0bae5b7aad22ce0dd99 100644 (file)
--- a/gitk-git/gitk
+++ b/gitk-git/gitk
# run before X event handlers, so reading from a fast source can
# make the GUI completely unresponsive.
proc run args {
- global isonrunq runq
+ global isonrunq runq currunq
set script $args
if {[info exists isonrunq($script)]} return
- if {$runq eq {}} {
+ if {$runq eq {} && ![info exists currunq]} {
after idle dorunq
}
lappend runq [list {} $script]
}
proc filereadable {fd script} {
- global runq
+ global runq currunq
fileevent $fd readable {}
- if {$runq eq {}} {
+ if {$runq eq {} && ![info exists currunq]} {
after idle dorunq
}
lappend runq [list $fd $script]
}
proc dorunq {} {
- global isonrunq runq
+ global isonrunq runq currunq
set tstart [clock clicks -milliseconds]
set t0 $tstart
while {[llength $runq] > 0} {
set fd [lindex $runq 0 0]
set script [lindex $runq 0 1]
+ set currunq [lindex $runq 0]
+ set runq [lrange $runq 1 end]
set repeat [eval $script]
+ unset currunq
set t1 [clock clicks -milliseconds]
set t [expr {$t1 - $t0}]
- set runq [lrange $runq 1 end]
if {$repeat ne {} && $repeat} {
if {$fd eq {} || $repeat == 2} {
# script returns 1 if it wants to be readded
index 9df447bd6dcfaddf7f05fe5f0b624700ff1f40d7..76e8872622e435b050f77198ef6eef6e6ff6869e 100644 (file)
--- a/path.c
+++ b/path.c
* path = Canonical absolute path
* prefix_list = Colon-separated list of absolute paths
*
- * Determines, for each path in parent_list, whether the "prefix" really
+ * Determines, for each path in prefix_list, whether the "prefix" really
* is an ancestor directory of path. Returns the length of the longest
* ancestor directory, excluding any trailing slashes, or -1 if no prefix
* is an ancestor. (Note that this means 0 is returned if prefix_list is
diff --git a/perl/Git.pm b/perl/Git.pm
index e1ca5b4a2289c59aa54f013aff54ecf1385e3030..102e6a4ce3f63ea5754eff581c17df325cc1e073 100644 (file)
--- a/perl/Git.pm
+++ b/perl/Git.pm
command_output_pipe command_input_pipe command_close_pipe
command_bidi_pipe command_close_bidi_pipe
version exec_path hash_object git_cmd_try
- remote_refs);
+ remote_refs
+ temp_acquire temp_release temp_reset);
=head1 DESCRIPTION
use Error qw(:try);
use Cwd qw(abs_path);
use IPC::Open2 qw(open2);
-
+use Fcntl qw(SEEK_SET SEEK_CUR);
}
delete @$self{@vars};
}
+
+{ # %TEMP_* Lexical Context
+
+my (%TEMP_LOCKS, %TEMP_FILES);
+
+=item temp_acquire ( NAME )
+
+Attempts to retreive the temporary file mapped to the string C<NAME>. If an
+associated temp file has not been created this session or was closed, it is
+created, cached, and set for autoflush and binmode.
+
+Internally locks the file mapped to C<NAME>. This lock must be released with
+C<temp_release()> when the temp file is no longer needed. Subsequent attempts
+to retrieve temporary files mapped to the same C<NAME> while still locked will
+cause an error. This locking mechanism provides a weak guarantee and is not
+threadsafe. It does provide some error checking to help prevent temp file refs
+writing over one another.
+
+In general, the L<File::Handle> returned should not be closed by consumers as
+it defeats the purpose of this caching mechanism. If you need to close the temp
+file handle, then you should use L<File::Temp> or another temp file faculty
+directly. If a handle is closed and then requested again, then a warning will
+issue.
+
+=cut
+
+sub temp_acquire {
+ my ($self, $name) = _maybe_self(@_);
+
+ my $temp_fd = _temp_cache($name);
+
+ $TEMP_LOCKS{$temp_fd} = 1;
+ $temp_fd;
+}
+
+=item temp_release ( NAME )
+
+=item temp_release ( FILEHANDLE )
+
+Releases a lock acquired through C<temp_acquire()>. Can be called either with
+the C<NAME> mapping used when acquiring the temp file or with the C<FILEHANDLE>
+referencing a locked temp file.
+
+Warns if an attempt is made to release a file that is not locked.
+
+The temp file will be truncated before being released. This can help to reduce
+disk I/O where the system is smart enough to detect the truncation while data
+is in the output buffers. Beware that after the temp file is released and
+truncated, any operations on that file may fail miserably until it is
+re-acquired. All contents are lost between each release and acquire mapped to
+the same string.
+
+=cut
+
+sub temp_release {
+ my ($self, $temp_fd, $trunc) = _maybe_self(@_);
+
+ if (ref($temp_fd) ne 'File::Temp') {
+ $temp_fd = $TEMP_FILES{$temp_fd};
+ }
+ unless ($TEMP_LOCKS{$temp_fd}) {
+ carp "Attempt to release temp file '",
+ $temp_fd, "' that has not been locked";
+ }
+ temp_reset($temp_fd) if $trunc and $temp_fd->opened;
+
+ $TEMP_LOCKS{$temp_fd} = 0;
+ undef;
+}
+
+sub _temp_cache {
+ my ($name) = @_;
+
+ _verify_require();
+
+ my $temp_fd = \$TEMP_FILES{$name};
+ if (defined $$temp_fd and $$temp_fd->opened) {
+ if ($TEMP_LOCKS{$$temp_fd}) {
+ throw Error::Simple("Temp file with moniker '",
+ $name, "' already in use");
+ }
+ } else {
+ if (defined $$temp_fd) {
+ # then we're here because of a closed handle.
+ carp "Temp file '", $name,
+ "' was closed. Opening replacement.";
+ }
+ $$temp_fd = File::Temp->new(
+ TEMPLATE => 'Git_XXXXXX',
+ DIR => File::Spec->tmpdir
+ ) or throw Error::Simple("couldn't open new temp file");
+ $$temp_fd->autoflush;
+ binmode $$temp_fd;
+ }
+ $$temp_fd;
+}
+
+sub _verify_require {
+ eval { require File::Temp; require File::Spec; };
+ $@ and throw Error::Simple($@);
+}
+
+=item temp_reset ( FILEHANDLE )
+
+Truncates and resets the position of the C<FILEHANDLE>.
+
+=cut
+
+sub temp_reset {
+ my ($self, $temp_fd) = _maybe_self(@_);
+
+ truncate $temp_fd, 0
+ or throw Error::Simple("couldn't truncate file");
+ sysseek($temp_fd, 0, SEEK_SET) and seek($temp_fd, 0, SEEK_SET)
+ or throw Error::Simple("couldn't seek to beginning of file");
+ sysseek($temp_fd, 0, SEEK_CUR) == 0 and tell($temp_fd) == 0
+ or throw Error::Simple("expected file position to be reset");
+}
+
+sub END {
+ unlink values %TEMP_FILES if %TEMP_FILES;
+}
+
+} # %TEMP_* Lexical Context
+
=back
=head1 ERROR HANDLING
diff --git a/t/t0023-crlf-am.sh b/t/t0023-crlf-am.sh
index 6f8a4347d5397b8b396db800c12c6e045a0d2b7c..aaed7254023b86a30c499db7c4b069c9d08b1085 100755 (executable)
--- a/t/t0023-crlf-am.sh
+++ b/t/t0023-crlf-am.sh
test_expect_success 'am' '
- git am --binary -3 <patchfile &&
+ git am -3 <patchfile &&
git diff-files --name-status --exit-code
'
index ffe3dd97b7b1c056d854e28795e1313ce1633452..5aa487ac02fc93c9ddbef85e430795543b976b60 100755 (executable)
test_expect_success '-p handles "no changes" gracefully' '
HEAD=$(git rev-parse HEAD) &&
git rebase -i -p HEAD^ &&
+ git update-index --refresh &&
+ git diff-files --quiet &&
+ git diff-index --quiet --cached HEAD -- &&
test $HEAD = $(git rev-parse HEAD)
'
git checkout -b to-be-rebased &&
test_tick &&
git rebase -i -p --onto branch1 master &&
+ git update-index --refresh &&
+ git diff-files --quiet &&
+ git diff-index --quiet --cached HEAD -- &&
test $(git rev-parse HEAD~6) = $(git rev-parse branch1) &&
test $(git rev-parse HEAD~4^2) = $(git rev-parse to-be-preserved) &&
test $(git rev-parse HEAD^^2^) = $(git rev-parse HEAD^^^) &&
test $(git show HEAD:unrelated-file) = 1
'
+test_expect_success 'edit ancestor with -p' '
+ FAKE_LINES="1 edit 2 3 4" git rebase -i -p HEAD~3 &&
+ echo 2 > unrelated-file &&
+ test_tick &&
+ git commit -m L2-modified --amend unrelated-file &&
+ git rebase --continue &&
+ git update-index --refresh &&
+ git diff-files --quiet &&
+ git diff-index --quiet --cached HEAD -- &&
+ test $(git show HEAD:unrelated-file) = 2
+'
+
test_expect_success '--continue tries to commit' '
test_tick &&
test_must_fail git rebase -i --onto new-branch1 HEAD^ &&
diff --git a/t/t3700-add.sh b/t/t3700-add.sh
index 7d123d17fc156c61a8e85a399c3762e8075485de..2ac93a346d016c65614f2bf6142049e7bdc39bd1 100755 (executable)
--- a/t/t3700-add.sh
+++ b/t/t3700-add.sh
! ( git ls-files foo1 | grep foo1 )
'
+test_expect_success 'git add '\''fo\[ou\]bar'\'' ignores foobar' '
+ git reset --hard &&
+ touch fo\[ou\]bar foobar &&
+ git add '\''fo\[ou\]bar'\'' &&
+ git ls-files fo\[ou\]bar | grep -F fo\[ou\]bar &&
+ ! ( git ls-files foobar | grep foobar )
+'
+
test_done
index 0d9cbb62615c0d94da784f63907989988b0e8151..7eae1f4500591799d656f1dde20cf15f296cf6e4 100755 (executable)
--- a/t/t4019-diff-wserror.sh
+++ b/t/t4019-diff-wserror.sh
echo " HT and SP indent" >>F &&
echo "With trailing SP " >>F &&
echo "Carriage ReturnQ" | tr Q "\015" >>F &&
- echo "No problem" >>F
+ echo "No problem" >>F &&
+ echo >>F
'
'
+test_expect_success 'trailing empty lines (1)' '
+
+ rm -f .gitattributes &&
+ test_must_fail git diff --check >output &&
+ grep "ends with blank lines." output &&
+ grep "trailing whitespace" output
+
+'
+
+test_expect_success 'trailing empty lines (2)' '
+
+ echo "F -whitespace" >.gitattributes &&
+ git diff --check >output &&
+ ! test -s output
+
+'
+
test_done
diff --git a/t/t5304-prune.sh b/t/t5304-prune.sh
index 9fd9d0700033027921c90290cedc0a31d71c7733..771c0a06a4bd01cf40628ffae379b5d992802ef6 100755 (executable)
--- a/t/t5304-prune.sh
+++ b/t/t5304-prune.sh
orig_pack=$(echo .git/objects/pack/*.pack) &&
: > .git/objects/tmp_1.pack &&
: > .git/objects/tmp_2.pack &&
- test-chmtime -86501 .git/objects/tmp_1.pack &&
+ test-chmtime =-86501 .git/objects/tmp_1.pack &&
git prune --expire 1.day &&
test -f $orig_pack &&
test -f .git/objects/tmp_2.pack &&
git prune --expire=1.hour.ago &&
test $((1 + $before)) = $(git count-objects | sed "s/ .*//") &&
test -f $BLOB_FILE &&
- test-chmtime -86500 $BLOB_FILE &&
+ test-chmtime =-86500 $BLOB_FILE &&
git prune --expire 1.day &&
test $before = $(git count-objects | sed "s/ .*//") &&
! test -f $BLOB_FILE
BLOB_FILE=.git/objects/$(echo $BLOB | sed "s/^../&\//") &&
test $((1 + $before)) = $(git count-objects | sed "s/ .*//") &&
test -f $BLOB_FILE &&
- test-chmtime -$((86400*14-30)) $BLOB_FILE &&
+ test-chmtime =-$((86400*14-30)) $BLOB_FILE &&
git gc &&
test $((1 + $before)) = $(git count-objects | sed "s/ .*//") &&
test -f $BLOB_FILE &&
- test-chmtime -$((86400*14+1)) $BLOB_FILE &&
+ test-chmtime =-$((86400*14+1)) $BLOB_FILE &&
git gc &&
test $before = $(git count-objects | sed "s/ .*//") &&
! test -f $BLOB_FILE
diff --git a/t/t5540-http-push.sh b/t/t5540-http-push.sh
index f8c17cd96cc86ca8f2db2ff51467f712d65f8956..b0d242e3edc13dd7cad8f5fc4b5d2d205e620190 100755 (executable)
--- a/t/t5540-http-push.sh
+++ b/t/t5540-http-push.sh
git clone --bare test_repo test_repo.git &&
cd test_repo.git &&
git --bare update-server-info &&
- chmod +x hooks/post-update &&
+ mv hooks/post-update.sample hooks/post-update &&
cd - &&
mv test_repo.git "$HTTPD_DOCUMENT_ROOT_PATH"
'
diff --git a/t/t9300-fast-import.sh b/t/t9300-fast-import.sh
index 1fc06c5a23b50d54c33755a9fce4ddd9ed3b9c79..c6bc0a607f200fcc8888b66ff1a8f0e324332db8 100755 (executable)
--- a/t/t9300-fast-import.sh
+++ b/t/t9300-fast-import.sh
INPUT_END
test_expect_success 'P: fail on inline gitlink' '
- ! git-fast-import <input'
+ test_must_fail git-fast-import <input'
test_tick
cat >input <<INPUT_END
INPUT_END
test_expect_success 'P: fail on blob mark in gitlink' '
- ! git-fast-import <input'
+ test_must_fail git-fast-import <input'
test_done
diff --git a/test-parse-options.c b/test-parse-options.c
index 6e18083a7d1655e9eabef197c58d92a910d2f67b..61d2c39814529bd0264e4c9e40241131d51d819c 100644 (file)
--- a/test-parse-options.c
+++ b/test-parse-options.c
if (unset)
return 1; /* do not support unset */
- *(unsigned long *)opt->value = strlen(arg);
+ *(int *)opt->value = strlen(arg);
return 0;
}