Browse Source

Merge branch 'js/read-tree' into js/c-merge-recursive

* js/read-tree: (107 commits)
  read-tree: move merge functions to the library
  read-trees: refactor the unpack_trees() part
  tar-tree: illustrate an obscure feature better
  git.c: allow alias expansion without a git directory
  setup_git_directory_gently: do not barf when GIT_DIR is given.
  Build on Debian GNU/kFreeBSD
  Call setup_git_directory() much earlier
  Call setup_git_directory() early
  Display an error from update-ref if target ref name is invalid.
  Fix http-fetch
  t4103: fix binary patch application test.
  git-apply -R: binary patches are irreversible for now.
  Teach git-apply about '-R'
  Makefile: ssh-pull.o depends on ssh-fetch.c
  log and diff family: honor config even from subdirectories
  git-reset: detect update-ref error and report it.
  lost-found: use fsck-objects --full
  Teach git-http-fetch the --stdin switch
  Teach git-local-fetch the --stdin switch
  Make pull() support fetching multiple targets at once
  ...
maint
Junio C Hamano 19 years ago
parent
commit
c1a788acee
  1. 6
      .gitignore
  2. 15
      Documentation/Makefile
  3. 2
      Documentation/asciidoc.conf
  4. 21
      Documentation/config.txt
  5. 8
      Documentation/git-cvsexportcommit.txt
  6. 13
      Documentation/git-daemon.txt
  7. 16
      Documentation/git-format-patch.txt
  8. 8
      Documentation/git-http-fetch.txt
  9. 6
      Documentation/git-local-fetch.txt
  10. 20
      Documentation/git-tar-tree.txt
  11. 12
      Documentation/git.txt
  12. 17
      Documentation/urls.txt
  13. 9
      INSTALL
  14. 57
      Makefile
  15. 2
      blame.c
  16. 46
      builtin-add.c
  17. 145
      builtin-apply.c
  18. 3
      builtin-cat-file.c
  19. 2
      builtin-check-ref-format.c
  20. 4
      builtin-commit-tree.c
  21. 2
      builtin-count.c
  22. 4
      builtin-diff-files.c
  23. 4
      builtin-diff-index.c
  24. 3
      builtin-diff-stages.c
  25. 4
      builtin-diff-tree.c
  26. 14
      builtin-diff.c
  27. 4
      builtin-fmt-merge-msg.c
  28. 3
      builtin-grep.c
  29. 6
      builtin-help.c
  30. 2
      builtin-init-db.c
  31. 71
      builtin-log.c
  32. 3
      builtin-ls-files.c
  33. 8
      builtin-ls-tree.c
  34. 4
      builtin-mailinfo.c
  35. 2
      builtin-mailsplit.c
  36. 297
      builtin-mv.c
  37. 4
      builtin-prune.c
  38. 2
      builtin-push.c
  39. 862
      builtin-read-tree.c
  40. 4
      builtin-rev-list.c
  41. 3
      builtin-rev-parse.c
  42. 6
      builtin-rm.c
  43. 14
      builtin-show-branch.c
  44. 2
      builtin-stripspace.c
  45. 30
      builtin-tar-tree.c
  46. 3
      builtin-update-index.c
  47. 3
      builtin-update-ref.c
  48. 2
      builtin-upload-tar.c
  49. 4
      builtin-write-tree.c
  50. 77
      builtin.h
  51. 2
      cache.h
  52. 3
      combine-diff.c
  53. 5
      config.c
  54. 24
      config.mak.in
  55. 183
      configure.ac
  56. 4
      contrib/emacs/Makefile
  57. 31
      contrib/emacs/git.el
  58. 2
      daemon.c
  59. 28
      diff.c
  60. 11
      diff.h
  61. 1
      environment.c
  62. 122
      fetch.c
  63. 17
      fetch.h
  64. 12
      git-am.sh
  65. 4
      git-clone.sh
  66. 50
      git-cvsexportcommit.perl
  67. 89
      git-cvsserver.perl
  68. 19
      git-fetch.sh
  69. 11
      git-instaweb.sh
  70. 2
      git-lost-found.sh
  71. 17
      git-merge.sh
  72. 250
      git-mv.perl
  73. 3
      git-pull.sh
  74. 2
      git-quiltimport.sh
  75. 9
      git-rebase.sh
  76. 5
      git-reset.sh
  77. 7
      git-resolve.sh
  78. 25
      git-svn.perl
  79. 236
      git.c
  80. 166
      gitweb/gitweb.cgi
  81. 45
      http-fetch.c
  82. 2
      http-push.c
  83. 34
      local-fetch.c
  84. 10
      log-tree.c
  85. 13
      pack-objects.c
  86. 39
      read-cache.c
  87. 5
      refs.c
  88. 4
      revision.c
  89. 4
      revision.h
  90. 4
      setup.c
  91. 132
      sha1_file.c
  92. 6
      ssh-fetch.c
  93. 12
      t/t1400-update-ref.sh
  94. 24
      t/t4102-apply-rename.sh
  95. 4
      t/t4103-apply-binary.sh
  96. 28
      t/t4112-apply-renames.sh
  97. 105
      t/t4114-apply-typechange.sh
  98. 19
      t/t6004-rev-list-path-optim.sh
  99. 40
      t/t7001-mv.sh
  100. 5
      unpack-objects.c
  101. Some files were not shown because too many files have changed in this diff Show More

6
.gitignore vendored

@ -137,4 +137,10 @@ git-core.spec @@ -137,4 +137,10 @@ git-core.spec
*.[ao]
*.py[co]
config.mak
autom4te.cache
config.log
config.status
config.mak.in
config.mak.autogen
configure
git-blame

15
Documentation/Makefile

@ -25,10 +25,10 @@ DOC_MAN1=$(patsubst %.txt,%.1,$(MAN1_TXT)) @@ -25,10 +25,10 @@ DOC_MAN1=$(patsubst %.txt,%.1,$(MAN1_TXT))
DOC_MAN7=$(patsubst %.txt,%.7,$(MAN7_TXT))

prefix?=$(HOME)
bin=$(prefix)/bin
mandir=$(prefix)/man
man1=$(mandir)/man1
man7=$(mandir)/man7
bindir?=$(prefix)/bin
mandir?=$(prefix)/man
man1dir=$(mandir)/man1
man7dir=$(mandir)/man7
# DESTDIR=

INSTALL?=install
@ -46,15 +46,16 @@ all: html man @@ -46,15 +46,16 @@ all: html man

html: $(DOC_HTML)

$(DOC_HTML) $(DOC_MAN1) $(DOC_MAN7): asciidoc.conf

man: man1 man7
man1: $(DOC_MAN1)
man7: $(DOC_MAN7)

install: man
$(INSTALL) -d -m755 $(DESTDIR)$(man1) $(DESTDIR)$(man7)
$(INSTALL) $(DOC_MAN1) $(DESTDIR)$(man1)
$(INSTALL) $(DOC_MAN7) $(DESTDIR)$(man7)
$(INSTALL) -d -m755 $(DESTDIR)$(man1dir) $(DESTDIR)$(man7dir)
$(INSTALL) $(DOC_MAN1) $(DESTDIR)$(man1dir)
$(INSTALL) $(DOC_MAN7) $(DESTDIR)$(man7dir)


#

2
Documentation/asciidoc.conf

@ -9,6 +9,8 @@ @@ -9,6 +9,8 @@

[attributes]
caret=^
startsb=[
endsb=]

ifdef::backend-docbook[]
[gitlink-inlinemacro]

21
Documentation/config.txt

@ -97,6 +97,12 @@ core.compression:: @@ -97,6 +97,12 @@ core.compression::
compression, and 1..9 are various speed/size tradeoffs, 9 being
slowest.

core.legacyheaders::
A boolean which enables the legacy object header format in case
you want to interoperate with old clients accessing the object
database directly (where the "http://" and "rsync://" protocols
count as direct access).

alias.*::
Command aliases for the gitlink:git[1] command wrapper - e.g.
after defining "alias.last = cat-file commit HEAD", the invocation
@ -193,6 +199,10 @@ merge.summary:: @@ -193,6 +199,10 @@ merge.summary::
Whether to include summaries of merged commits in newly created
merge commit messages. False by default.

pack.window::
The size of the window used by gitlink:git-pack-objects[1] when no
window size is given on the command line. Defaults to 10.

pull.octopus::
The default merge strategy to use when pulling multiple branches
at once.
@ -208,6 +218,17 @@ showbranch.default:: @@ -208,6 +218,17 @@ showbranch.default::
The default set of branches for gitlink:git-show-branch[1].
See gitlink:git-show-branch[1].

tar.umask::
By default, git-link:git-tar-tree[1] sets file and directories modes
to 0666 or 0777. While this is both useful and acceptable for projects
such as the Linux Kernel, it might be excessive for other projects.
With this variable, it becomes possible to tell
git-link:git-tar-tree[1] to apply a specific umask to the modes above.
The special value "user" indicates that the user's current umask will
be used. This should be enough for most projects, as it will lead to
the same permissions as git-link:git-checkout[1] would use. The default
value remains 0, which means world read-write.

user.email::
Your email address to be recorded in any newly created commits.
Can be overridden by the 'GIT_AUTHOR_EMAIL' and 'GIT_COMMITTER_EMAIL'

8
Documentation/git-cvsexportcommit.txt

@ -8,7 +8,7 @@ git-cvsexportcommit - Export a commit to a CVS checkout @@ -8,7 +8,7 @@ git-cvsexportcommit - Export a commit to a CVS checkout

SYNOPSIS
--------
'git-cvsexportcommit' [-h] [-v] [-c] [-p] [-f] [-m msgprefix] [PARENTCOMMIT] COMMITID
'git-cvsexportcommit' [-h] [-v] [-c] [-p] [-a] [-f] [-m msgprefix] [PARENTCOMMIT] COMMITID


DESCRIPTION
@ -36,9 +36,13 @@ OPTIONS @@ -36,9 +36,13 @@ OPTIONS
commit if any hunks fail to apply or there were other problems.

-p::
Be pedantic (paranoid) when applying patches. Invokes patch with
Be pedantic (paranoid) when applying patches. Invokes patch with
--fuzz=0

-a::
Add authorship information. Adds Author line, and Committer (if
different from Author) to the message.

-f::
Force the merge even if the files are not up to date.


13
Documentation/git-daemon.txt

@ -11,7 +11,7 @@ SYNOPSIS @@ -11,7 +11,7 @@ SYNOPSIS
'git-daemon' [--verbose] [--syslog] [--inetd | --port=n] [--export-all]
[--timeout=n] [--init-timeout=n] [--strict-paths]
[--base-path=path] [--user-path | --user-path=path]
[directory...]
[--reuseaddr] [--detach] [--pid-file=file] [directory...]

DESCRIPTION
-----------
@ -82,6 +82,17 @@ OPTIONS @@ -82,6 +82,17 @@ OPTIONS
--verbose::
Log details about the incoming connections and requested files.

--reuseaddr::
Use SO_REUSEADDR when binding the listening socket.
This allows the server to restart without waiting for
old connections to time out.

--detach::
Detach from the shell. Implies --syslog.

--pid-file=file::
Save the process id in 'file'.

<directory>::
A directory to add to the whitelist of allowed directories. Unless
--strict-paths is specified this will also include subdirectories

16
Documentation/git-format-patch.txt

@ -9,8 +9,9 @@ git-format-patch - Prepare patches for e-mail submission @@ -9,8 +9,9 @@ git-format-patch - Prepare patches for e-mail submission
SYNOPSIS
--------
[verse]
'git-format-patch' [-n | -k] [-o <dir> | --stdout] [--attach]
'git-format-patch' [-n | -k] [-o <dir> | --stdout] [--attach] [--thread]
[-s | --signoff] [--diff-options] [--start-number <n>]
[--in-reply-to=Message-Id]
<since>[..<until>]

DESCRIPTION
@ -35,6 +36,10 @@ they are created in the current working directory. @@ -35,6 +36,10 @@ they are created in the current working directory.
If -n is specified, instead of "[PATCH] Subject", the first line
is formatted as "[PATCH n/m] Subject".

If given --thread, git-format-patch will generate In-Reply-To and
References headers to make the second and subsequent patch mails appear
as replies to the first mail; this also generates a Message-Id header to
reference.

OPTIONS
-------
@ -63,6 +68,15 @@ OPTIONS @@ -63,6 +68,15 @@ OPTIONS
--attach::
Create attachments instead of inlining patches.

--thread::
Add In-Reply-To and References headers to make the second and
subsequent mails appear as replies to the first. Also generates
the Message-Id header to reference.

--in-reply-to=Message-Id::
Make the first mail (or all the mails with --no-thread) appear as a
reply to the given Message-Id, which avoids breaking threads to
provide a new patch series.

CONFIGURATION
-------------

8
Documentation/git-http-fetch.txt

@ -8,7 +8,7 @@ git-http-fetch - downloads a remote git repository via HTTP @@ -8,7 +8,7 @@ git-http-fetch - downloads a remote git repository via HTTP

SYNOPSIS
--------
'git-http-fetch' [-c] [-t] [-a] [-d] [-v] [-w filename] [--recover] <commit> <url>
'git-http-fetch' [-c] [-t] [-a] [-d] [-v] [-w filename] [--recover] [--stdin] <commit> <url>

DESCRIPTION
-----------
@ -33,6 +33,12 @@ commit-id:: @@ -33,6 +33,12 @@ commit-id::
Writes the commit-id into the filename under $GIT_DIR/refs/<filename> on
the local end after the transfer is complete.

--stdin::
Instead of a commit id on the commandline (which is not expected in this
case), 'git-http-fetch' expects lines on stdin in the format

<commit-id>['\t'<filename-as-in--w>]

Author
------
Written by Linus Torvalds <torvalds@osdl.org>

6
Documentation/git-local-fetch.txt

@ -29,6 +29,12 @@ OPTIONS @@ -29,6 +29,12 @@ OPTIONS
Writes the commit-id into the filename under $GIT_DIR/refs/<filename> on
the local end after the transfer is complete.

--stdin::
Instead of a commit id on the commandline (which is not expected in this
case), 'git-local-fetch' expects lines on stdin in the format

<commit-id>['\t'<filename-as-in--w>]

Author
------
Written by Junio C Hamano <junkio@cox.net>

20
Documentation/git-tar-tree.txt

@ -37,7 +37,20 @@ OPTIONS @@ -37,7 +37,20 @@ OPTIONS
Instead of making a tar archive from local repository,
retrieve a tar archive from a remote repository.

Examples
CONFIGURATION
-------------
By default, file and directories modes are set to 0666 or 0777. It is
possible to change this by setting the "umask" variable in the
repository configuration as follows :

[tar]
umask = 002 ;# group friendly

The special umask value "user" indicates that the user's current umask
will be used instead. The default value remains 0, which means world
readable/writable files and directories.

EXAMPLES
--------
git tar-tree HEAD junk | (cd /var/tmp/ && tar xf -)::

@ -58,6 +71,11 @@ git tar-tree --remote=example.com:git.git v1.4.0 >git-1.4.0.tar:: @@ -58,6 +71,11 @@ git tar-tree --remote=example.com:git.git v1.4.0 >git-1.4.0.tar::

Get a tarball v1.4.0 from example.com.

git tar-tree HEAD:Documentation/ git-docs > git-1.4.0-docs.tar::

Put everything in the current head's Documentation/ directory
into 'git-1.4.0-docs.tar', with the prefix 'git-docs/'.

Author
------
Written by Rene Scharfe.

12
Documentation/git.txt

@ -8,7 +8,8 @@ git - the stupid content tracker @@ -8,7 +8,8 @@ git - the stupid content tracker

SYNOPSIS
--------
'git' [--version] [--exec-path[=GIT_EXEC_PATH]] [--help] COMMAND [ARGS]
'git' [--version] [--exec-path[=GIT_EXEC_PATH]] [-p|--paginate]
[--bare] [--git-dir=GIT_DIR] [--help] COMMAND [ARGS]

DESCRIPTION
-----------
@ -41,6 +42,15 @@ OPTIONS @@ -41,6 +42,15 @@ OPTIONS
environment variable. If no path is given 'git' will print
the current setting and then exit.

-p|--paginate::
Pipe all output into 'less' (or if set, $PAGER).

--git-dir=<path>::
Set the path to the repository. This can also be controlled by
setting the GIT_DIR environment variable.

--bare::
Same as --git-dir=`pwd`.

FURTHER DOCUMENTATION
---------------------

17
Documentation/urls.txt

@ -10,20 +10,21 @@ to name the remote repository: @@ -10,20 +10,21 @@ to name the remote repository:
- https://host.xz/path/to/repo.git/
- git://host.xz/path/to/repo.git/
- git://host.xz/~user/path/to/repo.git/
- ssh://+++[user@+++]host.xz/path/to/repo.git/
- ssh://+++[user@+++]host.xz/~user/path/to/repo.git/
- ssh://+++[user@+++]host.xz/~/path/to/repo.git
- ssh://{startsb}user@{endsb}host.xz/path/to/repo.git/
- ssh://{startsb}user@{endsb}host.xz/~user/path/to/repo.git/
- ssh://{startsb}user@{endsb}host.xz/~/path/to/repo.git
===============================================================

SSH Is the default transport protocol and also supports an
scp-like syntax. Both syntaxes support username expansion,
SSH is the default transport protocol. You can optionally specify
which user to log-in as, and an alternate, scp-like syntax is also
supported. Both syntaxes support username expansion,
as does the native git protocol. The following three are
identical to the last three above, respectively:

===============================================================
- host.xz:/path/to/repo.git/
- host.xz:~user/path/to/repo.git/
- host.xz:path/to/repo.git
- {startsb}user@{endsb}host.xz:/path/to/repo.git/
- {startsb}user@{endsb}host.xz:~user/path/to/repo.git/
- {startsb}user@{endsb}host.xz:path/to/repo.git
===============================================================

To sync with a local directory, use:

9
INSTALL

@ -13,6 +13,15 @@ that uses $prefix, the built results have some paths encoded, @@ -13,6 +13,15 @@ that uses $prefix, the built results have some paths encoded,
which are derived from $prefix, so "make all; make prefix=/usr
install" would not work.

Alternatively you can use autoconf generated ./configure script to
set up install paths (via config.mak.autogen), so you can write instead

$ autoconf ;# as yourself if ./configure doesn't exist yet
$ ./configure --prefix=/usr ;# as yourself
$ make all doc ;# as yourself
# make install install-doc ;# as root


Issues of note:

- git normally installs a helper script wrapper called "git", which

57
Makefile

@ -37,6 +37,18 @@ all: @@ -37,6 +37,18 @@ all:
# tests. These tests take up a significant amount of the total test time
# but are not needed unless you plan to talk to SVN repos.
#
# Define NO_FINK if you are building on Darwin/Mac OS X, have Fink
# installed in /sw, but don't want GIT to link against any libraries
# installed there. If defined you may specify your own (or Fink's)
# include directories and library directories by defining CFLAGS
# and LDFLAGS appropriately.
#
# Define NO_DARWIN_PORTS if you are building on Darwin/Mac OS X,
# have DarwinPorts installed in /opt/local, but don't want GIT to
# link against any libraries installed there. If defined you may
# specify your own (or DarwinPort's) include directories and
# library directories by defining CFLAGS and LDFLAGS appropriately.
#
# Define PPC_SHA1 environment variable when running make to make use of
# a bundled SHA1 routine optimized for PowerPC.
#
@ -104,6 +116,8 @@ template_dir = $(prefix)/share/git-core/templates/ @@ -104,6 +116,8 @@ template_dir = $(prefix)/share/git-core/templates/
GIT_PYTHON_DIR = $(prefix)/share/git-core/python
# DESTDIR=

export prefix bindir gitexecdir template_dir GIT_PYTHON_DIR

CC = gcc
AR = ar
TAR = tar
@ -137,7 +151,7 @@ SCRIPT_PERL = \ @@ -137,7 +151,7 @@ SCRIPT_PERL = \
git-archimport.perl git-cvsimport.perl git-relink.perl \
git-shortlog.perl git-rerere.perl \
git-annotate.perl git-cvsserver.perl \
git-svnimport.perl git-mv.perl git-cvsexportcommit.perl \
git-svnimport.perl git-cvsexportcommit.perl \
git-send-email.perl git-svn.perl

SCRIPT_PYTHON = \
@ -179,7 +193,7 @@ BUILT_INS = git-log$X git-whatchanged$X git-show$X git-update-ref$X \ @@ -179,7 +193,7 @@ BUILT_INS = git-log$X git-whatchanged$X git-show$X git-update-ref$X \
git-read-tree$X git-commit-tree$X git-write-tree$X \
git-apply$X git-show-branch$X git-diff-files$X git-update-index$X \
git-diff-index$X git-diff-stages$X git-diff-tree$X git-cat-file$X \
git-fmt-merge-msg$X git-prune$X
git-fmt-merge-msg$X git-prune$X git-mv$X

# what 'all' will build and 'install' will install, in gitexecdir
ALL_PROGRAMS = $(PROGRAMS) $(SIMPLE_PROGRAMS) $(SCRIPTS)
@ -208,7 +222,7 @@ LIB_H = \ @@ -208,7 +222,7 @@ LIB_H = \
blob.h cache.h commit.h csum-file.h delta.h \
diff.h object.h pack.h pkt-line.h quote.h refs.h \
run-command.h strbuf.h tag.h tree.h git-compat-util.h revision.h \
tree-walk.h log-tree.h dir.h
tree-walk.h log-tree.h dir.h path-list.h unpack-trees.h

DIFF_OBJS = \
diff.o diff-lib.o diffcore-break.o diffcore-order.o \
@ -223,7 +237,7 @@ LIB_OBJS = \ @@ -223,7 +237,7 @@ LIB_OBJS = \
server-info.o setup.o sha1_file.o sha1_name.o strbuf.o \
tag.o tree.o usage.o config.o environment.o ctype.o copy.o \
fetch-clone.o revision.o pager.o tree-walk.o xdiff-interface.o \
alloc.o merge-file.o $(DIFF_OBJS)
alloc.o merge-file.o path-list.o unpack-trees.o $(DIFF_OBJS)

BUILTIN_OBJS = \
builtin-log.o builtin-help.o builtin-count.o builtin-diff.o builtin-push.o \
@ -235,7 +249,8 @@ BUILTIN_OBJS = \ @@ -235,7 +249,8 @@ BUILTIN_OBJS = \
builtin-apply.o builtin-show-branch.o builtin-diff-files.o \
builtin-diff-index.o builtin-diff-stages.o builtin-diff-tree.o \
builtin-cat-file.o builtin-mailsplit.o builtin-stripspace.o \
builtin-update-ref.o builtin-fmt-merge-msg.o builtin-prune.o
builtin-update-ref.o builtin-fmt-merge-msg.o builtin-prune.o \
builtin-mv.o

GITLIBS = $(LIB_FILE) $(XDIFF_LIB)
LIBS = $(GITLIBS) -lz
@ -251,19 +266,24 @@ LIBS = $(GITLIBS) -lz @@ -251,19 +266,24 @@ LIBS = $(GITLIBS) -lz
ifeq ($(uname_S),Linux)
NO_STRLCPY = YesPlease
endif
ifeq ($(uname_S),GNU/kFreeBSD)
NO_STRLCPY = YesPlease
endif
ifeq ($(uname_S),Darwin)
NEEDS_SSL_WITH_CRYPTO = YesPlease
NEEDS_LIBICONV = YesPlease
NO_STRLCPY = YesPlease
## fink
ifeq ($(shell test -d /sw/lib && echo y),y)
ALL_CFLAGS += -I/sw/include
ALL_LDFLAGS += -L/sw/lib
ifndef NO_FINK
ifeq ($(shell test -d /sw/lib && echo y),y)
ALL_CFLAGS += -I/sw/include
ALL_LDFLAGS += -L/sw/lib
endif
endif
## darwinports
ifeq ($(shell test -d /opt/local/lib && echo y),y)
ALL_CFLAGS += -I/opt/local/include
ALL_LDFLAGS += -L/opt/local/lib
ifndef NO_DARWIN_PORTS
ifeq ($(shell test -d /opt/local/lib && echo y),y)
ALL_CFLAGS += -I/opt/local/include
ALL_LDFLAGS += -L/opt/local/lib
endif
endif
endif
ifeq ($(uname_S),SunOS)
@ -337,6 +357,7 @@ ifneq (,$(findstring arm,$(uname_M))) @@ -337,6 +357,7 @@ ifneq (,$(findstring arm,$(uname_M)))
ARM_SHA1 = YesPlease
endif

-include config.mak.autogen
-include config.mak

ifdef WITH_OWN_SUBPROCESS_PY
@ -562,7 +583,7 @@ git-instaweb: git-instaweb.sh gitweb/gitweb.cgi gitweb/gitweb.css @@ -562,7 +583,7 @@ git-instaweb: git-instaweb.sh gitweb/gitweb.cgi gitweb/gitweb.css
-e '/@@GITWEB_CGI@@/d' \
-e '/@@GITWEB_CSS@@/r gitweb/gitweb.css' \
-e '/@@GITWEB_CSS@@/d' \
$@.sh > $@+
$@.sh | sed "s|/usr/bin/git|$(bindir)/git|" > $@+
chmod +x $@+
mv $@+ $@

@ -599,6 +620,8 @@ $(SIMPLE_PROGRAMS) : git-%$X : %.o @@ -599,6 +620,8 @@ $(SIMPLE_PROGRAMS) : git-%$X : %.o
$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \
$(LIB_FILE) $(SIMPLE_LIB)

ssh-pull.o: ssh-fetch.c
ssh-push.o: ssh-upload.c
git-local-fetch$X: fetch.o
git-ssh-fetch$X: rsh.o fetch.o
git-ssh-upload$X: rsh.o
@ -745,8 +768,8 @@ dist-doc: @@ -745,8 +768,8 @@ dist-doc:
rm -fr .doc-tmp-dir
mkdir .doc-tmp-dir .doc-tmp-dir/man1 .doc-tmp-dir/man7
$(MAKE) -C Documentation DESTDIR=./ \
man1=../.doc-tmp-dir/man1 \
man7=../.doc-tmp-dir/man7 \
man1dir=../.doc-tmp-dir/man1 \
man7dir=../.doc-tmp-dir/man7 \
install
cd .doc-tmp-dir && $(TAR) cf ../$(manpages).tar .
gzip -n -9 -f $(manpages).tar
@ -759,6 +782,8 @@ clean: @@ -759,6 +782,8 @@ clean:
$(LIB_FILE) $(XDIFF_LIB)
rm -f $(ALL_PROGRAMS) $(BUILT_INS) git$X
rm -f *.spec *.pyc *.pyo */*.pyc */*.pyo common-cmds.h TAGS tags
rm -rf autom4te.cache
rm -f config.log config.mak.autogen configure config.status config.cache
rm -rf $(GIT_TARNAME) .doc-tmp-dir
rm -f $(GIT_TARNAME).tar.gz git-core_$(GIT_VERSION)-*.tar.gz
rm -f $(htmldocs).tar.gz $(manpages).tar.gz

2
blame.c

@ -834,7 +834,7 @@ int main(int argc, const char **argv) @@ -834,7 +834,7 @@ int main(int argc, const char **argv)
}


init_revisions(&rev);
init_revisions(&rev, setup_git_directory());
rev.remove_empty_trees = 1;
rev.topo_order = 1;
rev.prune_fn = simplify_commit;

46
builtin-add.c

@ -21,8 +21,7 @@ static void prune_directory(struct dir_struct *dir, const char **pathspec, int p @@ -21,8 +21,7 @@ static void prune_directory(struct dir_struct *dir, const char **pathspec, int p

for (specs = 0; pathspec[specs]; specs++)
/* nothing */;
seen = xmalloc(specs);
memset(seen, 0, specs);
seen = xcalloc(specs, 1);

src = dst = dir->entries;
i = dir->nr;
@ -83,52 +82,12 @@ static void fill_directory(struct dir_struct *dir, const char **pathspec) @@ -83,52 +82,12 @@ static void fill_directory(struct dir_struct *dir, const char **pathspec)
prune_directory(dir, pathspec, baselen);
}

static int add_file_to_index(const char *path, int verbose)
{
int size, namelen;
struct stat st;
struct cache_entry *ce;

if (lstat(path, &st))
die("%s: unable to stat (%s)", path, strerror(errno));

if (!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode))
die("%s: can only add regular files or symbolic links", path);

namelen = strlen(path);
size = cache_entry_size(namelen);
ce = xcalloc(1, size);
memcpy(ce->name, path, namelen);
ce->ce_flags = htons(namelen);
fill_stat_cache_info(ce, &st);

ce->ce_mode = create_ce_mode(st.st_mode);
if (!trust_executable_bit) {
/* If there is an existing entry, pick the mode bits
* from it.
*/
int pos = cache_name_pos(path, namelen);
if (pos >= 0)
ce->ce_mode = active_cache[pos]->ce_mode;
}

if (index_path(ce->sha1, path, &st, 1))
die("unable to index file %s", path);
if (add_cache_entry(ce, ADD_CACHE_OK_TO_ADD))
die("unable to add %s to index",path);
if (verbose)
printf("add '%s'\n", path);
cache_tree_invalidate_path(active_cache_tree, path);
return 0;
}

static struct lock_file lock_file;

int cmd_add(int argc, const char **argv, char **envp)
int cmd_add(int argc, const char **argv, const char *prefix)
{
int i, newfd;
int verbose = 0, show_only = 0;
const char *prefix = setup_git_directory();
const char **pathspec;
struct dir_struct dir;

@ -160,7 +119,6 @@ int cmd_add(int argc, const char **argv, char **envp) @@ -160,7 +119,6 @@ int cmd_add(int argc, const char **argv, char **envp)
}
die(builtin_add_usage);
}
git_config(git_default_config);
pathspec = get_pathspec(prefix, argv + i);

fill_directory(&dir, pathspec);

145
builtin-apply.c

@ -120,7 +120,7 @@ struct fragment { @@ -120,7 +120,7 @@ struct fragment {
struct patch {
char *new_name, *old_name, *def_name;
unsigned int old_mode, new_mode;
int is_rename, is_copy, is_new, is_delete, is_binary;
int is_rename, is_copy, is_new, is_delete, is_binary, is_reverse;
#define BINARY_DELTA_DEFLATED 1
#define BINARY_LITERAL_DEFLATED 2
unsigned long deflate_origlen;
@ -1119,6 +1119,34 @@ static int parse_chunk(char *buffer, unsigned long size, struct patch *patch) @@ -1119,6 +1119,34 @@ static int parse_chunk(char *buffer, unsigned long size, struct patch *patch)
return offset + hdrsize + patchsize;
}

#define swap(a,b) myswap((a),(b),sizeof(a))

#define myswap(a, b, size) do { \
unsigned char mytmp[size]; \
memcpy(mytmp, &a, size); \
memcpy(&a, &b, size); \
memcpy(&b, mytmp, size); \
} while (0)

static void reverse_patches(struct patch *p)
{
for (; p; p = p->next) {
struct fragment *frag = p->fragments;

swap(p->new_name, p->old_name);
swap(p->new_mode, p->old_mode);
swap(p->is_new, p->is_delete);
swap(p->lines_added, p->lines_deleted);
swap(p->old_sha1_prefix, p->new_sha1_prefix);

for (; frag; frag = frag->next) {
swap(frag->newpos, frag->oldpos);
swap(frag->newlines, frag->oldlines);
}
p->is_reverse = !p->is_reverse;
}
}

static const char pluses[] = "++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++";
static const char minuses[]= "----------------------------------------------------------------------";

@ -1336,7 +1364,7 @@ static int apply_line(char *output, const char *patch, int plen) @@ -1336,7 +1364,7 @@ static int apply_line(char *output, const char *patch, int plen)
}

static int apply_one_fragment(struct buffer_desc *desc, struct fragment *frag,
int inaccurate_eof)
int reverse, int inaccurate_eof)
{
int match_beginning, match_end;
char *buf = desc->buffer;
@ -1350,6 +1378,7 @@ static int apply_one_fragment(struct buffer_desc *desc, struct fragment *frag, @@ -1350,6 +1378,7 @@ static int apply_one_fragment(struct buffer_desc *desc, struct fragment *frag,
int pos, lines;

while (size > 0) {
char first;
int len = linelen(patch, size);
int plen;

@ -1366,16 +1395,23 @@ static int apply_one_fragment(struct buffer_desc *desc, struct fragment *frag, @@ -1366,16 +1395,23 @@ static int apply_one_fragment(struct buffer_desc *desc, struct fragment *frag,
plen = len-1;
if (len < size && patch[len] == '\\')
plen--;
switch (*patch) {
first = *patch;
if (reverse) {
if (first == '-')
first = '+';
else if (first == '+')
first = '-';
}
switch (first) {
case ' ':
case '-':
memcpy(old + oldsize, patch + 1, plen);
oldsize += plen;
if (*patch == '-')
if (first == '-')
break;
/* Fall-through for ' ' */
case '+':
if (*patch != '+' || !no_add)
if (first != '+' || !no_add)
newsize += apply_line(new + newsize, patch,
plen);
break;
@ -1499,6 +1535,12 @@ static int apply_binary_fragment(struct buffer_desc *desc, struct patch *patch) @@ -1499,6 +1535,12 @@ static int apply_binary_fragment(struct buffer_desc *desc, struct patch *patch)
void *data;
void *result;

/* Binary patch is irreversible */
if (patch->is_reverse)
return error("cannot reverse-apply a binary patch to '%s'",
patch->new_name
? patch->new_name : patch->old_name);

data = inflate_it(fragment->patch, fragment->size,
patch->deflate_origlen);
if (!data)
@ -1615,7 +1657,8 @@ static int apply_fragments(struct buffer_desc *desc, struct patch *patch) @@ -1615,7 +1657,8 @@ static int apply_fragments(struct buffer_desc *desc, struct patch *patch)
return apply_binary(desc, patch);

while (frag) {
if (apply_one_fragment(desc, frag, patch->inaccurate_eof) < 0)
if (apply_one_fragment(desc, frag, patch->is_reverse,
patch->inaccurate_eof) < 0)
return error("patch failed: %s:%ld",
name, frag->oldpos);
frag = frag->next;
@ -1664,13 +1707,14 @@ static int apply_data(struct patch *patch, struct stat *st, struct cache_entry * @@ -1664,13 +1707,14 @@ static int apply_data(struct patch *patch, struct stat *st, struct cache_entry *
return 0;
}

static int check_patch(struct patch *patch)
static int check_patch(struct patch *patch, struct patch *prev_patch)
{
struct stat st;
const char *old_name = patch->old_name;
const char *new_name = patch->new_name;
const char *name = old_name ? old_name : new_name;
struct cache_entry *ce = NULL;
int ok_if_exists;

if (old_name) {
int changed = 0;
@ -1728,13 +1772,33 @@ static int check_patch(struct patch *patch) @@ -1728,13 +1772,33 @@ static int check_patch(struct patch *patch)
old_name, st_mode, patch->old_mode);
}

if (new_name && prev_patch && prev_patch->is_delete &&
!strcmp(prev_patch->old_name, new_name))
/* A type-change diff is always split into a patch to
* delete old, immediately followed by a patch to
* create new (see diff.c::run_diff()); in such a case
* it is Ok that the entry to be deleted by the
* previous patch is still in the working tree and in
* the index.
*/
ok_if_exists = 1;
else
ok_if_exists = 0;

if (new_name && (patch->is_new | patch->is_rename | patch->is_copy)) {
if (check_index && cache_name_pos(new_name, strlen(new_name)) >= 0)
if (check_index &&
cache_name_pos(new_name, strlen(new_name)) >= 0 &&
!ok_if_exists)
return error("%s: already exists in index", new_name);
if (!cached) {
if (!lstat(new_name, &st))
return error("%s: already exists in working directory", new_name);
if (errno != ENOENT)
struct stat nst;
if (!lstat(new_name, &nst)) {
if (S_ISDIR(nst.st_mode) || ok_if_exists)
; /* ok */
else
return error("%s: already exists in working directory", new_name);
}
else if ((errno != ENOENT) && (errno != ENOTDIR))
return error("%s: %s", new_name, strerror(errno));
}
if (!patch->new_mode) {
@ -1762,10 +1826,13 @@ static int check_patch(struct patch *patch) @@ -1762,10 +1826,13 @@ static int check_patch(struct patch *patch)

static int check_patch_list(struct patch *patch)
{
struct patch *prev_patch = NULL;
int error = 0;

for (;patch ; patch = patch->next)
error |= check_patch(patch);
for (prev_patch = NULL; patch ; patch = patch->next) {
error |= check_patch(patch, prev_patch);
prev_patch = patch;
}
return error;
}

@ -2010,6 +2077,16 @@ static void create_one_file(char *path, unsigned mode, const char *buf, unsigned @@ -2010,6 +2077,16 @@ static void create_one_file(char *path, unsigned mode, const char *buf, unsigned
return;
}

if (errno == EEXIST || errno == EACCES) {
/* We may be trying to create a file where a directory
* used to be.
*/
struct stat st;
errno = 0;
if (!lstat(path, &st) && S_ISDIR(st.st_mode) && !rmdir(path))
errno = EEXIST;
}

if (errno == EEXIST) {
unsigned int nr = getpid();

@ -2044,32 +2121,42 @@ static void create_file(struct patch *patch) @@ -2044,32 +2121,42 @@ static void create_file(struct patch *patch)
cache_tree_invalidate_path(active_cache_tree, path);
}

static void write_out_one_result(struct patch *patch)
/* phase zero is to remove, phase one is to create */
static void write_out_one_result(struct patch *patch, int phase)
{
if (patch->is_delete > 0) {
remove_file(patch);
if (phase == 0)
remove_file(patch);
return;
}
if (patch->is_new > 0 || patch->is_copy) {
create_file(patch);
if (phase == 1)
create_file(patch);
return;
}
/*
* Rename or modification boils down to the same
* thing: remove the old, write the new
*/
remove_file(patch);
if (phase == 0)
remove_file(patch);
if (phase == 1)
create_file(patch);
}

static void write_out_results(struct patch *list, int skipped_patch)
{
int phase;

if (!list && !skipped_patch)
die("No changes");

while (list) {
write_out_one_result(list);
list = list->next;
for (phase = 0; phase < 2; phase++) {
struct patch *l = list;
while (l) {
write_out_one_result(l, phase);
l = l->next;
}
}
}

@ -2098,7 +2185,8 @@ static int use_patch(struct patch *p) @@ -2098,7 +2185,8 @@ static int use_patch(struct patch *p)
return 1;
}

static int apply_patch(int fd, const char *filename, int inaccurate_eof)
static int apply_patch(int fd, const char *filename,
int reverse, int inaccurate_eof)
{
unsigned long offset, size;
char *buffer = read_patch_file(fd, &size);
@ -2118,6 +2206,8 @@ static int apply_patch(int fd, const char *filename, int inaccurate_eof) @@ -2118,6 +2206,8 @@ static int apply_patch(int fd, const char *filename, int inaccurate_eof)
nr = parse_chunk(buffer + offset, size, patch);
if (nr < 0)
break;
if (reverse)
reverse_patches(patch);
if (use_patch(patch)) {
patch_stats(patch);
*listp = patch;
@ -2178,10 +2268,11 @@ static int git_apply_config(const char *var, const char *value) @@ -2178,10 +2268,11 @@ static int git_apply_config(const char *var, const char *value)
}


int cmd_apply(int argc, const char **argv, char **envp)
int cmd_apply(int argc, const char **argv, const char *prefix)
{
int i;
int read_stdin = 1;
int reverse = 0;
int inaccurate_eof = 0;

const char *whitespace_option = NULL;
@ -2192,7 +2283,7 @@ int cmd_apply(int argc, const char **argv, char **envp) @@ -2192,7 +2283,7 @@ int cmd_apply(int argc, const char **argv, char **envp)
int fd;

if (!strcmp(arg, "-")) {
apply_patch(0, "<stdin>", inaccurate_eof);
apply_patch(0, "<stdin>", reverse, inaccurate_eof);
read_stdin = 0;
continue;
}
@ -2269,6 +2360,10 @@ int cmd_apply(int argc, const char **argv, char **envp) @@ -2269,6 +2360,10 @@ int cmd_apply(int argc, const char **argv, char **envp)
parse_whitespace_option(arg + 13);
continue;
}
if (!strcmp(arg, "-R") || !strcmp(arg, "--reverse")) {
reverse = 1;
continue;
}
if (!strcmp(arg, "--inaccurate-eof")) {
inaccurate_eof = 1;
continue;
@ -2289,12 +2384,12 @@ int cmd_apply(int argc, const char **argv, char **envp) @@ -2289,12 +2384,12 @@ int cmd_apply(int argc, const char **argv, char **envp)
usage(apply_usage);
read_stdin = 0;
set_default_whitespace_mode(whitespace_option);
apply_patch(fd, arg, inaccurate_eof);
apply_patch(fd, arg, reverse, inaccurate_eof);
close(fd);
}
set_default_whitespace_mode(whitespace_option);
if (read_stdin)
apply_patch(0, "<stdin>", inaccurate_eof);
apply_patch(0, "<stdin>", reverse, inaccurate_eof);
if (whitespace_error) {
if (squelch_whitespace_errors &&
squelch_whitespace_errors < whitespace_error) {

3
builtin-cat-file.c

@ -94,7 +94,7 @@ static int pprint_tag(const unsigned char *sha1, const char *buf, unsigned long @@ -94,7 +94,7 @@ static int pprint_tag(const unsigned char *sha1, const char *buf, unsigned long
return 0;
}

int cmd_cat_file(int argc, const char **argv, char **envp)
int cmd_cat_file(int argc, const char **argv, const char *prefix)
{
unsigned char sha1[20];
char type[20];
@ -102,7 +102,6 @@ int cmd_cat_file(int argc, const char **argv, char **envp) @@ -102,7 +102,6 @@ int cmd_cat_file(int argc, const char **argv, char **envp)
unsigned long size;
int opt;

setup_git_directory();
git_config(git_default_config);
if (argc != 3)
usage("git-cat-file [-t|-s|-e|-p|<type>] <sha1>");

2
builtin-check-ref-format.c

@ -6,7 +6,7 @@ @@ -6,7 +6,7 @@
#include "refs.h"
#include "builtin.h"

int cmd_check_ref_format(int argc, const char **argv, char **envp)
int cmd_check_ref_format(int argc, const char **argv, const char *prefix)
{
if (argc != 2)
usage("git check-ref-format refname");

4
builtin-commit-tree.c

@ -77,7 +77,7 @@ static int new_parent(int idx) @@ -77,7 +77,7 @@ static int new_parent(int idx)
return 1;
}

int cmd_commit_tree(int argc, const char **argv, char **envp)
int cmd_commit_tree(int argc, const char **argv, const char *prefix)
{
int i;
int parents = 0;
@ -88,8 +88,6 @@ int cmd_commit_tree(int argc, const char **argv, char **envp) @@ -88,8 +88,6 @@ int cmd_commit_tree(int argc, const char **argv, char **envp)
unsigned int size;

setup_ident();
setup_git_directory();

git_config(git_default_config);

if (argc < 2)

2
builtin-count.c

@ -67,7 +67,7 @@ static void count_objects(DIR *d, char *path, int len, int verbose, @@ -67,7 +67,7 @@ static void count_objects(DIR *d, char *path, int len, int verbose,
}
}

int cmd_count_objects(int ac, const char **av, char **ep)
int cmd_count_objects(int ac, const char **av, const char *prefix)
{
int i;
int verbose = 0;

4
builtin-diff-files.c

@ -13,13 +13,13 @@ static const char diff_files_usage[] = @@ -13,13 +13,13 @@ static const char diff_files_usage[] =
"git-diff-files [-q] [-0/-1/2/3 |-c|--cc] [<common diff options>] [<path>...]"
COMMON_DIFF_OPTIONS_HELP;

int cmd_diff_files(int argc, const char **argv, char **envp)
int cmd_diff_files(int argc, const char **argv, const char *prefix)
{
struct rev_info rev;
int silent = 0;

init_revisions(&rev, prefix);
git_config(git_default_config); /* no "diff" UI options */
init_revisions(&rev);
rev.abbrev = 0;

argc = setup_revisions(argc, argv, &rev, NULL);

4
builtin-diff-index.c

@ -9,14 +9,14 @@ static const char diff_cache_usage[] = @@ -9,14 +9,14 @@ static const char diff_cache_usage[] =
"[<common diff options>] <tree-ish> [<path>...]"
COMMON_DIFF_OPTIONS_HELP;

int cmd_diff_index(int argc, const char **argv, char **envp)
int cmd_diff_index(int argc, const char **argv, const char *prefix)
{
struct rev_info rev;
int cached = 0;
int i;

init_revisions(&rev, prefix);
git_config(git_default_config); /* no "diff" UI options */
init_revisions(&rev);
rev.abbrev = 0;

argc = setup_revisions(argc, argv, &rev, NULL);

3
builtin-diff-stages.c

@ -55,10 +55,9 @@ static void diff_stages(int stage1, int stage2, const char **pathspec) @@ -55,10 +55,9 @@ static void diff_stages(int stage1, int stage2, const char **pathspec)
}
}

int cmd_diff_stages(int ac, const char **av, char **envp)
int cmd_diff_stages(int ac, const char **av, const char *prefix)
{
int stage1, stage2;
const char *prefix = setup_git_directory();
const char **pathspec = NULL;

git_config(git_default_config); /* no "diff" UI options */

4
builtin-diff-tree.c

@ -59,7 +59,7 @@ static const char diff_tree_usage[] = @@ -59,7 +59,7 @@ static const char diff_tree_usage[] =
" --root include the initial commit as diff against /dev/null\n"
COMMON_DIFF_OPTIONS_HELP;

int cmd_diff_tree(int argc, const char **argv, char **envp)
int cmd_diff_tree(int argc, const char **argv, const char *prefix)
{
int nr_sha1;
char line[1000];
@ -67,9 +67,9 @@ int cmd_diff_tree(int argc, const char **argv, char **envp) @@ -67,9 +67,9 @@ int cmd_diff_tree(int argc, const char **argv, char **envp)
static struct rev_info *opt = &log_tree_opt;
int read_stdin = 0;

init_revisions(opt, prefix);
git_config(git_default_config); /* no "diff" UI options */
nr_sha1 = 0;
init_revisions(opt);
opt->abbrev = 0;
opt->diff = 1;
argc = setup_revisions(argc, argv, opt, NULL);

14
builtin-diff.c

@ -221,7 +221,7 @@ void add_head(struct rev_info *revs) @@ -221,7 +221,7 @@ void add_head(struct rev_info *revs)
add_pending_object(revs, obj, "HEAD");
}

int cmd_diff(int argc, const char **argv, char **envp)
int cmd_diff(int argc, const char **argv, const char *prefix)
{
int i;
struct rev_info rev;
@ -251,7 +251,7 @@ int cmd_diff(int argc, const char **argv, char **envp) @@ -251,7 +251,7 @@ int cmd_diff(int argc, const char **argv, char **envp)
*/

git_config(git_diff_ui_config);
init_revisions(&rev);
init_revisions(&rev, prefix);

argc = setup_revisions(argc, argv, &rev, NULL);
if (!rev.diffopt.output_format) {
@ -346,7 +346,15 @@ int cmd_diff(int argc, const char **argv, char **envp) @@ -346,7 +346,15 @@ int cmd_diff(int argc, const char **argv, char **envp)
return builtin_diff_index(&rev, argc, argv);
else if (ents == 2)
return builtin_diff_tree(&rev, argc, argv, ent);
else if ((ents == 3) && (ent[0].item->flags & UNINTERESTING)) {
/* diff A...B where there is one sane merge base between
* A and B. We have ent[0] == merge-base, ent[1] == A,
* and ent[2] == B. Show diff between the base and B.
*/
return builtin_diff_tree(&rev, argc, argv, ent);
}
else
return builtin_diff_combined(&rev, argc, argv, ent, ents);
return builtin_diff_combined(&rev, argc, argv,
ent, ents);
usage(builtin_diff_usage);
}

4
builtin-fmt-merge-msg.c

@ -242,7 +242,7 @@ static void shortlog(const char *name, unsigned char *sha1, @@ -242,7 +242,7 @@ static void shortlog(const char *name, unsigned char *sha1,
free_list(&subjects);
}

int cmd_fmt_merge_msg(int argc, char **argv, char **envp)
int cmd_fmt_merge_msg(int argc, char **argv, const char *prefix)
{
int limit = 20, i = 0;
char line[1024];
@ -342,7 +342,7 @@ int cmd_fmt_merge_msg(int argc, char **argv, char **envp) @@ -342,7 +342,7 @@ int cmd_fmt_merge_msg(int argc, char **argv, char **envp)
struct rev_info rev;

head = lookup_commit(head_sha1);
init_revisions(&rev);
init_revisions(&rev, prefix);
rev.commit_format = CMIT_FMT_ONELINE;
rev.ignore_merges = 1;
rev.limited = 1;

3
builtin-grep.c

@ -919,14 +919,13 @@ static const char emsg_missing_context_len[] = @@ -919,14 +919,13 @@ static const char emsg_missing_context_len[] =
static const char emsg_missing_argument[] =
"option requires an argument -%s";

int cmd_grep(int argc, const char **argv, char **envp)
int cmd_grep(int argc, const char **argv, const char *prefix)
{
int hit = 0;
int cached = 0;
int seen_dashdash = 0;
struct grep_opt opt;
struct object_array list = { 0, 0, NULL };
const char *prefix = setup_git_directory();
const char **paths = NULL;
int i;


6
builtin-help.c

@ -221,15 +221,15 @@ static void show_man_page(const char *git_cmd) @@ -221,15 +221,15 @@ static void show_man_page(const char *git_cmd)
execlp("man", "man", page, NULL);
}

int cmd_version(int argc, const char **argv, char **envp)
int cmd_version(int argc, const char **argv, const char *prefix)
{
printf("git version %s\n", git_version_string);
return 0;
}

int cmd_help(int argc, const char **argv, char **envp)
int cmd_help(int argc, const char **argv, const char *prefix)
{
const char *help_cmd = argv[1];
const char *help_cmd = argc > 1 ? argv[1] : NULL;
if (!help_cmd)
cmd_usage(0, git_exec_path(), NULL);
else if (!strcmp(help_cmd, "--all") || !strcmp(help_cmd, "-a"))

2
builtin-init-db.c

@ -250,7 +250,7 @@ static const char init_db_usage[] = @@ -250,7 +250,7 @@ static const char init_db_usage[] =
* On the other hand, it might just make lookup slower and messier. You
* be the judge. The default case is to have one DB per managed directory.
*/
int cmd_init_db(int argc, const char **argv, char **envp)
int cmd_init_db(int argc, const char **argv, const char *prefix)
{
const char *git_dir;
const char *sha1_dir;

71
builtin-log.c

@ -10,11 +10,13 @@ @@ -10,11 +10,13 @@
#include "revision.h"
#include "log-tree.h"
#include "builtin.h"
#include <time.h>
#include <sys/time.h>

/* this is in builtin-diff.c */
void add_head(struct rev_info *revs);

static void cmd_log_init(int argc, const char **argv, char **envp,
static void cmd_log_init(int argc, const char **argv, const char *prefix,
struct rev_info *rev)
{
rev->abbrev = DEFAULT_ABBREV;
@ -43,27 +45,27 @@ static int cmd_log_walk(struct rev_info *rev) @@ -43,27 +45,27 @@ static int cmd_log_walk(struct rev_info *rev)
return 0;
}

int cmd_whatchanged(int argc, const char **argv, char **envp)
int cmd_whatchanged(int argc, const char **argv, const char *prefix)
{
struct rev_info rev;

git_config(git_diff_ui_config);
init_revisions(&rev);
init_revisions(&rev, prefix);
rev.diff = 1;
rev.diffopt.recursive = 1;
rev.simplify_history = 0;
cmd_log_init(argc, argv, envp, &rev);
cmd_log_init(argc, argv, prefix, &rev);
if (!rev.diffopt.output_format)
rev.diffopt.output_format = DIFF_FORMAT_RAW;
return cmd_log_walk(&rev);
}

int cmd_show(int argc, const char **argv, char **envp)
int cmd_show(int argc, const char **argv, const char *prefix)
{
struct rev_info rev;

git_config(git_diff_ui_config);
init_revisions(&rev);
init_revisions(&rev, prefix);
rev.diff = 1;
rev.diffopt.recursive = 1;
rev.combine_merges = 1;
@ -71,18 +73,18 @@ int cmd_show(int argc, const char **argv, char **envp) @@ -71,18 +73,18 @@ int cmd_show(int argc, const char **argv, char **envp)
rev.always_show_header = 1;
rev.ignore_merges = 0;
rev.no_walk = 1;
cmd_log_init(argc, argv, envp, &rev);
cmd_log_init(argc, argv, prefix, &rev);
return cmd_log_walk(&rev);
}

int cmd_log(int argc, const char **argv, char **envp)
int cmd_log(int argc, const char **argv, const char *prefix)
{
struct rev_info rev;

git_config(git_diff_ui_config);
init_revisions(&rev);
init_revisions(&rev, prefix);
rev.always_show_header = 1;
cmd_log_init(argc, argv, envp, &rev);
cmd_log_init(argc, argv, prefix, &rev);
return cmd_log_walk(&rev);
}

@ -176,7 +178,7 @@ static int get_patch_id(struct commit *commit, struct diff_options *options, @@ -176,7 +178,7 @@ static int get_patch_id(struct commit *commit, struct diff_options *options,
return diff_flush_patch_id(options, sha1);
}

static void get_patch_ids(struct rev_info *rev, struct diff_options *options)
static void get_patch_ids(struct rev_info *rev, struct diff_options *options, const char *prefix)
{
struct rev_info check_rev;
struct commit *commit;
@ -201,7 +203,7 @@ static void get_patch_ids(struct rev_info *rev, struct diff_options *options) @@ -201,7 +203,7 @@ static void get_patch_ids(struct rev_info *rev, struct diff_options *options)
die("diff_setup_done failed");

/* given a range a..b get all patch ids for b..a */
init_revisions(&check_rev);
init_revisions(&check_rev, prefix);
o1->flags ^= UNINTERESTING;
o2->flags ^= UNINTERESTING;
add_pending_object(&check_rev, o1, "o1");
@ -226,7 +228,19 @@ static void get_patch_ids(struct rev_info *rev, struct diff_options *options) @@ -226,7 +228,19 @@ static void get_patch_ids(struct rev_info *rev, struct diff_options *options)
o2->flags = flags2;
}

int cmd_format_patch(int argc, const char **argv, char **envp)
static void gen_message_id(char *dest, unsigned int length, char *base)
{
const char *committer = git_committer_info(1);
const char *email_start = strrchr(committer, '<');
const char *email_end = strrchr(committer, '>');
if(!email_start || !email_end || email_start > email_end - 1)
die("Could not extract email from committer identity.");
snprintf(dest, length, "%s.%lu.git.%.*s", base,
(unsigned long) time(NULL),
(int)(email_end - email_start - 1), email_start + 1);
}

int cmd_format_patch(int argc, const char **argv, const char *prefix)
{
struct commit *commit;
struct commit **list = NULL;
@ -237,11 +251,15 @@ int cmd_format_patch(int argc, const char **argv, char **envp) @@ -237,11 +251,15 @@ int cmd_format_patch(int argc, const char **argv, char **envp)
int start_number = -1;
int keep_subject = 0;
int ignore_if_in_upstream = 0;
int thread = 0;
const char *in_reply_to = NULL;
struct diff_options patch_id_opts;
char *add_signoff = NULL;
char message_id[1024];
char ref_message_id[1024];

git_config(git_format_config);
init_revisions(&rev);
init_revisions(&rev, prefix);
rev.commit_format = CMIT_FMT_EMAIL;
rev.verbose_header = 1;
rev.diff = 1;
@ -304,6 +322,16 @@ int cmd_format_patch(int argc, const char **argv, char **envp) @@ -304,6 +322,16 @@ int cmd_format_patch(int argc, const char **argv, char **envp)
rev.mime_boundary = argv[i] + 9;
else if (!strcmp(argv[i], "--ignore-if-in-upstream"))
ignore_if_in_upstream = 1;
else if (!strcmp(argv[i], "--thread"))
thread = 1;
else if (!strncmp(argv[i], "--in-reply-to=", 14))
in_reply_to = argv[i] + 14;
else if (!strcmp(argv[i], "--in-reply-to")) {
i++;
if (i == argc)
die("Need a Message-Id for --in-reply-to");
in_reply_to = argv[i];
}
else
argv[j++] = argv[i];
}
@ -335,7 +363,7 @@ int cmd_format_patch(int argc, const char **argv, char **envp) @@ -335,7 +363,7 @@ int cmd_format_patch(int argc, const char **argv, char **envp)
}

if (ignore_if_in_upstream)
get_patch_ids(&rev, &patch_id_opts);
get_patch_ids(&rev, &patch_id_opts, prefix);

if (!use_stdout)
realstdout = fdopen(dup(1), "w");
@ -361,10 +389,23 @@ int cmd_format_patch(int argc, const char **argv, char **envp) @@ -361,10 +389,23 @@ int cmd_format_patch(int argc, const char **argv, char **envp)
if (numbered)
rev.total = total + start_number - 1;
rev.add_signoff = add_signoff;
rev.ref_message_id = in_reply_to;
while (0 <= --nr) {
int shown;
commit = list[nr];
rev.nr = total - nr + (start_number - 1);
/* Make the second and subsequent mails replies to the first */
if (thread) {
if (nr == (total - 2)) {
strncpy(ref_message_id, message_id,
sizeof(ref_message_id));
ref_message_id[sizeof(ref_message_id)-1]='\0';
rev.ref_message_id = ref_message_id;
}
gen_message_id(message_id, sizeof(message_id),
sha1_to_hex(commit->object.sha1));
rev.message_id = message_id;
}
if (!use_stdout)
reopen_stdout(commit, rev.nr, keep_subject);
shown = log_tree_commit(&rev, commit);

3
builtin-ls-files.c

@ -322,14 +322,13 @@ static const char ls_files_usage[] = @@ -322,14 +322,13 @@ static const char ls_files_usage[] =
"[ --exclude-per-directory=<filename> ] [--full-name] [--abbrev] "
"[--] [<file>]*";

int cmd_ls_files(int argc, const char **argv, char** envp)
int cmd_ls_files(int argc, const char **argv, const char *prefix)
{
int i;
int exc_given = 0;
struct dir_struct dir;

memset(&dir, 0, sizeof(dir));
prefix = setup_git_directory();
if (prefix)
prefix_offset = strlen(prefix);
git_config(git_default_config);

8
builtin-ls-tree.c

@ -18,7 +18,7 @@ static int abbrev = 0; @@ -18,7 +18,7 @@ static int abbrev = 0;
static int ls_options = 0;
static const char **pathspec;
static int chomp_prefix = 0;
static const char *prefix;
static const char *ls_tree_prefix;

static const char ls_tree_usage[] =
"git-ls-tree [-d] [-r] [-t] [-z] [--name-only] [--name-status] [--full-name] [--abbrev[=<n>]] <tree-ish> [path...]";
@ -71,7 +71,7 @@ static int show_tree(const unsigned char *sha1, const char *base, int baselen, @@ -71,7 +71,7 @@ static int show_tree(const unsigned char *sha1, const char *base, int baselen,
return 0;

if (chomp_prefix &&
(baselen < chomp_prefix || memcmp(prefix, base, chomp_prefix)))
(baselen < chomp_prefix || memcmp(ls_tree_prefix, base, chomp_prefix)))
return 0;

if (!(ls_options & LS_NAME_ONLY))
@ -85,13 +85,13 @@ static int show_tree(const unsigned char *sha1, const char *base, int baselen, @@ -85,13 +85,13 @@ static int show_tree(const unsigned char *sha1, const char *base, int baselen,
return retval;
}

int cmd_ls_tree(int argc, const char **argv, char **envp)
int cmd_ls_tree(int argc, const char **argv, const char *prefix)
{
unsigned char sha1[20];
struct tree *tree;

prefix = setup_git_directory();
git_config(git_default_config);
ls_tree_prefix = prefix;
if (prefix && *prefix)
chomp_prefix = strlen(prefix);
while (1 < argc && argv[1][0] == '-') {

4
builtin-mailinfo.c

@ -446,7 +446,7 @@ static int read_one_header_line(char *line, int sz, FILE *in) @@ -446,7 +446,7 @@ static int read_one_header_line(char *line, int sz, FILE *in)
break;
}
/* Count mbox From headers as headers */
if (!ofs && !memcmp(line, "From ", 5))
if (!ofs && (!memcmp(line, "From ", 5) || !memcmp(line, ">From ", 6)))
ofs = 1;
return ofs;
}
@ -836,7 +836,7 @@ int mailinfo(FILE *in, FILE *out, int ks, const char *encoding, @@ -836,7 +836,7 @@ int mailinfo(FILE *in, FILE *out, int ks, const char *encoding,
static const char mailinfo_usage[] =
"git-mailinfo [-k] [-u | --encoding=<encoding>] msg patch <mail >info";

int cmd_mailinfo(int argc, const char **argv, char **envp)
int cmd_mailinfo(int argc, const char **argv, const char *prefix)
{
/* NEEDSWORK: might want to do the optional .git/ directory
* discovery

2
builtin-mailsplit.c

@ -138,7 +138,7 @@ out: @@ -138,7 +138,7 @@ out:
free(name);
return ret;
}
int cmd_mailsplit(int argc, const char **argv, char **envp)
int cmd_mailsplit(int argc, const char **argv, const char *prefix)
{
int nr = 0, nr_prec = 4, ret;
int allow_bare = 0;

297
builtin-mv.c

@ -0,0 +1,297 @@ @@ -0,0 +1,297 @@
/*
* "git mv" builtin command
*
* Copyright (C) 2006 Johannes Schindelin
*/
#include <fnmatch.h>

#include "cache.h"
#include "builtin.h"
#include "dir.h"
#include "cache-tree.h"
#include "path-list.h"

static const char builtin_mv_usage[] =
"git-mv [-n] [-f] (<source> <destination> | [-k] <source>... <destination>)";

static const char **copy_pathspec(const char *prefix, const char **pathspec,
int count, int base_name)
{
const char **result = xmalloc((count + 1) * sizeof(const char *));
memcpy(result, pathspec, count * sizeof(const char *));
result[count] = NULL;
if (base_name) {
int i;
for (i = 0; i < count; i++) {
const char *last_slash = strrchr(result[i], '/');
if (last_slash)
result[i] = last_slash + 1;
}
}
return get_pathspec(prefix, result);
}

static void show_list(const char *label, struct path_list *list)
{
if (list->nr > 0) {
int i;
printf("%s", label);
for (i = 0; i < list->nr; i++)
printf("%s%s", i > 0 ? ", " : "", list->items[i].path);
putchar('\n');
}
}

static const char *add_slash(const char *path)
{
int len = strlen(path);
if (path[len - 1] != '/') {
char *with_slash = xmalloc(len + 2);
memcpy(with_slash, path, len);
strcat(with_slash + len, "/");
return with_slash;
}
return path;
}

static struct lock_file lock_file;

int cmd_mv(int argc, const char **argv, const char *prefix)
{
int i, newfd, count;
int verbose = 0, show_only = 0, force = 0, ignore_errors = 0;
const char **source, **destination, **dest_path;
enum update_mode { BOTH = 0, WORKING_DIRECTORY, INDEX } *modes;
struct stat st;
struct path_list overwritten = {NULL, 0, 0, 0};
struct path_list src_for_dst = {NULL, 0, 0, 0};
struct path_list added = {NULL, 0, 0, 0};
struct path_list deleted = {NULL, 0, 0, 0};
struct path_list changed = {NULL, 0, 0, 0};

git_config(git_default_config);

newfd = hold_lock_file_for_update(&lock_file, get_index_file());
if (newfd < 0)
die("unable to create new index file");

if (read_cache() < 0)
die("index file corrupt");

for (i = 1; i < argc; i++) {
const char *arg = argv[i];

if (arg[0] != '-')
break;
if (!strcmp(arg, "--")) {
i++;
break;
}
if (!strcmp(arg, "-n")) {
show_only = 1;
continue;
}
if (!strcmp(arg, "-f")) {
force = 1;
continue;
}
if (!strcmp(arg, "-k")) {
ignore_errors = 1;
continue;
}
die(builtin_mv_usage);
}
count = argc - i - 1;
if (count < 1)
usage(builtin_mv_usage);

source = copy_pathspec(prefix, argv + i, count, 0);
modes = xcalloc(count, sizeof(enum update_mode));
dest_path = copy_pathspec(prefix, argv + argc - 1, 1, 0);

if (!lstat(dest_path[0], &st) &&
S_ISDIR(st.st_mode)) {
dest_path[0] = add_slash(dest_path[0]);
destination = copy_pathspec(dest_path[0], argv + i, count, 1);
} else {
if (count != 1)
usage(builtin_mv_usage);
destination = dest_path;
}

/* Checking */
for (i = 0; i < count; i++) {
const char *bad = NULL;

if (show_only)
printf("Checking rename of '%s' to '%s'\n",
source[i], destination[i]);

if (lstat(source[i], &st) < 0)
bad = "bad source";

if (S_ISDIR(st.st_mode)) {
const char *dir = source[i], *dest_dir = destination[i];
int first, last, len = strlen(dir);

if (lstat(dest_dir, &st) == 0) {
bad = "cannot move directory over file";
goto next;
}

modes[i] = WORKING_DIRECTORY;

first = cache_name_pos(source[i], len);
if (first >= 0)
die ("Huh? %s/ is in index?", dir);

first = -1 - first;
for (last = first; last < active_nr; last++) {
const char *path = active_cache[last]->name;
if (strncmp(path, dir, len) || path[len] != '/')
break;
}

if (last - first < 1)
bad = "source directory is empty";
else if (!bad) {
int j, dst_len = strlen(dest_dir);

if (last - first > 0) {
source = realloc(source,
(count + last - first)
* sizeof(char *));
destination = realloc(destination,
(count + last - first)
* sizeof(char *));
modes = realloc(modes,
(count + last - first)
* sizeof(enum update_mode));
}

dest_dir = add_slash(dest_dir);

for (j = 0; j < last - first; j++) {
const char *path =
active_cache[first + j]->name;
source[count + j] = path;
destination[count + j] =
prefix_path(dest_dir, dst_len,
path + len);
modes[count + j] = INDEX;
}
count += last - first;
}

goto next;
}

if (!bad && lstat(destination[i], &st) == 0) {
bad = "destination exists";
if (force) {
/*
* only files can overwrite each other:
* check both source and destination
*/
if (S_ISREG(st.st_mode)) {
fprintf(stderr, "Warning: %s;"
" will overwrite!\n",
bad);
bad = NULL;
path_list_insert(destination[i],
&overwritten);
} else
bad = "Cannot overwrite";
}
}

if (!bad &&
!strncmp(destination[i], source[i], strlen(source[i])))
bad = "can not move directory into itself";

if (!bad && cache_name_pos(source[i], strlen(source[i])) < 0)
bad = "not under version control";

if (!bad) {
if (path_list_has_path(&src_for_dst, destination[i]))
bad = "multiple sources for the same target";
else
path_list_insert(destination[i], &src_for_dst);
}

next:
if (bad) {
if (ignore_errors) {
if (--count > 0) {
memmove(source + i, source + i + 1,
(count - i) * sizeof(char *));
memmove(destination + i,
destination + i + 1,
(count - i) * sizeof(char *));
}
} else
die ("%s, source=%s, destination=%s",
bad, source[i], destination[i]);
}
}

for (i = 0; i < count; i++) {
if (show_only || verbose)
printf("Renaming %s to %s\n",
source[i], destination[i]);
if (!show_only && modes[i] != INDEX &&
rename(source[i], destination[i]) < 0 &&
!ignore_errors)
die ("renaming %s failed: %s",
source[i], strerror(errno));

if (modes[i] == WORKING_DIRECTORY)
continue;

if (cache_name_pos(source[i], strlen(source[i])) >= 0) {
path_list_insert(source[i], &deleted);

/* destination can be a directory with 1 file inside */
if (path_list_has_path(&overwritten, destination[i]))
path_list_insert(destination[i], &changed);
else
path_list_insert(destination[i], &added);
} else
path_list_insert(destination[i], &added);
}

if (show_only) {
show_list("Changed : ", &changed);
show_list("Adding : ", &added);
show_list("Deleting : ", &deleted);
} else {
for (i = 0; i < changed.nr; i++) {
const char *path = changed.items[i].path;
int i = cache_name_pos(path, strlen(path));
struct cache_entry *ce = active_cache[i];

if (i < 0)
die ("Huh? Cache entry for %s unknown?", path);
refresh_cache_entry(ce, 0);
}

for (i = 0; i < added.nr; i++) {
const char *path = added.items[i].path;
add_file_to_index(path, verbose);
}

for (i = 0; i < deleted.nr; i++) {
const char *path = deleted.items[i].path;
remove_file_from_cache(path);
}

if (active_cache_changed) {
if (write_cache(newfd, active_cache, active_nr) ||
close(newfd) ||
commit_lock_file(&lock_file))
die("Unable to write new index file");
}
}

return 0;
}

4
builtin-prune.c

@ -217,7 +217,7 @@ static void add_cache_refs(void) @@ -217,7 +217,7 @@ static void add_cache_refs(void)
add_cache_tree(active_cache_tree);
}

int cmd_prune(int argc, const char **argv, char **envp)
int cmd_prune(int argc, const char **argv, const char *prefix)
{
int i;

@ -234,7 +234,7 @@ int cmd_prune(int argc, const char **argv, char **envp) @@ -234,7 +234,7 @@ int cmd_prune(int argc, const char **argv, char **envp)
* Set up revision parsing, and mark us as being interested
* in all object types, not just commits.
*/
init_revisions(&revs);
init_revisions(&revs, prefix);
revs.tag_objects = 1;
revs.blob_objects = 1;
revs.tree_objects = 1;

2
builtin-push.c

@ -270,7 +270,7 @@ static int do_push(const char *repo) @@ -270,7 +270,7 @@ static int do_push(const char *repo)
return 0;
}

int cmd_push(int argc, const char **argv, char **envp)
int cmd_push(int argc, const char **argv, const char *prefix)
{
int i;
const char *repo = "origin"; /* default repository */

862
builtin-read-tree.c

File diff suppressed because it is too large Load Diff

4
builtin-rev-list.c

@ -306,12 +306,12 @@ static void mark_edges_uninteresting(struct commit_list *list) @@ -306,12 +306,12 @@ static void mark_edges_uninteresting(struct commit_list *list)
}
}

int cmd_rev_list(int argc, const char **argv, char **envp)
int cmd_rev_list(int argc, const char **argv, const char *prefix)
{
struct commit_list *list;
int i;

init_revisions(&revs);
init_revisions(&revs, prefix);
revs.abbrev = 0;
revs.commit_format = CMIT_FMT_UNSPECIFIED;
argc = setup_revisions(argc, argv, &revs, NULL);

3
builtin-rev-parse.c

@ -209,11 +209,10 @@ static int try_difference(const char *arg) @@ -209,11 +209,10 @@ static int try_difference(const char *arg)
return 0;
}

int cmd_rev_parse(int argc, const char **argv, char **envp)
int cmd_rev_parse(int argc, const char **argv, const char *prefix)
{
int i, as_is = 0, verify = 0;
unsigned char sha1[20];
const char *prefix = setup_git_directory();

git_config(git_default_config);


6
builtin-rm.c

@ -43,11 +43,10 @@ static int remove_file(const char *name) @@ -43,11 +43,10 @@ static int remove_file(const char *name)

static struct lock_file lock_file;

int cmd_rm(int argc, const char **argv, char **envp)
int cmd_rm(int argc, const char **argv, const char *prefix)
{
int i, newfd;
int verbose = 0, show_only = 0, force = 0;
const char *prefix = setup_git_directory();
const char **pathspec;
char *seen;

@ -90,8 +89,7 @@ int cmd_rm(int argc, const char **argv, char **envp) @@ -90,8 +89,7 @@ int cmd_rm(int argc, const char **argv, char **envp)
seen = NULL;
for (i = 0; pathspec[i] ; i++)
/* nothing */;
seen = xmalloc(i);
memset(seen, 0, i);
seen = xcalloc(i, 1);

for (i = 0; i < active_nr; i++) {
struct cache_entry *ce = active_cache[i];

14
builtin-show-branch.c

@ -89,6 +89,8 @@ static int name_first_parent_chain(struct commit *c) @@ -89,6 +89,8 @@ static int name_first_parent_chain(struct commit *c)
name_parent(c, p);
i++;
}
else
break;
c = p;
}
return i;
@ -172,7 +174,7 @@ static void name_commits(struct commit_list *list, @@ -172,7 +174,7 @@ static void name_commits(struct commit_list *list,
static int mark_seen(struct commit *commit, struct commit_list **seen_p)
{
if (!commit->object.flags) {
insert_by_date(commit, seen_p);
commit_list_insert(commit, seen_p);
return 1;
}
return 0;
@ -218,9 +220,8 @@ static void join_revs(struct commit_list **list_p, @@ -218,9 +220,8 @@ static void join_revs(struct commit_list **list_p,
* Postprocess to complete well-poisoning.
*
* At this point we have all the commits we have seen in
* seen_p list (which happens to be sorted chronologically but
* it does not really matter). Mark anything that can be
* reached from uninteresting commits not interesting.
* seen_p list. Mark anything that can be reached from
* uninteresting commits not interesting.
*/
for (;;) {
int changed = 0;
@ -549,7 +550,7 @@ static int omit_in_dense(struct commit *commit, struct commit **rev, int n) @@ -549,7 +550,7 @@ static int omit_in_dense(struct commit *commit, struct commit **rev, int n)
return 0;
}

int cmd_show_branch(int ac, const char **av, char **envp)
int cmd_show_branch(int ac, const char **av, const char *prefix)
{
struct commit *rev[MAX_REVS], *commit;
struct commit_list *list = NULL, *seen = NULL;
@ -572,7 +573,6 @@ int cmd_show_branch(int ac, const char **av, char **envp) @@ -572,7 +573,6 @@ int cmd_show_branch(int ac, const char **av, char **envp)
int topics = 0;
int dense = 1;

setup_git_directory();
git_config(git_show_branch_config);

/* If nothing is specified, try the default first */
@ -701,6 +701,8 @@ int cmd_show_branch(int ac, const char **av, char **envp) @@ -701,6 +701,8 @@ int cmd_show_branch(int ac, const char **av, char **envp)
if (0 <= extra)
join_revs(&list, &seen, num_rev, extra);

sort_by_date(&seen);

if (merge_base)
return show_merge_base(seen, num_rev);


2
builtin-stripspace.c

@ -54,7 +54,7 @@ void stripspace(FILE *in, FILE *out) @@ -54,7 +54,7 @@ void stripspace(FILE *in, FILE *out)
fputc('\n', out);
}

int cmd_stripspace(int argc, const char **argv, char **envp)
int cmd_stripspace(int argc, const char **argv, const char *prefix)
{
stripspace(stdin, stdout);
return 0;

30
builtin-tar-tree.c

@ -20,6 +20,7 @@ static char block[BLOCKSIZE]; @@ -20,6 +20,7 @@ static char block[BLOCKSIZE];
static unsigned long offset;

static time_t archive_time;
static int tar_umask;

/* tries hard to write, either succeeds or dies in the attempt */
static void reliable_write(const void *data, unsigned long size)
@ -188,13 +189,13 @@ static void write_entry(const unsigned char *sha1, struct strbuf *path, @@ -188,13 +189,13 @@ static void write_entry(const unsigned char *sha1, struct strbuf *path,
} else {
if (S_ISDIR(mode)) {
*header.typeflag = TYPEFLAG_DIR;
mode |= 0777;
mode = (mode | 0777) & ~tar_umask;
} else if (S_ISLNK(mode)) {
*header.typeflag = TYPEFLAG_LNK;
mode |= 0777;
} else if (S_ISREG(mode)) {
*header.typeflag = TYPEFLAG_REG;
mode |= (mode & 0100) ? 0777 : 0666;
mode = (mode | ((mode & 0100) ? 0777 : 0666)) & ~tar_umask;
} else {
error("unsupported file mode: 0%o (SHA1: %s)",
mode, sha1_to_hex(sha1));
@ -293,7 +294,21 @@ static void traverse_tree(struct tree_desc *tree, struct strbuf *path) @@ -293,7 +294,21 @@ static void traverse_tree(struct tree_desc *tree, struct strbuf *path)
}
}

static int generate_tar(int argc, const char **argv, char** envp)
int git_tar_config(const char *var, const char *value)
{
if (!strcmp(var, "tar.umask")) {
if (!strcmp(value, "user")) {
tar_umask = umask(0);
umask(tar_umask);
} else {
tar_umask = git_config_int(var, value);
}
return 0;
}
return git_default_config(var, value);
}

static int generate_tar(int argc, const char **argv, const char *prefix)
{
unsigned char sha1[20], tree_sha1[20];
struct commit *commit;
@ -304,8 +319,7 @@ static int generate_tar(int argc, const char **argv, char** envp) @@ -304,8 +319,7 @@ static int generate_tar(int argc, const char **argv, char** envp)
current_path.alloc = PATH_MAX;
current_path.len = current_path.eof = 0;

setup_git_directory();
git_config(git_default_config);
git_config(git_tar_config);

switch (argc) {
case 3:
@ -387,19 +401,19 @@ static int remote_tar(int argc, const char **argv) @@ -387,19 +401,19 @@ static int remote_tar(int argc, const char **argv)
return !!ret;
}

int cmd_tar_tree(int argc, const char **argv, char **envp)
int cmd_tar_tree(int argc, const char **argv, const char *prefix)
{
if (argc < 2)
usage(tar_tree_usage);
if (!strncmp("--remote=", argv[1], 9))
return remote_tar(argc, argv);
return generate_tar(argc, argv, envp);
return generate_tar(argc, argv, prefix);
}

/* ustar header + extended global header content */
#define HEADERSIZE (2 * RECORDSIZE)

int cmd_get_tar_commit_id(int argc, const char **argv, char **envp)
int cmd_get_tar_commit_id(int argc, const char **argv, const char *prefix)
{
char buffer[HEADERSIZE];
struct ustar_header *header = (struct ustar_header *)buffer;

3
builtin-update-index.c

@ -476,12 +476,11 @@ static int do_reupdate(int ac, const char **av, @@ -476,12 +476,11 @@ static int do_reupdate(int ac, const char **av,
return 0;
}

int cmd_update_index(int argc, const char **argv, char **envp)
int cmd_update_index(int argc, const char **argv, const char *prefix)
{
int i, newfd, entries, has_errors = 0, line_termination = '\n';
int allow_options = 1;
int read_from_stdin = 0;
const char *prefix = setup_git_directory();
int prefix_length = prefix ? strlen(prefix) : 0;
char set_executable_bit = 0;
unsigned int refresh_flags = 0;

3
builtin-update-ref.c

@ -5,7 +5,7 @@ @@ -5,7 +5,7 @@
static const char git_update_ref_usage[] =
"git-update-ref <refname> <value> [<oldval>] [-m <reason>]";

int cmd_update_ref(int argc, const char **argv, char **envp)
int cmd_update_ref(int argc, const char **argv, const char *prefix)
{
const char *refname=NULL, *value=NULL, *oldval=NULL, *msg=NULL;
struct ref_lock *lock;
@ -13,7 +13,6 @@ int cmd_update_ref(int argc, const char **argv, char **envp) @@ -13,7 +13,6 @@ int cmd_update_ref(int argc, const char **argv, char **envp)
int i;

setup_ident();
setup_git_directory();
git_config(git_default_config);

for (i = 1; i < argc; i++) {

2
builtin-upload-tar.c

@ -15,7 +15,7 @@ static int nak(const char *reason) @@ -15,7 +15,7 @@ static int nak(const char *reason)
return 1;
}

int cmd_upload_tar(int argc, const char **argv, char **envp)
int cmd_upload_tar(int argc, const char **argv, const char *prefix)
{
int len;
const char *dir = argv[1];

4
builtin-write-tree.c

@ -60,14 +60,12 @@ int write_tree(unsigned char *sha1, int missing_ok, const char *prefix) @@ -60,14 +60,12 @@ int write_tree(unsigned char *sha1, int missing_ok, const char *prefix)
return 0;
}

int cmd_write_tree(int argc, const char **argv, char **envp)
int cmd_write_tree(int argc, const char **argv, const char *unused_prefix)
{
int missing_ok = 0, ret;
const char *prefix = NULL;
unsigned char sha1[20];

setup_git_directory();

while (1 < argc) {
const char *arg = argv[1];
if (!strcmp(arg, "--missing-ok"))

77
builtin.h

@ -15,53 +15,54 @@ void cmd_usage(int show_all, const char *exec_path, const char *fmt, ...) @@ -15,53 +15,54 @@ void cmd_usage(int show_all, const char *exec_path, const char *fmt, ...)
#endif
;

extern int cmd_help(int argc, const char **argv, char **envp);
extern int cmd_version(int argc, const char **argv, char **envp);
extern int cmd_help(int argc, const char **argv, const char *prefix);
extern int cmd_version(int argc, const char **argv, const char *prefix);

extern int cmd_whatchanged(int argc, const char **argv, char **envp);
extern int cmd_show(int argc, const char **argv, char **envp);
extern int cmd_log(int argc, const char **argv, char **envp);
extern int cmd_diff(int argc, const char **argv, char **envp);
extern int cmd_format_patch(int argc, const char **argv, char **envp);
extern int cmd_count_objects(int argc, const char **argv, char **envp);
extern int cmd_whatchanged(int argc, const char **argv, const char *prefix);
extern int cmd_show(int argc, const char **argv, const char *prefix);
extern int cmd_log(int argc, const char **argv, const char *prefix);
extern int cmd_diff(int argc, const char **argv, const char *prefix);
extern int cmd_format_patch(int argc, const char **argv, const char *prefix);
extern int cmd_count_objects(int argc, const char **argv, const char *prefix);

extern int cmd_prune(int argc, const char **argv, char **envp);
extern int cmd_prune(int argc, const char **argv, const char *prefix);

extern int cmd_push(int argc, const char **argv, char **envp);
extern int cmd_grep(int argc, const char **argv, char **envp);
extern int cmd_rm(int argc, const char **argv, char **envp);
extern int cmd_add(int argc, const char **argv, char **envp);
extern int cmd_rev_list(int argc, const char **argv, char **envp);
extern int cmd_check_ref_format(int argc, const char **argv, char **envp);
extern int cmd_init_db(int argc, const char **argv, char **envp);
extern int cmd_tar_tree(int argc, const char **argv, char **envp);
extern int cmd_upload_tar(int argc, const char **argv, char **envp);
extern int cmd_get_tar_commit_id(int argc, const char **argv, char **envp);
extern int cmd_ls_files(int argc, const char **argv, char **envp);
extern int cmd_ls_tree(int argc, const char **argv, char **envp);
extern int cmd_read_tree(int argc, const char **argv, char **envp);
extern int cmd_commit_tree(int argc, const char **argv, char **envp);
extern int cmd_apply(int argc, const char **argv, char **envp);
extern int cmd_show_branch(int argc, const char **argv, char **envp);
extern int cmd_diff_files(int argc, const char **argv, char **envp);
extern int cmd_diff_index(int argc, const char **argv, char **envp);
extern int cmd_diff_stages(int argc, const char **argv, char **envp);
extern int cmd_diff_tree(int argc, const char **argv, char **envp);
extern int cmd_cat_file(int argc, const char **argv, char **envp);
extern int cmd_rev_parse(int argc, const char **argv, char **envp);
extern int cmd_update_index(int argc, const char **argv, char **envp);
extern int cmd_update_ref(int argc, const char **argv, char **envp);
extern int cmd_fmt_merge_msg(int argc, const char **argv, char **envp);
extern int cmd_push(int argc, const char **argv, const char *prefix);
extern int cmd_grep(int argc, const char **argv, const char *prefix);
extern int cmd_rm(int argc, const char **argv, const char *prefix);
extern int cmd_add(int argc, const char **argv, const char *prefix);
extern int cmd_rev_list(int argc, const char **argv, const char *prefix);
extern int cmd_check_ref_format(int argc, const char **argv, const char *prefix);
extern int cmd_init_db(int argc, const char **argv, const char *prefix);
extern int cmd_tar_tree(int argc, const char **argv, const char *prefix);
extern int cmd_upload_tar(int argc, const char **argv, const char *prefix);
extern int cmd_get_tar_commit_id(int argc, const char **argv, const char *prefix);
extern int cmd_ls_files(int argc, const char **argv, const char *prefix);
extern int cmd_ls_tree(int argc, const char **argv, const char *prefix);
extern int cmd_read_tree(int argc, const char **argv, const char *prefix);
extern int cmd_commit_tree(int argc, const char **argv, const char *prefix);
extern int cmd_apply(int argc, const char **argv, const char *prefix);
extern int cmd_show_branch(int argc, const char **argv, const char *prefix);
extern int cmd_diff_files(int argc, const char **argv, const char *prefix);
extern int cmd_diff_index(int argc, const char **argv, const char *prefix);
extern int cmd_diff_stages(int argc, const char **argv, const char *prefix);
extern int cmd_diff_tree(int argc, const char **argv, const char *prefix);
extern int cmd_cat_file(int argc, const char **argv, const char *prefix);
extern int cmd_rev_parse(int argc, const char **argv, const char *prefix);
extern int cmd_update_index(int argc, const char **argv, const char *prefix);
extern int cmd_update_ref(int argc, const char **argv, const char *prefix);
extern int cmd_fmt_merge_msg(int argc, const char **argv, const char *prefix);
extern int cmd_mv(int argc, const char **argv, const char *prefix);

extern int cmd_write_tree(int argc, const char **argv, char **envp);
extern int cmd_write_tree(int argc, const char **argv, const char *prefix);
extern int write_tree(unsigned char *sha1, int missing_ok, const char *prefix);

extern int cmd_mailsplit(int argc, const char **argv, char **envp);
extern int cmd_mailsplit(int argc, const char **argv, const char *prefix);
extern int split_mbox(const char **mbox, const char *dir, int allow_bare, int nr_prec, int skip);

extern int cmd_mailinfo(int argc, const char **argv, char **envp);
extern int cmd_mailinfo(int argc, const char **argv, const char *prefix);
extern int mailinfo(FILE *in, FILE *out, int ks, const char *encoding, const char *msg, const char *patch);

extern int cmd_stripspace(int argc, const char **argv, char **envp);
extern int cmd_stripspace(int argc, const char **argv, const char *prefix);
extern void stripspace(FILE *in, FILE *out);
#endif

2
cache.h

@ -155,6 +155,7 @@ extern int add_cache_entry(struct cache_entry *ce, int option); @@ -155,6 +155,7 @@ extern int add_cache_entry(struct cache_entry *ce, int option);
extern struct cache_entry *refresh_cache_entry(struct cache_entry *ce, int really);
extern int remove_cache_entry_at(int pos);
extern int remove_file_from_cache(const char *path);
extern int add_file_to_index(const char *path, int verbose);
extern int ce_same_name(struct cache_entry *a, struct cache_entry *b);
extern int ce_match_stat(struct cache_entry *ce, struct stat *st, int);
extern int ce_modified(struct cache_entry *ce, struct stat *st, int);
@ -180,6 +181,7 @@ extern int commit_lock_file(struct lock_file *); @@ -180,6 +181,7 @@ extern int commit_lock_file(struct lock_file *);
extern void rollback_lock_file(struct lock_file *);

/* Environment bits from configuration mechanism */
extern int use_legacy_headers;
extern int trust_executable_bit;
extern int assume_unchanged;
extern int prefer_symlink_refs;

3
combine-diff.c

@ -639,8 +639,7 @@ static int show_patch_diff(struct combine_diff_path *elem, int num_parent, @@ -639,8 +639,7 @@ static int show_patch_diff(struct combine_diff_path *elem, int num_parent,
/* deleted file */
result_size = 0;
elem->mode = 0;
result = xmalloc(1);
result[0] = 0;
result = xcalloc(1, 1);
}
if (0 <= fd)
close(fd);

5
config.c

@ -279,6 +279,11 @@ int git_default_config(const char *var, const char *value) @@ -279,6 +279,11 @@ int git_default_config(const char *var, const char *value)
return 0;
}

if (!strcmp(var, "core.legacyheaders")) {
use_legacy_headers = git_config_bool(var, value);
return 0;
}

if (!strcmp(var, "core.compression")) {
int level = git_config_int(var, value);
if (level == -1)

24
config.mak.in

@ -0,0 +1,24 @@ @@ -0,0 +1,24 @@
# git Makefile configuration, included in main Makefile
# @configure_input@

CC = @CC@
AR = @AR@
TAR = @TAR@
#INSTALL = @INSTALL@ # needs install-sh or install.sh in sources

prefix = @prefix@
exec_prefix = @exec_prefix@
bindir = @bindir@
#gitexecdir = @libexecdir@/git-core/
datarootdir = @datarootdir@
template_dir = @datadir@/git-core/templates/
GIT_PYTHON_DIR = @datadir@/git-core/python

mandir=@mandir@

srcdir = @srcdir@
VPATH = @srcdir@

export exec_prefix mandir
export srcdir VPATH

183
configure.ac

@ -0,0 +1,183 @@ @@ -0,0 +1,183 @@
# -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.

AC_PREREQ(2.59)
AC_INIT([git], [1.4.1], [git@vger.kernel.org])

AC_CONFIG_SRCDIR([git.c])

config_file=config.mak.autogen
config_append=config.mak.append
config_in=config.mak.in

echo "# ${config_append}. Generated by configure." > "${config_append}"


## Definitions of macros
# GIT_CONF_APPEND_LINE(LINE)
# --------------------------
# Append LINE to file ${config_append}
AC_DEFUN([GIT_CONF_APPEND_LINE],
[echo "$1" >> "${config_append}"])# GIT_CONF_APPEND_LINE


## Checks for programs.
AC_MSG_NOTICE([CHECKS for programs])
#
AC_PROG_CC
#AC_PROG_INSTALL # needs install-sh or install.sh in sources
AC_CHECK_TOOL(AR, ar, :)
AC_CHECK_PROGS(TAR, [gtar tar])
#
# Define NO_PYTHON if you want to lose all benefits of the recursive merge.


## Checks for libraries.
AC_MSG_NOTICE([CHECKS for libraries])
#
# Define NO_OPENSSL environment variable if you do not have OpenSSL.
# Define NEEDS_SSL_WITH_CRYPTO if you need -lcrypto with -lssl (Darwin).
AC_CHECK_LIB([ssl], [SHA1_Init],[],
[AC_CHECK_LIB([crypto], [SHA1_INIT],
[GIT_CONF_APPEND_LINE(NEEDS_SSL_WITH_CRYPTO=YesPlease)],
[GIT_CONF_APPEND_LINE(NO_OPENSSL=YesPlease)])])
#
# Define NO_CURL if you do not have curl installed. git-http-pull and
# git-http-push are not built, and you cannot use http:// and https://
# transports.
AC_CHECK_LIB([curl], [curl_global_init],[],
[GIT_CONF_APPEND_LINE(NO_CURL=YesPlease)])
#
# Define NO_EXPAT if you do not have expat installed. git-http-push is
# not built, and you cannot push using http:// and https:// transports.
AC_CHECK_LIB([expat], [XML_ParserCreate],[],
[GIT_CONF_APPEND_LINE(NO_EXPAT=YesPlease)])
#
# Define NEEDS_LIBICONV if linking with libc is not enough (Darwin).
AC_CHECK_LIB([c], [iconv],[],
[AC_CHECK_LIB([iconv],[iconv],
[GIT_CONF_APPEND_LINE(NEEDS_LIBICONV=YesPlease)],[])])
#
# Define NEEDS_SOCKET if linking with libc is not enough (SunOS,
# Patrick Mauritz).
AC_CHECK_LIB([c], [socket],[],
[AC_CHECK_LIB([socket],[socket],
[GIT_CONF_APPEND_LINE(NEEDS_SOCKET=YesPlease)],[])])


## Checks for header files.


## Checks for typedefs, structures, and compiler characteristics.
AC_MSG_NOTICE([CHECKS for typedefs, structures, and compiler characteristics])
#
# Define NO_D_INO_IN_DIRENT if you don't have d_ino in your struct dirent.
AC_CHECK_MEMBER(struct dirent.d_ino,[],
[GIT_CONF_APPEND_LINE(NO_D_INO_IN_DIRENT=YesPlease)],
[#include <dirent.h>])
#
# Define NO_D_TYPE_IN_DIRENT if your platform defines DT_UNKNOWN but lacks
# d_type in struct dirent (latest Cygwin -- will be fixed soonish).
AC_CHECK_MEMBER(struct dirent.d_type,[],
[GIT_CONF_APPEND_LINE(NO_D_TYPE_IN_DIRENT=YesPlease)],
[#include <dirent.h>])
#
# Define NO_SOCKADDR_STORAGE if your platform does not have struct
# sockaddr_storage.
AC_CHECK_TYPE(struct sockaddr_storage,[],
[GIT_CONF_APPEND_LINE(NO_SOCKADDR_STORAGE=YesPlease)],
[#include <netinet/in.h>])


## Checks for library functions.
## (in default C library and libraries checked by AC_CHECK_LIB)
AC_MSG_NOTICE([CHECKS for library functions])
#
# Define NO_STRCASESTR if you don't have strcasestr.
AC_CHECK_FUNC(strcasestr,[],
[GIT_CONF_APPEND_LINE(NO_STRCASESTR=YesPlease)])
#
# Define NO_STRLCPY if you don't have strlcpy.
AC_CHECK_FUNC(strlcpy,[],
[GIT_CONF_APPEND_LINE(NO_STRLCPY=YesPlease)])
#
# Define NO_SETENV if you don't have setenv in the C library.
AC_CHECK_FUNC(setenv,[],
[GIT_CONF_APPEND_LINE(NO_SETENV=YesPlease)])
#
# Define NO_MMAP if you want to avoid mmap.
#
# Define NO_IPV6 if you lack IPv6 support and getaddrinfo().
#
# Define NO_ICONV if your libc does not properly support iconv.


## Other checks.
# Define USE_PIC if you need the main git objects to be built with -fPIC
# in order to build and link perl/Git.so. x86-64 seems to need this.
#
# Define NO_SYMLINK_HEAD if you never want .git/HEAD to be a symbolic link.
# Enable it on Windows. By default, symrefs are still used.
#
# Define WITH_OWN_SUBPROCESS_PY if you want to use with python 2.3.
#
# Define NO_ACCURATE_DIFF if your diff program at least sometimes misses
# a missing newline at the end of the file.


## Site configuration
## --with-PACKAGE[=ARG] and --without-PACKAGE
# Define NO_SVN_TESTS if you want to skip time-consuming SVN interopability
# tests. These tests take up a significant amount of the total test time
# but are not needed unless you plan to talk to SVN repos.
#
# Define MOZILLA_SHA1 environment variable when running make to make use of
# a bundled SHA1 routine coming from Mozilla. It is GPL'd and should be fast
# on non-x86 architectures (e.g. PowerPC), while the OpenSSL version (default
# choice) has very fast version optimized for i586.
#
# Define PPC_SHA1 environment variable when running make to make use of
# a bundled SHA1 routine optimized for PowerPC.
#
# Define ARM_SHA1 environment variable when running make to make use of
# a bundled SHA1 routine optimized for ARM.
#
# Define NO_OPENSSL environment variable if you do not have OpenSSL.
# This also implies MOZILLA_SHA1.
#
# Define NO_CURL if you do not have curl installed. git-http-pull and
# git-http-push are not built, and you cannot use http:// and https://
# transports.
#
# Define CURLDIR=/foo/bar if your curl header and library files are in
# /foo/bar/include and /foo/bar/lib directories.
#
# Define NO_EXPAT if you do not have expat installed. git-http-push is
# not built, and you cannot push using http:// and https:// transports.
#
# Define NO_MMAP if you want to avoid mmap.
#
# Define NO_PYTHON if you want to loose all benefits of the recursive merge.
#
## --enable-FEATURE[=ARG] and --disable-FEATURE
# Define COLLISION_CHECK below if you believe that SHA1's
# 1461501637330902918203684832716283019655932542976 hashes do not give you
# sufficient guarantee that no collisions between objects will ever happen.
#
# Define USE_NSEC below if you want git to care about sub-second file mtimes
# and ctimes. Note that you need recent glibc (at least 2.2.4) for this, and
# it will BREAK YOUR LOCAL DIFFS! show-diff and anything using it will likely
# randomly break unless your underlying filesystem supports those sub-second
# times (my ext3 doesn't).
#
# Define USE_STDEV below if you want git to care about the underlying device
# change being considered an inode change from the update-cache perspective.


## Output files
AC_CONFIG_FILES(["${config_file}":"${config_in}":"${config_append}"])
AC_OUTPUT


## Cleanup
rm -f "${config_append}"

4
contrib/emacs/Makefile

@ -3,9 +3,9 @@ @@ -3,9 +3,9 @@
EMACS = emacs

ELC = git.elc vc-git.elc
INSTALL = install
INSTALL ?= install
INSTALL_ELC = $(INSTALL) -m 644
prefix = $(HOME)
prefix ?= $(HOME)
emacsdir = $(prefix)/share/emacs/site-lisp

all: $(ELC)

31
contrib/emacs/git.el

@ -55,7 +55,8 @@ @@ -55,7 +55,8 @@
;;;; ------------------------------------------------------------

(defgroup git nil
"Git user interface")
"A user interface for the git versioning system."
:group 'tools)

(defcustom git-committer-name nil
"User name to use for commits.
@ -83,6 +84,12 @@ then to `add-log-mailing-address' and then to `user-mail-address'." @@ -83,6 +84,12 @@ then to `add-log-mailing-address' and then to `user-mail-address'."
:group 'git
:type 'boolean)

(defcustom git-reuse-status-buffer t
"Whether `git-status' should try to reuse an existing buffer
if there is already one that displays the same directory."
:group 'git
:type 'boolean)

(defcustom git-per-dir-ignore-file ".gitignore"
"Name of the per-directory ignore file."
:group 'git
@ -258,7 +265,7 @@ and returns the process output as a string." @@ -258,7 +265,7 @@ and returns the process output as a string."
(set-buffer (find-file-noselect ignore-name))
(goto-char (point-max))
(unless (zerop (current-column)) (insert "\n"))
(insert name "\n")
(insert "/" name "\n")
(sort-lines nil (point-min) (point-max))
(save-buffer))
(when created
@ -584,6 +591,8 @@ and returns the process output as a string." @@ -584,6 +591,8 @@ and returns the process output as a string."
(condition-case nil (delete-file ".git/MERGE_HEAD") (error nil))
(with-current-buffer buffer (erase-buffer))
(git-set-files-state files 'uptodate)
(when (file-directory-p ".git/rr-cache")
(git-run-command nil nil "rerere"))
(git-refresh-files)
(git-refresh-ewoc-hf git-status)
(message "Committed %s." commit))
@ -1001,12 +1010,28 @@ Commands: @@ -1001,12 +1010,28 @@ Commands:
(set (make-local-variable 'list-buffers-directory) default-directory)
(run-hooks 'git-status-mode-hook)))

(defun git-find-status-buffer (dir)
"Find the git status buffer handling a specified directory."
(let ((list (buffer-list))
(fulldir (expand-file-name dir))
found)
(while (and list (not found))
(let ((buffer (car list)))
(with-current-buffer buffer
(when (and list-buffers-directory
(string-equal fulldir (expand-file-name list-buffers-directory))
(string-match "\\*git-status\\*$" (buffer-name buffer)))
(setq found buffer))))
(setq list (cdr list)))
found))

(defun git-status (dir)
"Entry point into git-status mode."
(interactive "DSelect directory: ")
(setq dir (git-get-top-dir dir))
(if (file-directory-p (concat (file-name-as-directory dir) ".git"))
(let ((buffer (create-file-buffer (expand-file-name "*git-status*" dir))))
(let ((buffer (or (and git-reuse-status-buffer (git-find-status-buffer dir))
(create-file-buffer (expand-file-name "*git-status*" dir)))))
(switch-to-buffer buffer)
(cd dir)
(git-status-mode)

2
daemon.c

@ -19,7 +19,7 @@ static const char daemon_usage[] = @@ -19,7 +19,7 @@ static const char daemon_usage[] =
"git-daemon [--verbose] [--syslog] [--inetd | --port=n] [--export-all]\n"
" [--timeout=n] [--init-timeout=n] [--strict-paths]\n"
" [--base-path=path] [--user-path | --user-path=path]\n"
" [--reuseaddr] [directory...]";
" [--reuseaddr] [--detach] [--pid-file=file] [directory...]";

/* List of acceptable pathname prefixes */
static char **ok_paths = NULL;

28
diff.c

@ -17,15 +17,6 @@ static int diff_detect_rename_default = 0; @@ -17,15 +17,6 @@ static int diff_detect_rename_default = 0;
static int diff_rename_limit_default = -1;
static int diff_use_color_default = 0;

enum color_diff {
DIFF_RESET = 0,
DIFF_PLAIN = 1,
DIFF_METAINFO = 2,
DIFF_FRAGINFO = 3,
DIFF_FILE_OLD = 4,
DIFF_FILE_NEW = 5,
};

/* "\033[1;38;5;2xx;48;5;2xxm\0" is 23 bytes */
static char diff_colors[][24] = {
"\033[m", /* reset */
@ -33,7 +24,8 @@ static char diff_colors[][24] = { @@ -33,7 +24,8 @@ static char diff_colors[][24] = {
"\033[1m", /* bold */
"\033[36m", /* cyan */
"\033[31m", /* red */
"\033[32m" /* green */
"\033[32m", /* green */
"\033[33m" /* yellow */
};

static int parse_diff_color_slot(const char *var, int ofs)
@ -48,6 +40,8 @@ static int parse_diff_color_slot(const char *var, int ofs) @@ -48,6 +40,8 @@ static int parse_diff_color_slot(const char *var, int ofs)
return DIFF_FILE_OLD;
if (!strcasecmp(var+ofs, "new"))
return DIFF_FILE_NEW;
if (!strcasecmp(var+ofs, "commit"))
return DIFF_COMMIT;
die("bad config variable '%s'", var);
}

@ -370,7 +364,7 @@ struct emit_callback { @@ -370,7 +364,7 @@ struct emit_callback {
const char **label_path;
};

static inline const char *get_color(int diff_use_color, enum color_diff ix)
const char *diff_get_color(int diff_use_color, enum color_diff ix)
{
if (diff_use_color)
return diff_colors[ix];
@ -381,8 +375,8 @@ static void fn_out_consume(void *priv, char *line, unsigned long len) @@ -381,8 +375,8 @@ static void fn_out_consume(void *priv, char *line, unsigned long len)
{
int i;
struct emit_callback *ecbdata = priv;
const char *set = get_color(ecbdata->color_diff, DIFF_METAINFO);
const char *reset = get_color(ecbdata->color_diff, DIFF_RESET);
const char *set = diff_get_color(ecbdata->color_diff, DIFF_METAINFO);
const char *reset = diff_get_color(ecbdata->color_diff, DIFF_RESET);

if (ecbdata->label_path[0]) {
printf("%s--- %s%s\n", set, ecbdata->label_path[0], reset);
@ -397,7 +391,7 @@ static void fn_out_consume(void *priv, char *line, unsigned long len) @@ -397,7 +391,7 @@ static void fn_out_consume(void *priv, char *line, unsigned long len)
;
if (2 <= i && i < len && line[i] == ' ') {
ecbdata->nparents = i - 1;
set = get_color(ecbdata->color_diff, DIFF_FRAGINFO);
set = diff_get_color(ecbdata->color_diff, DIFF_FRAGINFO);
}
else if (len < ecbdata->nparents)
set = reset;
@ -410,7 +404,7 @@ static void fn_out_consume(void *priv, char *line, unsigned long len) @@ -410,7 +404,7 @@ static void fn_out_consume(void *priv, char *line, unsigned long len)
else if (line[i] == '+')
color = DIFF_FILE_NEW;
}
set = get_color(ecbdata->color_diff, color);
set = diff_get_color(ecbdata->color_diff, color);
}
if (len > 0 && line[len-1] == '\n')
len--;
@ -767,8 +761,8 @@ static void builtin_diff(const char *name_a, @@ -767,8 +761,8 @@ static void builtin_diff(const char *name_a,
mmfile_t mf1, mf2;
const char *lbl[2];
char *a_one, *b_two;
const char *set = get_color(o->color_diff, DIFF_METAINFO);
const char *reset = get_color(o->color_diff, DIFF_RESET);
const char *set = diff_get_color(o->color_diff, DIFF_METAINFO);
const char *reset = diff_get_color(o->color_diff, DIFF_RESET);

a_one = quote_two("a/", name_a);
b_two = quote_two("b/", name_b);

11
diff.h

@ -69,6 +69,17 @@ struct diff_options { @@ -69,6 +69,17 @@ struct diff_options {
add_remove_fn_t add_remove;
};

enum color_diff {
DIFF_RESET = 0,
DIFF_PLAIN = 1,
DIFF_METAINFO = 2,
DIFF_FRAGINFO = 3,
DIFF_FILE_OLD = 4,
DIFF_FILE_NEW = 5,
DIFF_COMMIT = 6,
};
const char *diff_get_color(int diff_use_color, enum color_diff ix);

extern const char mime_boundary_leader[];

extern void diff_tree_setup_paths(const char **paths, struct diff_options *);

1
environment.c

@ -11,6 +11,7 @@ @@ -11,6 +11,7 @@

char git_default_email[MAX_GITNAME];
char git_default_name[MAX_GITNAME];
int use_legacy_headers = 1;
int trust_executable_bit = 1;
int assume_unchanged = 0;
int prefer_symlink_refs = 0;

122
fetch.c

@ -7,9 +7,7 @@ @@ -7,9 +7,7 @@
#include "tag.h"
#include "blob.h"
#include "refs.h"

const char *write_ref = NULL;
const char *write_ref_log_details = NULL;
#include "strbuf.h"

int get_tree = 0;
int get_history = 0;
@ -213,54 +211,106 @@ static int mark_complete(const char *path, const unsigned char *sha1) @@ -213,54 +211,106 @@ static int mark_complete(const char *path, const unsigned char *sha1)
return 0;
}

int pull(char *target)
int pull_targets_stdin(char ***target, const char ***write_ref)
{
int targets = 0, targets_alloc = 0;
struct strbuf buf;
*target = NULL; *write_ref = NULL;
strbuf_init(&buf);
while (1) {
char *rf_one = NULL;
char *tg_one;

read_line(&buf, stdin, '\n');
if (buf.eof)
break;
tg_one = buf.buf;
rf_one = strchr(tg_one, '\t');
if (rf_one)
*rf_one++ = 0;

if (targets >= targets_alloc) {
targets_alloc = targets_alloc ? targets_alloc * 2 : 64;
*target = xrealloc(*target, targets_alloc * sizeof(**target));
*write_ref = xrealloc(*write_ref, targets_alloc * sizeof(**write_ref));
}
(*target)[targets] = strdup(tg_one);
(*write_ref)[targets] = rf_one ? strdup(rf_one) : NULL;
targets++;
}
return targets;
}

void pull_targets_free(int targets, char **target, const char **write_ref)
{
struct ref_lock *lock = NULL;
unsigned char sha1[20];
while (targets--) {
free(target[targets]);
if (write_ref && write_ref[targets])
free((char *) write_ref[targets]);
}
}

int pull(int targets, char **target, const char **write_ref,
const char *write_ref_log_details)
{
struct ref_lock **lock = xcalloc(targets, sizeof(struct ref_lock *));
unsigned char *sha1 = xmalloc(targets * 20);
char *msg;
int ret;
int i;

save_commit_buffer = 0;
track_object_refs = 0;
if (write_ref) {
lock = lock_ref_sha1(write_ref, NULL, 0);
if (!lock) {
error("Can't lock ref %s", write_ref);
return -1;

for (i = 0; i < targets; i++) {
if (!write_ref || !write_ref[i])
continue;

lock[i] = lock_ref_sha1(write_ref[i], NULL, 0);
if (!lock[i]) {
error("Can't lock ref %s", write_ref[i]);
goto unlock_and_fail;
}
}

if (!get_recover)
for_each_ref(mark_complete);

if (interpret_target(target, sha1)) {
error("Could not interpret %s as something to pull", target);
if (lock)
unlock_ref(lock);
return -1;
for (i = 0; i < targets; i++) {
if (interpret_target(target[i], &sha1[20 * i])) {
error("Could not interpret %s as something to pull", target[i]);
goto unlock_and_fail;
}
if (process(lookup_unknown_object(&sha1[20 * i])))
goto unlock_and_fail;
}
if (process(lookup_unknown_object(sha1))) {
if (lock)
unlock_ref(lock);
return -1;

if (loop())
goto unlock_and_fail;

if (write_ref_log_details) {
msg = xmalloc(strlen(write_ref_log_details) + 12);
sprintf(msg, "fetch from %s", write_ref_log_details);
} else {
msg = NULL;
}
if (loop()) {
if (lock)
unlock_ref(lock);
return -1;
for (i = 0; i < targets; i++) {
if (!write_ref || !write_ref[i])
continue;
ret = write_ref_sha1(lock[i], &sha1[20 * i], msg ? msg : "fetch (unknown)");
lock[i] = NULL;
if (ret)
goto unlock_and_fail;
}
if (msg)
free(msg);

if (write_ref) {
if (write_ref_log_details) {
msg = xmalloc(strlen(write_ref_log_details) + 12);
sprintf(msg, "fetch from %s", write_ref_log_details);
}
else
msg = NULL;
ret = write_ref_sha1(lock, sha1, msg ? msg : "fetch (unknown)");
if (msg)
free(msg);
return ret;
}
return 0;


unlock_and_fail:
for (i = 0; i < targets; i++)
if (lock[i])
unlock_ref(lock[i]);
return -1;
}

17
fetch.h

@ -22,12 +22,6 @@ extern void prefetch(unsigned char *sha1); @@ -22,12 +22,6 @@ extern void prefetch(unsigned char *sha1);
*/
extern int fetch_ref(char *ref, unsigned char *sha1);

/* If set, the ref filename to write the target value to. */
extern const char *write_ref;

/* If set additional text will appear in the ref log. */
extern const char *write_ref_log_details;

/* Set to fetch the target tree. */
extern int get_tree;

@ -46,6 +40,15 @@ extern int get_recover; @@ -46,6 +40,15 @@ extern int get_recover;
/* Report what we got under get_verbosely */
extern void pull_say(const char *, const char *);

extern int pull(char *target);
/* Load pull targets from stdin */
extern int pull_targets_stdin(char ***target, const char ***write_ref);

/* Free up loaded targets */
extern void pull_targets_free(int targets, char **target, const char **write_ref);

/* If write_ref is set, the ref filename to write the target value to. */
/* If write_ref_log_details is set, additional text will appear in the ref log. */
extern int pull(int targets, char **target, const char **write_ref,
const char *write_ref_log_details);

#endif /* PULL_H */

12
git-am.sh

@ -91,6 +91,7 @@ fall_back_3way () { @@ -91,6 +91,7 @@ fall_back_3way () {
}

prec=4
rloga=am
dotest=.dotest sign= utf8= keep= skip= interactive= resolved= binary= ws= resolvemsg=

while case "$#" in 0) break;; esac
@ -130,6 +131,9 @@ do @@ -130,6 +131,9 @@ do
--resolvemsg=*)
resolvemsg=$(echo "$1" | sed -e "s/^--resolvemsg=//"); shift ;;

--reflog-action=*)
rloga=`expr "z$1" : 'z-[^=]*=\(.*\)'`; shift ;;

--)
shift; break ;;
-*)
@ -152,8 +156,10 @@ fi @@ -152,8 +156,10 @@ fi

if test -d "$dotest"
then
test ",$#," = ",0," ||
die "previous dotest directory $dotest still exists but mbox given."
if test ",$#," != ",0," || ! tty -s
then
die "previous dotest directory $dotest still exists but mbox given."
fi
resume=yes
else
# Make sure we are not given --skip nor --resolved
@ -413,7 +419,7 @@ do @@ -413,7 +419,7 @@ do
parent=$(git-rev-parse --verify HEAD) &&
commit=$(git-commit-tree $tree -p $parent <"$dotest/final-commit") &&
echo Committed: $commit &&
git-update-ref -m "am: $SUBJECT" HEAD $commit $parent ||
git-update-ref -m "$rloga: $SUBJECT" HEAD $commit $parent ||
stop_here $this

if test -x "$GIT_DIR"/hooks/post-applypatch

4
git-clone.sh

@ -266,7 +266,7 @@ yes,yes) @@ -266,7 +266,7 @@ yes,yes)
echo "$repo/objects" >> "$GIT_DIR/objects/info/alternates"
;;
esac
git-ls-remote "$repo" >"$GIT_DIR/CLONE_HEAD"
git-ls-remote "$repo" >"$GIT_DIR/CLONE_HEAD" || exit 1
;;
*)
case "$repo" in
@ -296,7 +296,7 @@ yes,yes) @@ -296,7 +296,7 @@ yes,yes)
done
rm -f "$GIT_DIR/TMP_ALT"
fi
git-ls-remote "$repo" >"$GIT_DIR/CLONE_HEAD"
git-ls-remote "$repo" >"$GIT_DIR/CLONE_HEAD" || exit 1
;;
http://*)
if test -z "@@NO_CURL@@"

50
git-cvsexportcommit.perl

@ -16,9 +16,9 @@ unless ($ENV{GIT_DIR} && -r $ENV{GIT_DIR}){ @@ -16,9 +16,9 @@ unless ($ENV{GIT_DIR} && -r $ENV{GIT_DIR}){
die "GIT_DIR is not defined or is unreadable";
}

our ($opt_h, $opt_p, $opt_v, $opt_c, $opt_f, $opt_m );
our ($opt_h, $opt_p, $opt_v, $opt_c, $opt_f, $opt_a, $opt_m );

getopts('hpvcfm:');
getopts('hpvcfam:');

$opt_h && usage();

@ -29,7 +29,6 @@ our ($tmpdir, $tmpdirname) = tempdir('git-cvsapplycommit-XXXXXX', @@ -29,7 +29,6 @@ our ($tmpdir, $tmpdirname) = tempdir('git-cvsapplycommit-XXXXXX',
TMPDIR => 1,
CLEANUP => 1);

print Dumper(@ARGV);
# resolve target commit
my $commit;
$commit = pop @ARGV;
@ -53,12 +52,32 @@ if (@ARGV) { @@ -53,12 +52,32 @@ if (@ARGV) {
# find parents from the commit itself
my @commit = safe_pipe_capture('git-cat-file', 'commit', $commit);
my @parents;
foreach my $p (@commit) {
if ($p =~ m/^$/) { # end of commit headers, we're done
last;
my $committer;
my $author;
my $stage = 'headers'; # headers, msg
my $title;
my $msg = '';

foreach my $line (@commit) {
chomp $line;
if ($stage eq 'headers' && $line eq '') {
$stage = 'msg';
next;
}
if ($p =~ m/^parent (\w{40})$/) { # found a parent
push @parents, $1;

if ($stage eq 'headers') {
if ($line =~ m/^parent (\w{40})$/) { # found a parent
push @parents, $1;
} elsif ($line =~ m/^author (.+) \d+ \+\d+$/) {
$author = $1;
} elsif ($line =~ m/^committer (.+) \d+ \+\d+$/) {
$committer = $1;
}
} else {
$msg .= $line . "\n";
unless ($title) {
$title = $line;
}
}
}

@ -84,12 +103,18 @@ $opt_v && print "Applying to CVS commit $commit from parent $parent\n"; @@ -84,12 +103,18 @@ $opt_v && print "Applying to CVS commit $commit from parent $parent\n";

# grab the commit message
open(MSG, ">.msg") or die "Cannot open .msg for writing";
print MSG $opt_m;
if ($opt_m) {
print MSG $opt_m;
}
print MSG $msg;
if ($opt_a) {
print MSG "\n\nAuthor: $author\n";
if ($author ne $committer) {
print MSG "Committer: $committer\n";
}
}
close MSG;

`git-cat-file commit $commit | sed -e '1,/^\$/d' >> .msg`;
$? && die "Error extracting the commit message";

my (@afiles, @dfiles, @mfiles, @dirs);
my @files = safe_pipe_capture('git-diff-tree', '-r', $parent, $commit);
#print @files;
@ -233,6 +258,7 @@ foreach my $f (@dfiles) { @@ -233,6 +258,7 @@ foreach my $f (@dfiles) {
}

print "Commit to CVS\n";
print "Patch: $title\n";
my $commitfiles = join(' ', @afiles, @mfiles, @dfiles);
my $cmd = "cvs commit -F .msg $commitfiles";


89
git-cvsserver.perl

@ -81,7 +81,7 @@ my $methods = { @@ -81,7 +81,7 @@ my $methods = {

# $state holds all the bits of information the clients sends us that could
# potentially be useful when it comes to actually _doing_ something.
my $state = {};
my $state = { prependdir => '' };
$log->info("--------------- STARTING -----------------");

my $TEMP_DIR = tempdir( CLEANUP => 1 );
@ -547,12 +547,15 @@ sub req_Argument @@ -547,12 +547,15 @@ sub req_Argument
{
my ( $cmd, $data ) = @_;

# TODO : Not quite sure how Argument and Argumentx differ, but I assume
# it's for multi-line arguments ... somehow ...
# Argumentx means: append to last Argument (with a newline in front)

$log->debug("$cmd : $data");

push @{$state->{arguments}}, $data;
if ( $cmd eq 'Argumentx') {
${$state->{arguments}}[$#{$state->{arguments}}] .= "\n" . $data;
} else {
push @{$state->{arguments}}, $data;
}
}

# expand-modules \n
@ -1139,9 +1142,7 @@ sub req_ci @@ -1139,9 +1142,7 @@ sub req_ci
exit;
}

open FILE, ">", "$ENV{GIT_DIR}refs/heads/$state->{module}";
print FILE $commithash;
close FILE;
print LOCKFILE $commithash;

$updater->update();

@ -1168,7 +1169,9 @@ sub req_ci @@ -1168,7 +1169,9 @@ sub req_ci
}

close LOCKFILE;
unlink($lockfile);
my $reffile = "$ENV{GIT_DIR}refs/heads/$state->{module}";
unlink($reffile);
rename($lockfile, $reffile);
chdir "/";

print "ok\n";
@ -2129,12 +2132,6 @@ sub update @@ -2129,12 +2132,6 @@ sub update
# first lets get the commit list
$ENV{GIT_DIR} = $self->{git_path};

# prepare database queries
my $db_insert_rev = $self->{dbh}->prepare_cached("INSERT INTO revision (name, revision, filehash, commithash, modified, author, mode) VALUES (?,?,?,?,?,?,?)",{},1);
my $db_insert_mergelog = $self->{dbh}->prepare_cached("INSERT INTO commitmsgs (key, value) VALUES (?,?)",{},1);
my $db_delete_head = $self->{dbh}->prepare_cached("DELETE FROM head",{},1);
my $db_insert_head = $self->{dbh}->prepare_cached("INSERT INTO head (name, revision, filehash, commithash, modified, author, mode) VALUES (?,?,?,?,?,?,?)",{},1);

my $commitinfo = `git-cat-file commit $self->{module} 2>&1`;
unless ( $commitinfo =~ /tree\s+[a-zA-Z0-9]{40}/ )
{
@ -2323,7 +2320,7 @@ sub update @@ -2323,7 +2320,7 @@ sub update
author => $commit->{author},
mode => $git_perms,
};
$db_insert_rev->execute($4, $head->{$4}{revision}, $2, $commit->{hash}, $commit->{date}, $commit->{author}, $git_perms);
$self->insert_rev($4, $head->{$4}{revision}, $2, $commit->{hash}, $commit->{date}, $commit->{author}, $git_perms);
}
elsif ( $3 eq "M" )
{
@ -2337,7 +2334,7 @@ sub update @@ -2337,7 +2334,7 @@ sub update
author => $commit->{author},
mode => $git_perms,
};
$db_insert_rev->execute($4, $head->{$4}{revision}, $2, $commit->{hash}, $commit->{date}, $commit->{author}, $git_perms);
$self->insert_rev($4, $head->{$4}{revision}, $2, $commit->{hash}, $commit->{date}, $commit->{author}, $git_perms);
}
elsif ( $3 eq "A" )
{
@ -2351,7 +2348,7 @@ sub update @@ -2351,7 +2348,7 @@ sub update
author => $commit->{author},
mode => $git_perms,
};
$db_insert_rev->execute($4, $head->{$4}{revision}, $2, $commit->{hash}, $commit->{date}, $commit->{author}, $git_perms);
$self->insert_rev($4, $head->{$4}{revision}, $2, $commit->{hash}, $commit->{date}, $commit->{author}, $git_perms);
}
else
{
@ -2408,7 +2405,7 @@ sub update @@ -2408,7 +2405,7 @@ sub update
};


$db_insert_rev->execute($git_filename, $newrevision, $git_hash, $commit->{hash}, $commit->{date}, $commit->{author}, $git_perms);
$self->insert_rev($git_filename, $newrevision, $git_hash, $commit->{hash}, $commit->{date}, $commit->{author}, $git_perms);
}
}
close FILELIST;
@ -2424,7 +2421,7 @@ sub update @@ -2424,7 +2421,7 @@ sub update
$head->{$file}{modified} = $commit->{date};
$head->{$file}{author} = $commit->{author};

$db_insert_rev->execute($file, $head->{$file}{revision}, $head->{$file}{filehash}, $commit->{hash}, $commit->{date}, $commit->{author}, $head->{$file}{mode});
$self->insert_rev($file, $head->{$file}{revision}, $head->{$file}{filehash}, $commit->{hash}, $commit->{date}, $commit->{author}, $head->{$file}{mode});
}
}
# END : "Detect deleted files"
@ -2433,7 +2430,7 @@ sub update @@ -2433,7 +2430,7 @@ sub update

if (exists $commit->{mergemsg})
{
$db_insert_mergelog->execute($commit->{hash}, $commit->{mergemsg});
$self->insert_mergelog($commit->{hash}, $commit->{mergemsg});
}

$lastpicked = $commit->{hash};
@ -2441,10 +2438,10 @@ sub update @@ -2441,10 +2438,10 @@ sub update
$self->_set_prop("last_commit", $commit->{hash});
}

$db_delete_head->execute();
$self->delete_head();
foreach my $file ( keys %$head )
{
$db_insert_head->execute(
$self->insert_head(
$file,
$head->{$file}{revision},
$head->{$file}{filehash},
@ -2462,6 +2459,54 @@ sub update @@ -2462,6 +2459,54 @@ sub update
$self->{dbh}->commit() or die "Failed to commit changes to SQLite";
}

sub insert_rev
{
my $self = shift;
my $name = shift;
my $revision = shift;
my $filehash = shift;
my $commithash = shift;
my $modified = shift;
my $author = shift;
my $mode = shift;

my $insert_rev = $self->{dbh}->prepare_cached("INSERT INTO revision (name, revision, filehash, commithash, modified, author, mode) VALUES (?,?,?,?,?,?,?)",{},1);
$insert_rev->execute($name, $revision, $filehash, $commithash, $modified, $author, $mode);
}

sub insert_mergelog
{
my $self = shift;
my $key = shift;
my $value = shift;

my $insert_mergelog = $self->{dbh}->prepare_cached("INSERT INTO commitmsgs (key, value) VALUES (?,?)",{},1);
$insert_mergelog->execute($key, $value);
}

sub delete_head
{
my $self = shift;

my $delete_head = $self->{dbh}->prepare_cached("DELETE FROM head",{},1);
$delete_head->execute();
}

sub insert_head
{
my $self = shift;
my $name = shift;
my $revision = shift;
my $filehash = shift;
my $commithash = shift;
my $modified = shift;
my $author = shift;
my $mode = shift;

my $insert_head = $self->{dbh}->prepare_cached("INSERT INTO head (name, revision, filehash, commithash, modified, author, mode) VALUES (?,?,?,?,?,?,?)",{},1);
$insert_head->execute($name, $revision, $filehash, $commithash, $modified, $author, $mode);
}

sub _headrev
{
my $self = shift;

19
git-fetch.sh

@ -20,6 +20,7 @@ verbose= @@ -20,6 +20,7 @@ verbose=
update_head_ok=
exec=
upload_pack=
keep=--thin
while case "$#" in 0) break ;; esac
do
case "$1" in
@ -69,7 +70,8 @@ case "$#" in @@ -69,7 +70,8 @@ case "$#" in
0)
test -f "$GIT_DIR/branches/origin" ||
test -f "$GIT_DIR/remotes/origin" ||
die "Where do you want to fetch from today?"
git-repo-config --get remote.origin.url >/dev/null ||
die "Where do you want to fetch from today?"
set origin ;;
esac

@ -153,7 +155,7 @@ fast_forward_local () { @@ -153,7 +155,7 @@ fast_forward_local () {
then
if now_=$(cat "$GIT_DIR/$1") && test "$now_" = "$2"
then
[ "$verbose" ] && echo >&2 "* $1: same as $3"
[ "$verbose" ] && echo >&2 "* $1: same as $3" ||:
else
echo >&2 "* $1: updating with $3"
git-update-ref -m "$rloga: updating tag" "$1" "$2"
@ -223,9 +225,16 @@ reflist=$(get_remote_refs_for_fetch "$@") @@ -223,9 +225,16 @@ reflist=$(get_remote_refs_for_fetch "$@")
if test "$tags"
then
taglist=`IFS=" " &&
git-ls-remote $upload_pack --tags "$remote" |
(
git-ls-remote $upload_pack --tags "$remote" ||
echo fail ouch
) |
while read sha1 name
do
case "$sha1" in
fail)
exit 1
esac
case "$name" in
*^*) continue ;;
esac
@ -235,7 +244,7 @@ then @@ -235,7 +244,7 @@ then
else
echo >&2 "warning: tag ${name} ignored"
fi
done`
done` || exit
if test "$#" -gt 1
then
# remote URL plus explicit refspecs; we need to merge them.
@ -347,7 +356,7 @@ fetch_main () { @@ -347,7 +356,7 @@ fetch_main () {
( : subshell because we muck with IFS
IFS=" $LF"
(
git-fetch-pack $exec $keep --thin "$remote" $rref || echo failed "$remote"
git-fetch-pack $exec $keep "$remote" $rref || echo failed "$remote"
) |
while read sha1 remote_name
do

11
git-instaweb.sh

@ -54,6 +54,10 @@ start_httpd () { @@ -54,6 +54,10 @@ start_httpd () {
fi
done
fi
if test $? != 0; then
echo "Could not execute http daemon $httpd."
exit 1
fi
}

stop_httpd () {
@ -183,8 +187,10 @@ PerlPassEnv GIT_EXEC_DIR @@ -183,8 +187,10 @@ PerlPassEnv GIT_EXEC_DIR
EOF
else
# plain-old CGI
list_mods=`echo "$httpd" | sed "s/-f$/-l/"`
$list_mods | grep 'mod_cgi\.c' >/dev/null 2>&1 || \
echo "LoadModule cgi_module $module_path/mod_cgi.so" >> "$conf"
cat >> "$conf" <<EOF
LoadModule cgi_module $module_path/mod_cgi.so
AddHandler cgi-script .cgi
<Location /gitweb.cgi>
Options +ExecCGI
@ -232,4 +238,5 @@ esac @@ -232,4 +238,5 @@ esac

start_httpd
test -z "$browser" && browser=echo
$browser http://127.0.0.1:$port
url=http://127.0.0.1:$port
$browser $url || echo $url

2
git-lost-found.sh

@ -12,7 +12,7 @@ fi @@ -12,7 +12,7 @@ fi
laf="$GIT_DIR/lost-found"
rm -fr "$laf" && mkdir -p "$laf/commit" "$laf/other" || exit

git fsck-objects |
git fsck-objects --full |
while read dangling type sha1
do
case "$dangling" in

17
git-merge.sh

@ -63,7 +63,13 @@ squash_message () { @@ -63,7 +63,13 @@ squash_message () {
}

finish () {
test '' = "$2" || echo "$2"
if test '' = "$2"
then
rlogm="$rloga"
else
echo "$2"
rlogm="$rloga: $2"
fi
case "$squash" in
t)
echo "Squash commit -- not updating HEAD"
@ -75,7 +81,7 @@ finish () { @@ -75,7 +81,7 @@ finish () {
echo "No merge message -- not updating HEAD"
;;
*)
git-update-ref HEAD "$1" "$head" || exit 1
git-update-ref -m "$rlogm" HEAD "$1" "$head" || exit 1
;;
esac
;;
@ -93,6 +99,7 @@ finish () { @@ -93,6 +99,7 @@ finish () {
esac
}

rloga=
while case "$#" in 0) break ;; esac
do
case "$1" in
@ -126,6 +133,9 @@ do @@ -126,6 +133,9 @@ do
die "available strategies are: $all_strategies" ;;
esac
;;
--reflog-action=*)
rloga=`expr "z$1" : 'z-[^=]*=\(.*\)'`
;;
-*) usage ;;
*) break ;;
esac
@ -140,6 +150,7 @@ shift @@ -140,6 +150,7 @@ shift

# All the rest are remote heads
test "$#" = 0 && usage ;# we need at least one remote head.
test "$rloga" = '' && rloga="merge: $@"

remoteheads=
for remote
@ -325,7 +336,7 @@ if test '' != "$result_tree" @@ -325,7 +336,7 @@ if test '' != "$result_tree"
then
parents=$(git-show-branch --independent "$head" "$@" | sed -e 's/^/-p /')
result_commit=$(echo "$merge_msg" | git-commit-tree $result_tree $parents) || exit
finish "$result_commit" "Merge $result_commit, made by $wt_strategy."
finish "$result_commit" "Merge made by $wt_strategy."
dropsave
exit 0
fi

250
git-mv.perl

@ -1,250 +0,0 @@ @@ -1,250 +0,0 @@
#!/usr/bin/perl
#
# Copyright 2005, Ryan Anderson <ryan@michonline.com>
# Josef Weidendorfer <Josef.Weidendorfer@gmx.de>
#
# This file is licensed under the GPL v2, or a later version
# at the discretion of Linus Torvalds.


use warnings;
use strict;
use Getopt::Std;

sub usage() {
print <<EOT;
$0 [-f] [-n] <source> <destination>
$0 [-f] [-n] [-k] <source> ... <destination directory>
EOT
exit(1);
}

our ($opt_n, $opt_f, $opt_h, $opt_k, $opt_v);
getopts("hnfkv") || usage;
usage() if $opt_h;
@ARGV >= 1 or usage;

my $GIT_DIR = `git rev-parse --git-dir`;
exit 1 if $?; # rev-parse would have given "not a git dir" message.
chomp($GIT_DIR);

my (@srcArgs, @dstArgs, @srcs, @dsts);
my ($src, $dst, $base, $dstDir);

# remove any trailing slash in arguments
for (@ARGV) { s/\/*$//; }

my $argCount = scalar @ARGV;
if (-d $ARGV[$argCount-1]) {
$dstDir = $ARGV[$argCount-1];
@srcArgs = @ARGV[0..$argCount-2];

foreach $src (@srcArgs) {
$base = $src;
$base =~ s/^.*\///;
$dst = "$dstDir/". $base;
push @dstArgs, $dst;
}
}
else {
if ($argCount < 2) {
print "Error: need at least two arguments\n";
exit(1);
}
if ($argCount > 2) {
print "Error: moving to directory '"
. $ARGV[$argCount-1]
. "' not possible; not existing\n";
exit(1);
}
@srcArgs = ($ARGV[0]);
@dstArgs = ($ARGV[1]);
$dstDir = "";
}

my $subdir_prefix = `git rev-parse --show-prefix`;
chomp($subdir_prefix);

# run in git base directory, so that git-ls-files lists all revisioned files
chdir "$GIT_DIR/..";

# normalize paths, needed to compare against versioned files and update-index
# also, this is nicer to end-users by doing ".//a/./b/.//./c" ==> "a/b/c"
for (@srcArgs, @dstArgs) {
# prepend git prefix as we run from base directory
$_ = $subdir_prefix.$_;
s|^\./||;
s|/\./|/| while (m|/\./|);
s|//+|/|g;
# Also "a/b/../c" ==> "a/c"
1 while (s,(^|/)[^/]+/\.\./,$1,);
}

my (@allfiles,@srcfiles,@dstfiles);
my $safesrc;
my (%overwritten, %srcForDst);

$/ = "\0";
open(F, 'git-ls-files -z |')
or die "Failed to open pipe from git-ls-files: " . $!;

@allfiles = map { chomp; $_; } <F>;
close(F);


my ($i, $bad);
while(scalar @srcArgs > 0) {
$src = shift @srcArgs;
$dst = shift @dstArgs;
$bad = "";

for ($src, $dst) {
# Be nicer to end-users by doing ".//a/./b/.//./c" ==> "a/b/c"
s|^\./||;
s|/\./|/| while (m|/\./|);
s|//+|/|g;
# Also "a/b/../c" ==> "a/c"
1 while (s,(^|/)[^/]+/\.\./,$1,);
}

if ($opt_v) {
print "Checking rename of '$src' to '$dst'\n";
}

unless (-f $src || -l $src || -d $src) {
$bad = "bad source '$src'";
}

$safesrc = quotemeta($src);
@srcfiles = grep /^$safesrc(\/|$)/, @allfiles;

$overwritten{$dst} = 0;
if (($bad eq "") && -e $dst) {
$bad = "destination '$dst' already exists";
if ($opt_f) {
# only files can overwrite each other: check both source and destination
if (-f $dst && (scalar @srcfiles == 1)) {
print "Warning: $bad; will overwrite!\n";
$bad = "";
$overwritten{$dst} = 1;
}
else {
$bad = "Can not overwrite '$src' with '$dst'";
}
}
}
if (($bad eq "") && ($dst =~ /^$safesrc\//)) {
$bad = "can not move directory '$src' into itself";
}

if ($bad eq "") {
if (scalar @srcfiles == 0) {
$bad = "'$src' not under version control";
}
}

if ($bad eq "") {
if (defined $srcForDst{$dst}) {
$bad = "can not move '$src' to '$dst'; already target of ";
$bad .= "'".$srcForDst{$dst}."'";
}
else {
$srcForDst{$dst} = $src;
}
}

if ($bad ne "") {
if ($opt_k) {
print "Warning: $bad; skipping\n";
next;
}
print "Error: $bad\n";
exit(1);
}
push @srcs, $src;
push @dsts, $dst;
}

# Final pass: rename/move
my (@deletedfiles,@addedfiles,@changedfiles);
$bad = "";
while(scalar @srcs > 0) {
$src = shift @srcs;
$dst = shift @dsts;

if ($opt_n || $opt_v) { print "Renaming $src to $dst\n"; }
if (!$opt_n) {
if (!rename($src,$dst)) {
$bad = "renaming '$src' failed: $!";
if ($opt_k) {
print "Warning: skipped: $bad\n";
$bad = "";
next;
}
last;
}
}

$safesrc = quotemeta($src);
@srcfiles = grep /^$safesrc(\/|$)/, @allfiles;
@dstfiles = @srcfiles;
s/^$safesrc(\/|$)/$dst$1/ for @dstfiles;

push @deletedfiles, @srcfiles;
if (scalar @srcfiles == 1) {
# $dst can be a directory with 1 file inside
if ($overwritten{$dst} ==1) {
push @changedfiles, $dstfiles[0];

} else {
push @addedfiles, $dstfiles[0];
}
}
else {
push @addedfiles, @dstfiles;
}
}

if ($opt_n) {
if (@changedfiles) {
print "Changed : ". join(", ", @changedfiles) ."\n";
}
if (@addedfiles) {
print "Adding : ". join(", ", @addedfiles) ."\n";
}
if (@deletedfiles) {
print "Deleting : ". join(", ", @deletedfiles) ."\n";
}
}
else {
if (@changedfiles) {
open(H, "| git-update-index -z --stdin")
or die "git-update-index failed to update changed files with code $!\n";
foreach my $fileName (@changedfiles) {
print H "$fileName\0";
}
close(H);
}
if (@addedfiles) {
open(H, "| git-update-index --add -z --stdin")
or die "git-update-index failed to add new names with code $!\n";
foreach my $fileName (@addedfiles) {
print H "$fileName\0";
}
close(H);
}
if (@deletedfiles) {
open(H, "| git-update-index --remove -z --stdin")
or die "git-update-index failed to remove old names with code $!\n";
foreach my $fileName (@deletedfiles) {
print H "$fileName\0";
}
close(H);
}
}

if ($bad ne "") {
print "Error: $bad\n";
exit(1);
}

3
git-pull.sh

@ -102,5 +102,6 @@ case "$strategy_args" in @@ -102,5 +102,6 @@ case "$strategy_args" in
esac

merge_name=$(git-fmt-merge-msg <"$GIT_DIR/FETCH_HEAD") || exit
git-merge $no_summary $no_commit $squash $strategy_args \
git-merge "--reflog-action=pull $*" \
$no_summary $no_commit $squash $strategy_args \
"$merge_name" HEAD $merge_head

2
git-quiltimport.sh

@ -112,7 +112,7 @@ for patch_name in $(cat "$QUILT_PATCHES/series" | grep -v '^#'); do @@ -112,7 +112,7 @@ for patch_name in $(cat "$QUILT_PATCHES/series" | grep -v '^#'); do
git-apply --index -C1 "$tmp_patch" &&
tree=$(git-write-tree) &&
commit=$((echo "$SUBJECT"; echo; cat "$tmp_msg") | git-commit-tree $tree -p $commit) &&
git-update-ref HEAD $commit || exit 4
git-update-ref -m "quiltimport: $patch_name" HEAD $commit || exit 4
fi
done
rm -rf $tmp_dir || exit 5

9
git-rebase.sh

@ -137,7 +137,8 @@ do @@ -137,7 +137,8 @@ do
finish_rb_merge
exit
fi
git am --resolved --3way --resolvemsg="$RESOLVEMSG"
git am --resolved --3way --resolvemsg="$RESOLVEMSG" \
--reflog-action=rebase
exit
;;
--skip)
@ -156,7 +157,8 @@ do @@ -156,7 +157,8 @@ do
finish_rb_merge
exit
fi
git am -3 --skip --resolvemsg="$RESOLVEMSG"
git am -3 --skip --resolvemsg="$RESOLVEMSG" \
--reflog-action=rebase
exit
;;
--abort)
@ -299,7 +301,8 @@ fi @@ -299,7 +301,8 @@ fi
if test -z "$do_merge"
then
git-format-patch -k --stdout --full-index "$upstream"..ORIG_HEAD |
git am --binary -3 -k --resolvemsg="$RESOLVEMSG"
git am --binary -3 -k --resolvemsg="$RESOLVEMSG" \
--reflog-action=rebase
exit $?
fi


5
git-reset.sh

@ -52,7 +52,8 @@ then @@ -52,7 +52,8 @@ then
else
rm -f "$GIT_DIR/ORIG_HEAD"
fi
git-update-ref -m "reset $reset_type $@" HEAD "$rev"
git-update-ref -m "reset $reset_type $*" HEAD "$rev"
update_ref_status=$?

case "$reset_type" in
--hard )
@ -66,3 +67,5 @@ case "$reset_type" in @@ -66,3 +67,5 @@ case "$reset_type" in
esac

rm -f "$GIT_DIR/MERGE_HEAD" "$GIT_DIR/rr-cache/MERGE_RR" "$GIT_DIR/SQUASH_MSG"

exit $update_ref_status

7
git-resolve.sh

@ -15,6 +15,7 @@ dropheads() { @@ -15,6 +15,7 @@ dropheads() {

head=$(git-rev-parse --verify "$1"^0) &&
merge=$(git-rev-parse --verify "$2"^0) &&
merge_name="$2" &&
merge_msg="$3" || usage

#
@ -43,7 +44,8 @@ case "$common" in @@ -43,7 +44,8 @@ case "$common" in
"$head")
echo "Updating from $head to $merge"
git-read-tree -u -m $head $merge || exit 1
git-update-ref HEAD "$merge" "$head"
git-update-ref -m "resolve $merge_name: Fast forward" \
HEAD "$merge" "$head"
git-diff-tree -p $head $merge | git-apply --stat
dropheads
exit 0
@ -100,6 +102,7 @@ if [ $? -ne 0 ]; then @@ -100,6 +102,7 @@ if [ $? -ne 0 ]; then
fi
result_commit=$(echo "$merge_msg" | git-commit-tree $result_tree -p $head -p $merge)
echo "Committed merge $result_commit"
git-update-ref HEAD "$result_commit" "$head"
git-update-ref -m "resolve $merge_name: In-index merge" \
HEAD "$result_commit" "$head"
git-diff-tree -p $head $result_commit | git-apply --stat
dropheads

25
git-svn.perl

@ -147,7 +147,7 @@ init_vars(); @@ -147,7 +147,7 @@ init_vars();
load_authors() if $_authors;
load_all_refs() if $_branch_all_refs;
svn_compat_check() unless $_use_lib;
migration_check() unless $cmd =~ /^(?:init|rebuild|multi-init)$/;
migration_check() unless $cmd =~ /^(?:init|rebuild|multi-init|commit-diff)$/;
$cmd{$cmd}->[0]->(@ARGV);
exit 0;

@ -2709,6 +2709,12 @@ sub libsvn_fetch { @@ -2709,6 +2709,12 @@ sub libsvn_fetch {
} else {
die "Unrecognized action: $m, ($f r$rev)\n";
}
} elsif ($t == $SVN::Node::dir && $m =~ /^[AR]$/) {
my @traversed = ();
libsvn_traverse($gui, '', $f, $rev, \@traversed);
foreach (@traversed) {
push @amr, [ $m, $_ ]
}
}
$pool->clear;
}
@ -2778,7 +2784,7 @@ sub libsvn_parse_revision { @@ -2778,7 +2784,7 @@ sub libsvn_parse_revision {
}

sub libsvn_traverse {
my ($gui, $pfx, $path, $rev) = @_;
my ($gui, $pfx, $path, $rev, $files) = @_;
my $cwd = "$pfx/$path";
my $pool = SVN::Pool->new;
$cwd =~ s#^/+##g;
@ -2786,10 +2792,15 @@ sub libsvn_traverse { @@ -2786,10 +2792,15 @@ sub libsvn_traverse {
foreach my $d (keys %$dirent) {
my $t = $dirent->{$d}->kind;
if ($t == $SVN::Node::dir) {
libsvn_traverse($gui, $cwd, $d, $rev);
libsvn_traverse($gui, $cwd, $d, $rev, $files);
} elsif ($t == $SVN::Node::file) {
print "\tA\t$cwd/$d\n" unless $_q;
libsvn_get_file($gui, "$cwd/$d", $rev);
my $file = "$cwd/$d";
if (defined $files) {
push @$files, $file;
} else {
print "\tA\t$file\n" unless $_q;
libsvn_get_file($gui, $file, $rev);
}
}
}
$pool->clear;
@ -2913,9 +2924,7 @@ sub libsvn_new_tree { @@ -2913,9 +2924,7 @@ sub libsvn_new_tree {
}
my ($paths, $rev, $author, $date, $msg) = @_;
open my $gui, '| git-update-index -z --index-info' or croak $!;
my $pool = SVN::Pool->new;
libsvn_traverse($gui, '', $SVN_PATH, $rev, $pool);
$pool->clear;
libsvn_traverse($gui, '', $SVN_PATH, $rev);
close $gui or croak $?;
return libsvn_log_entry($rev, $author, $date, $msg);
}

236
git.c

@ -35,6 +35,59 @@ static void prepend_to_path(const char *dir, int len) @@ -35,6 +35,59 @@ static void prepend_to_path(const char *dir, int len)
setenv("PATH", path, 1);
}

static int handle_options(const char*** argv, int* argc)
{
int handled = 0;

while (*argc > 0) {
const char *cmd = (*argv)[0];
if (cmd[0] != '-')
break;

/*
* For legacy reasons, the "version" and "help"
* commands can be written with "--" prepended
* to make them look like flags.
*/
if (!strcmp(cmd, "--help") || !strcmp(cmd, "--version"))
break;

/*
* Check remaining flags.
*/
if (!strncmp(cmd, "--exec-path", 11)) {
cmd += 11;
if (*cmd == '=')
git_set_exec_path(cmd + 1);
else {
puts(git_exec_path());
exit(0);
}
} else if (!strcmp(cmd, "-p") || !strcmp(cmd, "--paginate")) {
setup_pager();
} else if (!strcmp(cmd, "--git-dir")) {
if (*argc < 1)
return -1;
setenv("GIT_DIR", (*argv)[1], 1);
(*argv)++;
(*argc)--;
} else if (!strncmp(cmd, "--git-dir=", 10)) {
setenv("GIT_DIR", cmd + 10, 1);
} else if (!strcmp(cmd, "--bare")) {
static char git_dir[1024];
setenv("GIT_DIR", getcwd(git_dir, 1024), 1);
} else {
fprintf(stderr, "Unknown option: %s\n", cmd);
cmd_usage(0, NULL, NULL);
}

(*argv)++;
(*argc)--;
handled++;
}
return handled;
}

static const char *alias_command;
static char *alias_string = NULL;

@ -103,49 +156,48 @@ static int handle_alias(int *argcp, const char ***argv) @@ -103,49 +156,48 @@ static int handle_alias(int *argcp, const char ***argv)
{
int nongit = 0, ret = 0, saved_errno = errno;
const char *subdir;
int count, option_count;
const char** new_argv;

subdir = setup_git_directory_gently(&nongit);
if (!nongit) {
int count;
const char** new_argv;

alias_command = (*argv)[0];
git_config(git_alias_config);
if (alias_string) {

count = split_cmdline(alias_string, &new_argv);
alias_command = (*argv)[0];
git_config(git_alias_config);
if (alias_string) {
count = split_cmdline(alias_string, &new_argv);
option_count = handle_options(&new_argv, &count);
memmove(new_argv - option_count, new_argv,
count * sizeof(char *));
new_argv -= option_count;

if (count < 1)
die("empty alias for %s", alias_command);
if (count < 1)
die("empty alias for %s", alias_command);

if (!strcmp(alias_command, new_argv[0]))
die("recursive alias: %s", alias_command);
if (!strcmp(alias_command, new_argv[0]))
die("recursive alias: %s", alias_command);

if (getenv("GIT_TRACE")) {
int i;
fprintf(stderr, "trace: alias expansion: %s =>",
alias_command);
for (i = 0; i < count; ++i) {
fputc(' ', stderr);
sq_quote_print(stderr, new_argv[i]);
}
fputc('\n', stderr);
fflush(stderr);
if (getenv("GIT_TRACE")) {
int i;
fprintf(stderr, "trace: alias expansion: %s =>",
alias_command);
for (i = 0; i < count; ++i) {
fputc(' ', stderr);
sq_quote_print(stderr, new_argv[i]);
}
fputc('\n', stderr);
fflush(stderr);
}

/* insert after command name */
if (*argcp > 1) {
new_argv = realloc(new_argv, sizeof(char*) *
(count + *argcp));
memcpy(new_argv + count, *argv + 1,
sizeof(char*) * *argcp);
}
new_argv = realloc(new_argv, sizeof(char*) *
(count + *argcp + 1));
/* insert after command name */
memcpy(new_argv + count, *argv + 1, sizeof(char*) * *argcp);
new_argv[count+*argcp] = NULL;

*argv = new_argv;
*argcp += count - 1;
*argv = new_argv;
*argcp += count - 1;

ret = 1;
}
ret = 1;
}

if (subdir)
@ -158,51 +210,55 @@ static int handle_alias(int *argcp, const char ***argv) @@ -158,51 +210,55 @@ static int handle_alias(int *argcp, const char ***argv)

const char git_version_string[] = GIT_VERSION;

#define NEEDS_PREFIX 1

static void handle_internal_command(int argc, const char **argv, char **envp)
{
const char *cmd = argv[0];
static struct cmd_struct {
const char *cmd;
int (*fn)(int, const char **, char **);
int (*fn)(int, const char **, const char *);
int prefix;
} commands[] = {
{ "version", cmd_version },
{ "help", cmd_help },
{ "log", cmd_log },
{ "whatchanged", cmd_whatchanged },
{ "show", cmd_show },
{ "log", cmd_log, NEEDS_PREFIX },
{ "whatchanged", cmd_whatchanged, NEEDS_PREFIX },
{ "show", cmd_show, NEEDS_PREFIX },
{ "push", cmd_push },
{ "format-patch", cmd_format_patch },
{ "format-patch", cmd_format_patch, NEEDS_PREFIX },
{ "count-objects", cmd_count_objects },
{ "diff", cmd_diff },
{ "grep", cmd_grep },
{ "rm", cmd_rm },
{ "add", cmd_add },
{ "rev-list", cmd_rev_list },
{ "diff", cmd_diff, NEEDS_PREFIX },
{ "grep", cmd_grep, NEEDS_PREFIX },
{ "rm", cmd_rm, NEEDS_PREFIX },
{ "add", cmd_add, NEEDS_PREFIX },
{ "rev-list", cmd_rev_list, NEEDS_PREFIX },
{ "init-db", cmd_init_db },
{ "get-tar-commit-id", cmd_get_tar_commit_id },
{ "upload-tar", cmd_upload_tar },
{ "check-ref-format", cmd_check_ref_format },
{ "ls-files", cmd_ls_files },
{ "ls-tree", cmd_ls_tree },
{ "tar-tree", cmd_tar_tree },
{ "read-tree", cmd_read_tree },
{ "commit-tree", cmd_commit_tree },
{ "ls-files", cmd_ls_files, NEEDS_PREFIX },
{ "ls-tree", cmd_ls_tree, NEEDS_PREFIX },
{ "tar-tree", cmd_tar_tree, NEEDS_PREFIX },
{ "read-tree", cmd_read_tree, NEEDS_PREFIX },
{ "commit-tree", cmd_commit_tree, NEEDS_PREFIX },
{ "apply", cmd_apply },
{ "show-branch", cmd_show_branch },
{ "diff-files", cmd_diff_files },
{ "diff-index", cmd_diff_index },
{ "diff-stages", cmd_diff_stages },
{ "diff-tree", cmd_diff_tree },
{ "cat-file", cmd_cat_file },
{ "rev-parse", cmd_rev_parse },
{ "write-tree", cmd_write_tree },
{ "show-branch", cmd_show_branch, NEEDS_PREFIX },
{ "diff-files", cmd_diff_files, NEEDS_PREFIX },
{ "diff-index", cmd_diff_index, NEEDS_PREFIX },
{ "diff-stages", cmd_diff_stages, NEEDS_PREFIX },
{ "diff-tree", cmd_diff_tree, NEEDS_PREFIX },
{ "cat-file", cmd_cat_file, NEEDS_PREFIX },
{ "rev-parse", cmd_rev_parse, NEEDS_PREFIX },
{ "write-tree", cmd_write_tree, NEEDS_PREFIX },
{ "mailsplit", cmd_mailsplit },
{ "mailinfo", cmd_mailinfo },
{ "stripspace", cmd_stripspace },
{ "update-index", cmd_update_index },
{ "update-ref", cmd_update_ref },
{ "fmt-merge-msg", cmd_fmt_merge_msg },
{ "prune", cmd_prune },
{ "update-index", cmd_update_index, NEEDS_PREFIX },
{ "update-ref", cmd_update_ref, NEEDS_PREFIX },
{ "fmt-merge-msg", cmd_fmt_merge_msg, NEEDS_PREFIX },
{ "prune", cmd_prune, NEEDS_PREFIX },
{ "mv", cmd_mv, NEEDS_PREFIX },
};
int i;

@ -214,9 +270,13 @@ static void handle_internal_command(int argc, const char **argv, char **envp) @@ -214,9 +270,13 @@ static void handle_internal_command(int argc, const char **argv, char **envp)

for (i = 0; i < ARRAY_SIZE(commands); i++) {
struct cmd_struct *p = commands+i;
const char *prefix;
if (strcmp(p->cmd, cmd))
continue;

prefix = NULL;
if (p->prefix)
prefix = setup_git_directory();
if (getenv("GIT_TRACE")) {
int i;
fprintf(stderr, "trace: built-in: git");
@ -228,7 +288,7 @@ static void handle_internal_command(int argc, const char **argv, char **envp) @@ -228,7 +288,7 @@ static void handle_internal_command(int argc, const char **argv, char **envp)
fflush(stderr);
}

exit(p->fn(argc, argv, envp));
exit(p->fn(argc, argv, prefix));
}
}

@ -269,51 +329,19 @@ int main(int argc, const char **argv, char **envp) @@ -269,51 +329,19 @@ int main(int argc, const char **argv, char **envp)
die("cannot handle %s internally", cmd);
}

/* Default command: "help" */
cmd = "help";

/* Look for flags.. */
while (argc > 1) {
cmd = *++argv;
argc--;

if (!strcmp(cmd, "-p") || !strcmp(cmd, "--paginate")) {
setup_pager();
continue;
}

if (strncmp(cmd, "--", 2))
break;

cmd += 2;

/*
* For legacy reasons, the "version" and "help"
* commands can be written with "--" prepended
* to make them look like flags.
*/
if (!strcmp(cmd, "help"))
break;
if (!strcmp(cmd, "version"))
break;

/*
* Check remaining flags (which by now must be
* "--exec-path", but maybe we will accept
* other arguments some day)
*/
if (!strncmp(cmd, "exec-path", 9)) {
cmd += 9;
if (*cmd == '=') {
git_set_exec_path(cmd + 1);
continue;
}
puts(git_exec_path());
exit(0);
}
cmd_usage(0, NULL, NULL);
argv++;
argc--;
handle_options(&argv, &argc);
if (argc > 0) {
if (!strncmp(argv[0], "--", 2))
argv[0] += 2;
} else {
/* Default command: "help" */
argv[0] = "help";
argc = 1;
}
argv[0] = cmd;
cmd = argv[0];

/*
* We search for git commands in the following order:

166
gitweb/gitweb.cgi

@ -227,7 +227,7 @@ if (!defined $action || $action eq "summary") { @@ -227,7 +227,7 @@ if (!defined $action || $action eq "summary") {
git_tag();
exit;
} elsif ($action eq "blame") {
git_blame();
git_blame2();
exit;
} else {
undef $action;
@ -795,7 +795,7 @@ sub git_read_projects { @@ -795,7 +795,7 @@ sub git_read_projects {
if (-d $projects_list) {
# search in directory
my $dir = $projects_list;
opendir my $dh, $dir or return undef;
opendir my ($dh), $dir or return undef;
while (my $dir = readdir($dh)) {
if (-e "$projectroot/$dir/HEAD") {
my $pr = {
@ -810,7 +810,7 @@ sub git_read_projects { @@ -810,7 +810,7 @@ sub git_read_projects {
# 'git%2Fgit.git Linus+Torvalds'
# 'libs%2Fklibc%2Fklibc.git H.+Peter+Anvin'
# 'linux%2Fhotplug%2Fudev.git Greg+Kroah-Hartman'
open my $fd , $projects_list or return undef;
open my ($fd), $projects_list or return undef;
while (my $line = <$fd>) {
chomp $line;
my ($path, $owner) = split ' ', $line;
@ -1138,7 +1138,7 @@ sub git_summary { @@ -1138,7 +1138,7 @@ sub git_summary {
"</td>\n" .
"<td>";
if (defined($comment)) {
print $cgi->a({-class => "list", -href => "$my_uri?" . esc_param("p=$project;a=tag;h=$tag{'id'}")}, $comment);
print $cgi->a({-class => "list", -href => "$my_uri?" . esc_param("p=$project;a=tag;h=$tag{'id'}")}, esc_html($comment));
}
print "</td>\n" .
"<td class=\"link\">";
@ -1199,6 +1199,20 @@ sub git_summary { @@ -1199,6 +1199,20 @@ sub git_summary {
git_footer_html();
}

sub git_print_page_path {
my $name = shift;
my $type = shift;

if (!defined $name) {
print "<div class=\"page_path\"><b>/</b></div>\n";
} elsif ($type =~ "blob") {
print "<div class=\"page_path\"><b>" .
$cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=blob_plain;f=$file_name")}, esc_html($name)) . "</b><br/></div>\n";
} else {
print "<div class=\"page_path\"><b>" . esc_html($name) . "</b><br/></div>\n";
}
}

sub git_tag {
my $head = git_read_head($project);
git_header_html();
@ -1238,6 +1252,73 @@ sub git_tag { @@ -1238,6 +1252,73 @@ sub git_tag {
git_footer_html();
}

sub git_blame2 {
my $fd;
my $ftype;
die_error(undef, "Permission denied.") if (!git_get_project_config_bool ('blame'));
die_error('404 Not Found', "File name not defined") if (!$file_name);
$hash_base ||= git_read_head($project);
die_error(undef, "Reading commit failed") unless ($hash_base);
my %co = git_read_commit($hash_base)
or die_error(undef, "Reading commit failed");
if (!defined $hash) {
$hash = git_get_hash_by_path($hash_base, $file_name, "blob")
or die_error(undef, "Error looking up file");
}
$ftype = git_get_type($hash);
if ($ftype !~ "blob") {
die_error("400 Bad Request", "object is not a blob");
}
open ($fd, "-|", $GIT, "blame", '-l', $file_name, $hash_base)
or die_error(undef, "Open failed");
git_header_html();
print "<div class=\"page_nav\">\n" .
$cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=summary")}, "summary") .
" | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=shortlog")}, "shortlog") .
" | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=log")}, "log") .
" | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=commit;h=$hash_base")}, "commit") .
" | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=commitdiff;h=$hash_base")}, "commitdiff") .
" | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=tree;h=$co{'tree'};hb=$hash_base")}, "tree") . "<br/>\n";
print $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=blob;h=$hash;hb=$hash_base;f=$file_name")}, "blob") .
" | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=blame;f=$file_name")}, "head") . "<br/>\n";
print "</div>\n".
"<div>" .
$cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=commit;h=$hash_base"), -class => "title"}, esc_html($co{'title'})) .
"</div>\n";
git_print_page_path($file_name, $ftype);
my @rev_color = (qw(light dark));
my $num_colors = scalar(@rev_color);
my $current_color = 0;
my $last_rev;
print "<div class=\"page_body\">\n";
print "<table class=\"blame\">\n";
print "<tr><th>Commit</th><th>Line</th><th>Data</th></tr>\n";
while (<$fd>) {
/^([0-9a-fA-F]{40}).*?(\d+)\)\s{1}(\s*.*)/;
my $full_rev = $1;
my $rev = substr($full_rev, 0, 8);
my $lineno = $2;
my $data = $3;

if (!defined $last_rev) {
$last_rev = $full_rev;
} elsif ($last_rev ne $full_rev) {
$last_rev = $full_rev;
$current_color = ++$current_color % $num_colors;
}
print "<tr class=\"$rev_color[$current_color]\">\n";
print "<td class=\"sha1\">" .
$cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=commit;h=$full_rev;f=$file_name")}, esc_html($rev)) . "</td>\n";
print "<td class=\"linenr\"><a id=\"l$lineno\" href=\"#l$lineno\" class=\"linenr\">" . esc_html($lineno) . "</a></td>\n";
print "<td class=\"pre\">" . esc_html($data) . "</td>\n";
print "</tr>\n";
}
print "</table>\n";
print "</div>";
close $fd or print "Reading blob failed\n";
git_footer_html();
}

sub git_blame {
my $fd;
die_error('403 Permission denied', "Permission denied.") if (!git_get_project_config_bool ('blame'));
@ -1266,7 +1347,7 @@ sub git_blame { @@ -1266,7 +1347,7 @@ sub git_blame {
"<div>" .
$cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=commit;h=$hash_base"), -class => "title"}, esc_html($co{'title'})) .
"</div>\n";
print "<div class=\"page_path\"><b>" . esc_html($file_name) . "</b></div>\n";
git_print_page_path($file_name);
print "<div class=\"page_body\">\n";
print <<HTML;
<table class="blame">
@ -1531,6 +1612,14 @@ sub git_blob_plain_mimetype { @@ -1531,6 +1612,14 @@ sub git_blob_plain_mimetype {
}

sub git_blob_plain {
if (!defined $hash) {
if (defined $file_name) {
my $base = $hash_base || git_read_head($project);
$hash = git_get_hash_by_path($base, $file_name, "blob") || die_error(undef, "Error lookup file.");
} else {
die_error(undef, "No file name defined.");
}
}
my $type = shift;
open my $fd, "-|", "$GIT cat-file blob $hash" or die_error("Couldn't cat $file_name, $hash");

@ -1554,10 +1643,14 @@ sub git_blob_plain { @@ -1554,10 +1643,14 @@ sub git_blob_plain {
}

sub git_blob {
if (!defined $hash && defined $file_name) {
my $base = $hash_base || git_read_head($project);
$hash = git_get_hash_by_path($base, $file_name, "blob") || die_error(undef, "Error lookup file.");
}
if (!defined $hash) {
if (defined $file_name) {
my $base = $hash_base || git_read_head($project);
$hash = git_get_hash_by_path($base, $file_name, "blob") || die_error(undef, "Error lookup file.");
} else {
die_error(undef, "No file name defined.");
}
}
my $have_blame = git_get_project_config_bool ('blame');
open my $fd, "-|", "$GIT cat-file blob $hash" or die_error(undef, "Open failed.");
my $mimetype = git_blob_plain_mimetype($fd, $file_name);
@ -1592,9 +1685,7 @@ sub git_blob { @@ -1592,9 +1685,7 @@ sub git_blob {
"<br/><br/></div>\n" .
"<div class=\"title\">$hash</div>\n";
}
if (defined $file_name) {
print "<div class=\"page_path\"><b>" . esc_html($file_name) . "</b></div>\n";
}
git_print_page_path($file_name, "blob");
print "<div class=\"page_body\">\n";
my $nr;
while (my $line = <$fd>) {
@ -1659,10 +1750,8 @@ sub git_tree { @@ -1659,10 +1750,8 @@ sub git_tree {
}
if (defined $file_name) {
$base = esc_html("$file_name/");
print "<div class=\"page_path\"><b>/" . esc_html($file_name) . "</b></div>\n";
} else {
print "<div class=\"page_path\"><b>/</b></div>\n";
}
git_print_page_path($file_name);
print "<div class=\"page_body\">\n";
print "<table cellspacing=\"0\">\n";
my $alternate = 0;
@ -1687,7 +1776,7 @@ sub git_tree { @@ -1687,7 +1776,7 @@ sub git_tree {
"<td class=\"link\">" .
$cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=blob;h=$t_hash$base_key;f=$base$t_name")}, "blob") .
# " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=blame;h=$t_hash$base_key;f=$base$t_name")}, "blame") .
" | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=history;h=$hash_base;f=$base$t_name")}, "history") .
" | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=history;h=$t_hash;hb=$hash_base;f=$base$t_name")}, "history") .
" | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=blob_plain;h=$t_hash;f=$base$t_name")}, "raw") .
"</td>\n";
} elsif ($t_type eq "tree") {
@ -1696,7 +1785,7 @@ sub git_tree { @@ -1696,7 +1785,7 @@ sub git_tree {
"</td>\n" .
"<td class=\"link\">" .
$cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=tree;h=$t_hash$base_key;f=$base$t_name")}, "tree") .
" | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=history;h=$hash_base;f=$base$t_name")}, "history") .
" | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=history;hb=$hash_base;f=$base$t_name")}, "history") .
"</td>\n";
}
print "</tr>\n";
@ -1931,7 +2020,13 @@ sub git_commit { @@ -1931,7 +2020,13 @@ sub git_commit {
print " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=commitdiff;h=$hash")}, "commitdiff");
}
print " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=tree;h=$co{'tree'};hb=$hash")}, "tree") . "\n" .
"<br/><br/></div>\n";
"<br/>\n";
if (defined $file_name && defined $co{'parent'}) {
my $parent = $co{'parent'};
print $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=blame;hb=$parent;f=$file_name")}, "blame") . "\n";
}
print "<br/></div>\n";

if (defined $co{'parent'}) {
print "<div>\n" .
$cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=commitdiff;h=$hash"), -class => "title"}, esc_html($co{'title'}) . $ref) . "\n" .
@ -2041,7 +2136,7 @@ sub git_commit { @@ -2041,7 +2136,7 @@ sub git_commit {
"<td><span class=\"file_status deleted\">[deleted " . file_type($from_mode). "]</span></td>\n" .
"<td class=\"link\">" .
$cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=blob;h=$from_id;hb=$hash;f=$file")}, "blob") .
" | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=history;h=$hash;f=$file")}, "history") .
" | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=history;hb=$hash;f=$file")}, "history") .
"</td>\n"
} elsif ($status eq "M" || $status eq "T") {
my $mode_chnge = "";
@ -2072,7 +2167,7 @@ sub git_commit { @@ -2072,7 +2167,7 @@ sub git_commit {
if ($to_id ne $from_id) {
print " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=blobdiff;h=$to_id;hp=$from_id;hb=$hash;f=$file")}, "diff");
}
print " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=history;h=$hash;f=$file")}, "history") . "\n";
print " | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=history;hb=$hash;f=$file")}, "history") . "\n";
print "</td>\n";
} elsif ($status eq "R") {
my ($from_file, $to_file) = split "\t", $file;
@ -2120,9 +2215,7 @@ sub git_blobdiff { @@ -2120,9 +2215,7 @@ sub git_blobdiff {
"<br/><br/></div>\n" .
"<div class=\"title\">$hash vs $hash_parent</div>\n";
}
if (defined $file_name) {
print "<div class=\"page_path\"><b>/" . esc_html($file_name) . "</b></div>\n";
}
git_print_page_path($file_name, "blob");
print "<div class=\"page_body\">\n" .
"<div class=\"diff_info\">blob:" .
$cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=blob;h=$hash_parent;hb=$hash_base;f=$file_name")}, $hash_parent) .
@ -2293,10 +2386,11 @@ sub git_commitdiff_plain { @@ -2293,10 +2386,11 @@ sub git_commitdiff_plain {
}

sub git_history {
if (!defined $hash) {
$hash = git_read_head($project);
if (!defined $hash_base) {
$hash_base = git_read_head($project);
}
my %co = git_read_commit($hash);
my $ftype;
my %co = git_read_commit($hash_base);
if (!%co) {
die_error(undef, "Unknown commit object.");
}
@ -2306,18 +2400,24 @@ sub git_history { @@ -2306,18 +2400,24 @@ sub git_history {
$cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=summary")}, "summary") .
" | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=shortlog")}, "shortlog") .
" | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=log")}, "log") .
" | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=commit;h=$hash")}, "commit") .
" | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=commitdiff;h=$hash")}, "commitdiff") .
" | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=tree;h=$co{'tree'};hb=$hash")}, "tree") .
" | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=commit;h=$hash_base")}, "commit") .
" | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=commitdiff;h=$hash_base")}, "commitdiff") .
" | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=tree;h=$co{'tree'};hb=$hash_base")}, "tree") .
"<br/><br/>\n" .
"</div>\n";
print "<div>\n" .
$cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=commit;h=$hash"), -class => "title"}, esc_html($co{'title'})) . "\n" .
$cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=commit;h=$hash_base"), -class => "title"}, esc_html($co{'title'})) . "\n" .
"</div>\n";
print "<div class=\"page_path\"><b>/" . esc_html($file_name) . "</b><br/></div>\n";
if (!defined $hash && defined $file_name) {
$hash = git_get_hash_by_path($hash_base, $file_name);
}
if (defined $hash) {
$ftype = git_get_type($hash);
}
git_print_page_path($file_name, $ftype);

open my $fd, "-|",
"$GIT rev-list --full-history $hash -- \'$file_name\'";
"$GIT rev-list --full-history $hash_base -- \'$file_name\'";
print "<table cellspacing=\"0\">\n";
my $alternate = 0;
while (my $line = <$fd>) {
@ -2345,7 +2445,7 @@ sub git_history { @@ -2345,7 +2445,7 @@ sub git_history {
$cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=commit;h=$commit")}, "commit") .
" | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=commitdiff;h=$commit")}, "commitdiff") .
" | " . $cgi->a({-href => "$my_uri?" . esc_param("p=$project;a=blob;hb=$commit;f=$file_name")}, "blob");
my $blob = git_get_hash_by_path($hash, $file_name);
my $blob = git_get_hash_by_path($hash_base, $file_name);
my $blob_parent = git_get_hash_by_path($commit, $file_name);
if (defined $blob && defined $blob_parent && $blob ne $blob_parent) {
print " | " .

45
http-fetch.c

@ -36,6 +36,8 @@ enum XML_Status { @@ -36,6 +36,8 @@ enum XML_Status {
#define PREV_BUF_SIZE 4096
#define RANGE_HEADER_SIZE 30

static int commits_on_stdin = 0;

static int got_alternates = -1;
static int corrupt_object_found = 0;

@ -43,7 +45,7 @@ static struct curl_slist *no_pragma_header; @@ -43,7 +45,7 @@ static struct curl_slist *no_pragma_header;

struct alt_base
{
char *base;
const char *base;
int path_len;
int got_indices;
struct packed_git *packs;
@ -81,7 +83,7 @@ struct object_request @@ -81,7 +83,7 @@ struct object_request
};

struct alternates_request {
char *base;
const char *base;
char *url;
struct buffer *buffer;
struct active_request_slot *slot;
@ -142,7 +144,7 @@ static size_t fwrite_sha1_file(void *ptr, size_t eltsize, size_t nmemb, @@ -142,7 +144,7 @@ static size_t fwrite_sha1_file(void *ptr, size_t eltsize, size_t nmemb,
return size;
}

static void fetch_alternates(char *base);
static void fetch_alternates(const char *base);

static void process_object_response(void *callback_data);

@ -507,7 +509,7 @@ static void process_alternates_response(void *callback_data) @@ -507,7 +509,7 @@ static void process_alternates_response(void *callback_data)
(struct alternates_request *)callback_data;
struct active_request_slot *slot = alt_req->slot;
struct alt_base *tail = alt;
char *base = alt_req->base;
const char *base = alt_req->base;
static const char null_byte = '\0';
char *data;
int i = 0;
@ -612,7 +614,7 @@ static void process_alternates_response(void *callback_data) @@ -612,7 +614,7 @@ static void process_alternates_response(void *callback_data)
got_alternates = 1;
}

static void fetch_alternates(char *base)
static void fetch_alternates(const char *base)
{
struct buffer buffer;
char *url;
@ -1185,7 +1187,7 @@ int fetch_ref(char *ref, unsigned char *sha1) @@ -1185,7 +1187,7 @@ int fetch_ref(char *ref, unsigned char *sha1)
char *url;
char hex[42];
struct buffer buffer;
char *base = alt->base;
const char *base = alt->base;
struct active_request_slot *slot;
struct slot_results results;
buffer.size = 41;
@ -1214,10 +1216,12 @@ int fetch_ref(char *ref, unsigned char *sha1) @@ -1214,10 +1216,12 @@ int fetch_ref(char *ref, unsigned char *sha1)
return 0;
}

int main(int argc, char **argv)
int main(int argc, const char **argv)
{
char *commit_id;
char *url;
int commits;
const char **write_ref = NULL;
char **commit_id;
const char *url;
char *path;
int arg = 1;
int rc = 0;
@ -1237,20 +1241,26 @@ int main(int argc, char **argv) @@ -1237,20 +1241,26 @@ int main(int argc, char **argv)
} else if (argv[arg][1] == 'v') {
get_verbosely = 1;
} else if (argv[arg][1] == 'w') {
write_ref = argv[arg + 1];
write_ref = &argv[arg + 1];
arg++;
} else if (!strcmp(argv[arg], "--recover")) {
get_recover = 1;
} else if (!strcmp(argv[arg], "--stdin")) {
commits_on_stdin = 1;
}
arg++;
}
if (argc < arg + 2) {
usage("git-http-fetch [-c] [-t] [-a] [-d] [-v] [--recover] [-w ref] commit-id url");
if (argc < arg + 2 - commits_on_stdin) {
usage("git-http-fetch [-c] [-t] [-a] [-v] [--recover] [-w ref] [--stdin] commit-id url");
return 1;
}
commit_id = argv[arg];
url = argv[arg + 1];
write_ref_log_details = url;
if (commits_on_stdin) {
commits = pull_targets_stdin(&commit_id, &write_ref);
} else {
commit_id = (char **) &argv[arg++];
commits = 1;
}
url = argv[arg];

http_init();

@ -1268,13 +1278,16 @@ int main(int argc, char **argv) @@ -1268,13 +1278,16 @@ int main(int argc, char **argv)
alt->path_len = strlen(path);
}

if (pull(commit_id))
if (pull(commits, commit_id, write_ref, url))
rc = 1;

http_cleanup();

curl_slist_free_all(no_pragma_header);

if (commits_on_stdin)
pull_targets_free(commits, commit_id, write_ref);

if (corrupt_object_found) {
fprintf(stderr,
"Some loose object were found to be corrupt, but they might be just\n"

2
http-push.c

@ -2521,7 +2521,7 @@ int main(int argc, char **argv) @@ -2521,7 +2521,7 @@ int main(int argc, char **argv)
commit_argv[3] = old_sha1_hex;
commit_argc++;
}
init_revisions(&revs);
init_revisions(&revs, setup_git_directory());
setup_revisions(commit_argc, commit_argv, &revs, NULL);
free(new_sha1_hex);
if (old_sha1_hex) {

34
local-fetch.c

@ -8,8 +8,9 @@ @@ -8,8 +8,9 @@
static int use_link = 0;
static int use_symlink = 0;
static int use_filecopy = 1;
static int commits_on_stdin = 0;

static char *path; /* "Remote" git repository */
static const char *path; /* "Remote" git repository */

void prefetch(unsigned char *sha1)
{
@ -194,17 +195,19 @@ int fetch_ref(char *ref, unsigned char *sha1) @@ -194,17 +195,19 @@ int fetch_ref(char *ref, unsigned char *sha1)
}

static const char local_pull_usage[] =
"git-local-fetch [-c] [-t] [-a] [-d] [-v] [-w filename] [--recover] [-l] [-s] [-n] commit-id path";
"git-local-fetch [-c] [-t] [-a] [-v] [-w filename] [--recover] [-l] [-s] [-n] [--stdin] commit-id path";

/*
/*
* By default we only use file copy.
* If -l is specified, a hard link is attempted.
* If -s is specified, then a symlink is attempted.
* If -n is _not_ specified, then a regular file-to-file copy is done.
*/
int main(int argc, char **argv)
int main(int argc, const char **argv)
{
char *commit_id;
int commits;
const char **write_ref = NULL;
char **commit_id;
int arg = 1;

setup_git_directory();
@ -229,21 +232,30 @@ int main(int argc, char **argv) @@ -229,21 +232,30 @@ int main(int argc, char **argv)
else if (argv[arg][1] == 'v')
get_verbosely = 1;
else if (argv[arg][1] == 'w')
write_ref = argv[++arg];
write_ref = &argv[++arg];
else if (!strcmp(argv[arg], "--recover"))
get_recover = 1;
else if (!strcmp(argv[arg], "--stdin"))
commits_on_stdin = 1;
else
usage(local_pull_usage);
arg++;
}
if (argc < arg + 2)
if (argc < arg + 2 - commits_on_stdin)
usage(local_pull_usage);
commit_id = argv[arg];
path = argv[arg + 1];
write_ref_log_details = path;
if (commits_on_stdin) {
commits = pull_targets_stdin(&commit_id, &write_ref);
} else {
commit_id = (char **) &argv[arg++];
commits = 1;
}
path = argv[arg];

if (pull(commit_id))
if (pull(commits, commit_id, write_ref, path))
return 1;

if (commits_on_stdin)
pull_targets_free(commits, commit_id, write_ref);

return 0;
}

10
log-tree.c

@ -97,6 +97,11 @@ void show_log(struct rev_info *opt, const char *sep) @@ -97,6 +97,11 @@ void show_log(struct rev_info *opt, const char *sep)
subject = "Subject: ";

printf("From %s Mon Sep 17 00:00:00 2001\n", sha1);
if (opt->message_id)
printf("Message-Id: <%s>\n", opt->message_id);
if (opt->ref_message_id)
printf("In-Reply-To: <%s>\nReferences: <%s>\n",
opt->ref_message_id, opt->ref_message_id);
if (opt->mime_boundary) {
static char subject_buffer[1024];
static char buffer[1024];
@ -129,7 +134,8 @@ void show_log(struct rev_info *opt, const char *sep) @@ -129,7 +134,8 @@ void show_log(struct rev_info *opt, const char *sep)
opt->diffopt.stat_sep = buffer;
}
} else {
printf("%s%s",
printf("%s%s%s",
diff_get_color(opt->diffopt.color_diff, DIFF_COMMIT),
opt->commit_format == CMIT_FMT_ONELINE ? "" : "commit ",
diff_unique_abbrev(commit->object.sha1, abbrev_commit));
if (opt->parents)
@ -138,6 +144,8 @@ void show_log(struct rev_info *opt, const char *sep) @@ -138,6 +144,8 @@ void show_log(struct rev_info *opt, const char *sep)
printf(" (from %s)",
diff_unique_abbrev(parent->object.sha1,
abbrev_commit));
printf("%s",
diff_get_color(opt->diffopt.color_diff, DIFF_RESET));
putchar(opt->commit_format == CMIT_FMT_ONELINE ? ' ' : '\n');
}


13
pack-objects.c

@ -63,6 +63,7 @@ static const char *base_name; @@ -63,6 +63,7 @@ static const char *base_name;
static unsigned char pack_file_sha1[20];
static int progress = 1;
static volatile sig_atomic_t progress_update = 0;
static int window = 10;

/*
* The object names in objects array are hashed with this hashtable,
@ -1216,16 +1217,26 @@ static void setup_progress_signal(void) @@ -1216,16 +1217,26 @@ static void setup_progress_signal(void)
setitimer(ITIMER_REAL, &v, NULL);
}

static int git_pack_config(const char *k, const char *v)
{
if(!strcmp(k, "pack.window")) {
window = git_config_int(k, v);
return 0;
}
return git_default_config(k, v);
}

int main(int argc, char **argv)
{
SHA_CTX ctx;
char line[40 + 1 + PATH_MAX + 2];
int window = 10, depth = 10, pack_to_stdout = 0;
int depth = 10, pack_to_stdout = 0;
struct object_entry **list;
int num_preferred_base = 0;
int i;

setup_git_directory();
git_config(git_pack_config);

progress = isatty(2);
for (i = 1; i < argc; i++) {

39
read-cache.c

@ -319,6 +319,45 @@ int remove_file_from_cache(const char *path) @@ -319,6 +319,45 @@ int remove_file_from_cache(const char *path)
return 0;
}

int add_file_to_index(const char *path, int verbose)
{
int size, namelen;
struct stat st;
struct cache_entry *ce;

if (lstat(path, &st))
die("%s: unable to stat (%s)", path, strerror(errno));

if (!S_ISREG(st.st_mode) && !S_ISLNK(st.st_mode))
die("%s: can only add regular files or symbolic links", path);

namelen = strlen(path);
size = cache_entry_size(namelen);
ce = xcalloc(1, size);
memcpy(ce->name, path, namelen);
ce->ce_flags = htons(namelen);
fill_stat_cache_info(ce, &st);

ce->ce_mode = create_ce_mode(st.st_mode);
if (!trust_executable_bit) {
/* If there is an existing entry, pick the mode bits
* from it.
*/
int pos = cache_name_pos(path, namelen);
if (pos >= 0)
ce->ce_mode = active_cache[pos]->ce_mode;
}

if (index_path(ce->sha1, path, &st, 1))
die("unable to index file %s", path);
if (add_cache_entry(ce, ADD_CACHE_OK_TO_ADD))
die("unable to add %s to index",path);
if (verbose)
printf("add '%s'\n", path);
cache_tree_invalidate_path(active_cache_tree, path);
return 0;
}

int ce_same_name(struct cache_entry *a, struct cache_entry *b)
{
int len = ce_namelen(a);

5
refs.c

@ -294,6 +294,7 @@ static struct ref_lock *lock_ref_sha1_basic(const char *path, @@ -294,6 +294,7 @@ static struct ref_lock *lock_ref_sha1_basic(const char *path,
int plen,
const unsigned char *old_sha1, int mustexist)
{
const char *orig_path = path;
struct ref_lock *lock;
struct stat st;

@ -303,7 +304,11 @@ static struct ref_lock *lock_ref_sha1_basic(const char *path, @@ -303,7 +304,11 @@ static struct ref_lock *lock_ref_sha1_basic(const char *path,
plen = strlen(path) - plen;
path = resolve_ref(path, lock->old_sha1, mustexist);
if (!path) {
int last_errno = errno;
error("unable to resolve reference %s: %s",
orig_path, strerror(errno));
unlock_ref(lock);
errno = last_errno;
return NULL;
}
lock->lk = xcalloc(1, sizeof(struct lock_file));

4
revision.c

@ -509,7 +509,7 @@ static int add_parents_only(struct rev_info *revs, const char *arg, int flags) @@ -509,7 +509,7 @@ static int add_parents_only(struct rev_info *revs, const char *arg, int flags)
return 1;
}

void init_revisions(struct rev_info *revs)
void init_revisions(struct rev_info *revs, const char *prefix)
{
memset(revs, 0, sizeof(*revs));

@ -521,7 +521,7 @@ void init_revisions(struct rev_info *revs) @@ -521,7 +521,7 @@ void init_revisions(struct rev_info *revs)
revs->pruning.change = file_change;
revs->lifo = 1;
revs->dense = 1;
revs->prefix = setup_git_directory();
revs->prefix = prefix;
revs->max_age = -1;
revs->min_age = -1;
revs->max_count = -1;

4
revision.h

@ -61,6 +61,8 @@ struct rev_info { @@ -61,6 +61,8 @@ struct rev_info {
struct log_info *loginfo;
int nr, total;
const char *mime_boundary;
const char *message_id;
const char *ref_message_id;
const char *add_signoff;
const char *extra_headers;

@ -85,7 +87,7 @@ struct rev_info { @@ -85,7 +87,7 @@ struct rev_info {
extern int rev_same_tree_as_empty(struct rev_info *, struct tree *t1);
extern int rev_compare_tree(struct rev_info *, struct tree *t1, struct tree *t2);

extern void init_revisions(struct rev_info *revs);
extern void init_revisions(struct rev_info *revs, const char *prefix);
extern int setup_revisions(int argc, const char **argv, struct rev_info *revs, const char *def);
extern void prepare_revision_walk(struct rev_info *revs);
extern struct commit *get_revision(struct rev_info *revs);

4
setup.c

@ -184,6 +184,10 @@ const char *setup_git_directory_gently(int *nongit_ok) @@ -184,6 +184,10 @@ const char *setup_git_directory_gently(int *nongit_ok)
}
return NULL;
bad_dir_environ:
if (!nongit_ok) {
*nongit_ok = 1;
return NULL;
}
path[len] = 0;
die("Not a git repository: '%s'", path);
}

132
sha1_file.c

@ -684,26 +684,74 @@ static void *map_sha1_file_internal(const unsigned char *sha1, @@ -684,26 +684,74 @@ static void *map_sha1_file_internal(const unsigned char *sha1,
return map;
}

static int unpack_sha1_header(z_stream *stream, void *map, unsigned long mapsize, void *buffer, unsigned long size)
static int unpack_sha1_header(z_stream *stream, unsigned char *map, unsigned long mapsize, void *buffer, unsigned long bufsiz)
{
unsigned char c;
unsigned int word, bits;
unsigned long size;
static const char *typename[8] = {
NULL, /* OBJ_EXT */
"commit", "tree", "blob", "tag",
NULL, NULL, NULL
};
const char *type;

/* Get the data stream */
memset(stream, 0, sizeof(*stream));
stream->next_in = map;
stream->avail_in = mapsize;
stream->next_out = buffer;
stream->avail_out = size;
stream->avail_out = bufsiz;

/*
* Is it a zlib-compressed buffer? If so, the first byte
* must be 0x78 (15-bit window size, deflated), and the
* first 16-bit word is evenly divisible by 31
*/
word = (map[0] << 8) + map[1];
if (map[0] == 0x78 && !(word % 31)) {
inflateInit(stream);
return inflate(stream, 0);
}

c = *map++;
mapsize--;
type = typename[(c >> 4) & 7];
if (!type)
return -1;

bits = 4;
size = c & 0xf;
while ((c & 0x80)) {
if (bits >= 8*sizeof(long))
return -1;
c = *map++;
size += (c & 0x7f) << bits;
bits += 7;
mapsize--;
}

/* Set up the stream for the rest.. */
stream->next_in = map;
stream->avail_in = mapsize;
inflateInit(stream);
return inflate(stream, 0);

/* And generate the fake traditional header */
stream->total_out = 1 + snprintf(buffer, bufsiz, "%s %lu", type, size);
return 0;
}

static void *unpack_sha1_rest(z_stream *stream, void *buffer, unsigned long size)
{
int bytes = strlen(buffer) + 1;
unsigned char *buf = xmalloc(1+size);
unsigned long n;

memcpy(buf, (char *) buffer + bytes, stream->total_out - bytes);
bytes = stream->total_out - bytes;
n = stream->total_out - bytes;
if (n > size)
n = size;
memcpy(buf, (char *) buffer + bytes, n);
bytes = n;
if (bytes < size) {
stream->next_out = buf + bytes;
stream->avail_out = size - bytes;
@ -1331,31 +1379,29 @@ char *write_sha1_file_prepare(void *buf, @@ -1331,31 +1379,29 @@ char *write_sha1_file_prepare(void *buf,
static int link_temp_to_file(const char *tmpfile, char *filename)
{
int ret;
char *dir;

if (!link(tmpfile, filename))
return 0;

/*
* Try to mkdir the last path component if that failed
* with an ENOENT.
* Try to mkdir the last path component if that failed.
*
* Re-try the "link()" regardless of whether the mkdir
* succeeds, since a race might mean that somebody
* else succeeded.
*/
ret = errno;
if (ret == ENOENT) {
char *dir = strrchr(filename, '/');
if (dir) {
*dir = 0;
mkdir(filename, 0777);
if (adjust_shared_perm(filename))
return -2;
*dir = '/';
if (!link(tmpfile, filename))
return 0;
ret = errno;
}
dir = strrchr(filename, '/');
if (dir) {
*dir = 0;
mkdir(filename, 0777);
if (adjust_shared_perm(filename))
return -2;
*dir = '/';
if (!link(tmpfile, filename))
return 0;
ret = errno;
}
return ret;
}
@ -1414,6 +1460,49 @@ static int write_buffer(int fd, const void *buf, size_t len) @@ -1414,6 +1460,49 @@ static int write_buffer(int fd, const void *buf, size_t len)
return 0;
}

static int write_binary_header(unsigned char *hdr, enum object_type type, unsigned long len)
{
int hdr_len;
unsigned char c;

c = (type << 4) | (len & 15);
len >>= 4;
hdr_len = 1;
while (len) {
*hdr++ = c | 0x80;
hdr_len++;
c = (len & 0x7f);
len >>= 7;
}
*hdr = c;
return hdr_len;
}

static void setup_object_header(z_stream *stream, const char *type, unsigned long len)
{
int obj_type, hdr;

if (use_legacy_headers) {
while (deflate(stream, 0) == Z_OK)
/* nothing */;
return;
}
if (!strcmp(type, blob_type))
obj_type = OBJ_BLOB;
else if (!strcmp(type, tree_type))
obj_type = OBJ_TREE;
else if (!strcmp(type, commit_type))
obj_type = OBJ_COMMIT;
else if (!strcmp(type, tag_type))
obj_type = OBJ_TAG;
else
die("trying to generate bogus object of type '%s'", type);
hdr = write_binary_header(stream->next_out, obj_type, len);
stream->total_out = hdr;
stream->next_out += hdr;
stream->avail_out -= hdr;
}

int write_sha1_file(void *buf, unsigned long len, const char *type, unsigned char *returnsha1)
{
int size;
@ -1459,7 +1548,7 @@ int write_sha1_file(void *buf, unsigned long len, const char *type, unsigned cha @@ -1459,7 +1548,7 @@ int write_sha1_file(void *buf, unsigned long len, const char *type, unsigned cha
/* Set it up */
memset(&stream, 0, sizeof(stream));
deflateInit(&stream, zlib_compression_level);
size = deflateBound(&stream, len+hdrlen);
size = 8 + deflateBound(&stream, len+hdrlen);
compressed = xmalloc(size);

/* Compress it */
@ -1469,8 +1558,7 @@ int write_sha1_file(void *buf, unsigned long len, const char *type, unsigned cha @@ -1469,8 +1558,7 @@ int write_sha1_file(void *buf, unsigned long len, const char *type, unsigned cha
/* First header.. */
stream.next_in = hdr;
stream.avail_in = hdrlen;
while (deflate(&stream, 0) == Z_OK)
/* nothing */;
setup_object_header(&stream, type, len);

/* Then the data itself.. */
stream.next_in = buf;

6
ssh-fetch.c

@ -120,9 +120,10 @@ int fetch_ref(char *ref, unsigned char *sha1) @@ -120,9 +120,10 @@ int fetch_ref(char *ref, unsigned char *sha1)

static const char ssh_fetch_usage[] =
MY_PROGRAM_NAME
" [-c] [-t] [-a] [-v] [-d] [--recover] [-w ref] commit-id url";
" [-c] [-t] [-a] [-v] [--recover] [-w ref] commit-id url";
int main(int argc, char **argv)
{
const char *write_ref = NULL;
char *commit_id;
char *url;
int arg = 1;
@ -159,7 +160,6 @@ int main(int argc, char **argv) @@ -159,7 +160,6 @@ int main(int argc, char **argv)
}
commit_id = argv[arg];
url = argv[arg + 1];
write_ref_log_details = url;

if (setup_connection(&fd_in, &fd_out, prog, url, arg, argv + 1))
return 1;
@ -167,7 +167,7 @@ int main(int argc, char **argv) @@ -167,7 +167,7 @@ int main(int argc, char **argv)
if (get_version())
return 1;

if (pull(commit_id))
if (pull(1, &commit_id, &write_ref, url))
return 1;

return 0;

12
t/t1400-update-ref.sh

@ -14,6 +14,8 @@ D=4444444444444444444444444444444444444444 @@ -14,6 +14,8 @@ D=4444444444444444444444444444444444444444
E=5555555555555555555555555555555555555555
F=6666666666666666666666666666666666666666
m=refs/heads/master
n_dir=refs/heads/gu
n=$n_dir/fixes

test_expect_success \
"create $m" \
@ -25,6 +27,16 @@ test_expect_success \ @@ -25,6 +27,16 @@ test_expect_success \
test $B = $(cat .git/$m)'
rm -f .git/$m

test_expect_success \
"fail to create $n" \
'touch .git/$n_dir
git-update-ref $n $A >out 2>err
test $? = 1 &&
test "" = "$(cat out)" &&
grep "error: unable to resolve reference" err &&
grep $n err'
rm -f .git/$n_dir out err

test_expect_success \
"create $m (by HEAD)" \
'git-update-ref HEAD $A &&

24
t/t4102-apply-rename.sh

@ -13,8 +13,8 @@ test_description='git-apply handling copy/rename patch. @@ -13,8 +13,8 @@ test_description='git-apply handling copy/rename patch.
cat >test-patch <<\EOF
diff --git a/foo b/bar
similarity index 47%
copy from foo
copy to bar
rename from foo
rename to bar
--- a/foo
+++ b/bar
@@ -1 +1 @@
@ -39,4 +39,24 @@ else @@ -39,4 +39,24 @@ else
'test -f bar && ls -l bar | grep "^-..x......"'
fi

test_expect_success 'apply reverse' \
'git-apply -R --index --stat --summary --apply test-patch &&
test "$(cat foo)" = "This is foo"'

cat >test-patch <<\EOF
diff --git a/foo b/bar
similarity index 47%
copy from foo
copy to bar
--- a/foo
+++ b/bar
@@ -1 +1 @@
-This is foo
+This is bar
EOF

test_expect_success 'apply copy' \
'git-apply --index --stat --summary --apply test-patch &&
test "$(cat bar)" = "This is bar" -a "$(cat foo)" = "This is foo"'

test_done

4
t/t4103-apply-binary.sh

@ -35,8 +35,8 @@ git-commit -m 'Second Version' @@ -35,8 +35,8 @@ git-commit -m 'Second Version'
git-diff-tree -p master binary >B.diff
git-diff-tree -p -C master binary >C.diff

git-diff-tree -p --full-index master binary >BF.diff
git-diff-tree -p --full-index -C master binary >CF.diff
git-diff-tree -p --binary master binary >BF.diff
git-diff-tree -p --binary -C master binary >CF.diff

test_expect_success 'stat binary diff -- should not fail.' \
'git-checkout master

28
t/t4112-apply-renames.sh

@ -11,31 +11,7 @@ test_description='git-apply should not get confused with rename/copy. @@ -11,31 +11,7 @@ test_description='git-apply should not get confused with rename/copy.

# setup

mkdir -p include/arch/x86_64/klibc klibc/arch/x86_64/include/klibc

cat >include/arch/x86_64/klibc/archsetjmp.h <<\EOF
/*
* arch/x86_64/include/klibc/archsetjmp.h
*/

#ifndef _KLIBC_ARCHSETJMP_H
#define _KLIBC_ARCHSETJMP_H

struct __jmp_buf {
unsigned long __rbx;
unsigned long __rsp;
unsigned long __rbp;
unsigned long __r12;
unsigned long __r13;
unsigned long __r14;
unsigned long __r15;
unsigned long __rip;
};

typedef struct __jmp_buf jmp_buf[1];

#endif /* _SETJMP_H */
EOF
mkdir -p klibc/arch/x86_64/include/klibc

cat >klibc/arch/x86_64/include/klibc/archsetjmp.h <<\EOF
/*
@ -139,7 +115,7 @@ rename to include/arch/m32r/klibc/archsetjmp.h @@ -139,7 +115,7 @@ rename to include/arch/m32r/klibc/archsetjmp.h
+#endif /* _KLIBC_ARCHSETJMP_H */
EOF

find include klibc -type f -print | xargs git-update-index --add --
find klibc -type f -print | xargs git-update-index --add --

test_expect_success 'check rename/copy patch' 'git-apply --check patch'


105
t/t4114-apply-typechange.sh

@ -0,0 +1,105 @@ @@ -0,0 +1,105 @@
#!/bin/sh
#
# Copyright (c) 2006 Eric Wong
#

test_description='git-apply should not get confused with type changes.

'

. ./test-lib.sh

test_expect_success 'setup repository and commits' '
echo "hello world" > foo &&
echo "hi planet" > bar &&
git update-index --add foo bar &&
git commit -m initial &&
git branch initial &&
rm -f foo &&
ln -s bar foo &&
git update-index foo &&
git commit -m "foo symlinked to bar" &&
git branch foo-symlinked-to-bar &&
rm -f foo &&
echo "how far is the sun?" > foo &&
git update-index foo &&
git commit -m "foo back to file" &&
git branch foo-back-to-file &&
rm -f foo &&
git update-index --remove foo &&
mkdir foo &&
echo "if only I knew" > foo/baz &&
git update-index --add foo/baz &&
git commit -m "foo becomes a directory" &&
git branch "foo-becomes-a-directory" &&
echo "hello world" > foo/baz &&
git update-index foo/baz &&
git commit -m "foo/baz is the original foo" &&
git branch foo-baz-renamed-from-foo
'

test_expect_success 'file renamed from foo to foo/baz' '
git checkout -f initial &&
git diff-tree -M -p HEAD foo-baz-renamed-from-foo > patch &&
git apply --index < patch
'
test_debug 'cat patch'


test_expect_success 'file renamed from foo/baz to foo' '
git checkout -f foo-baz-renamed-from-foo &&
git diff-tree -M -p HEAD initial > patch &&
git apply --index < patch
'
test_debug 'cat patch'


test_expect_success 'directory becomes file' '
git checkout -f foo-becomes-a-directory &&
git diff-tree -p HEAD initial > patch &&
git apply --index < patch
'
test_debug 'cat patch'


test_expect_success 'file becomes directory' '
git checkout -f initial &&
git diff-tree -p HEAD foo-becomes-a-directory > patch &&
git apply --index < patch
'
test_debug 'cat patch'


test_expect_success 'file becomes symlink' '
git checkout -f initial &&
git diff-tree -p HEAD foo-symlinked-to-bar > patch &&
git apply --index < patch
'
test_debug 'cat patch'


test_expect_success 'symlink becomes file' '
git checkout -f foo-symlinked-to-bar &&
git diff-tree -p HEAD foo-back-to-file > patch &&
git apply --index < patch
'
test_debug 'cat patch'


test_expect_success 'symlink becomes directory' '
git checkout -f foo-symlinked-to-bar &&
git diff-tree -p HEAD foo-becomes-a-directory > patch &&
git apply --index < patch
'
test_debug 'cat patch'


test_expect_success 'directory becomes symlink' '
git checkout -f foo-becomes-a-directory &&
git diff-tree -p HEAD foo-symlinked-to-bar > patch &&
git apply --index < patch
'
test_debug 'cat patch'


test_done

19
t/t6004-rev-list-path-optim.sh

@ -0,0 +1,19 @@ @@ -0,0 +1,19 @@
#!/bin/sh

test_description='git-rev-list trivial path optimization test'

. ./test-lib.sh

test_expect_success setup '
echo Hello > a &&
git add a &&
git commit -m "Initial commit" a
'

test_expect_success path-optimization '
commit=$(echo "Unchanged tree" | git-commit-tree "HEAD^{tree}" -p HEAD) &&
test $(git-rev-list $commit | wc -l) = 2 &&
test $(git-rev-list $commit -- . | wc -l) = 1
'

test_done

40
t/t7001-mv.sh

@ -38,4 +38,44 @@ test_expect_success \ @@ -38,4 +38,44 @@ test_expect_success \
'git-diff-tree -r -M --name-status HEAD^ HEAD | \
grep -E "^R100.+path1/COPYING.+path0/COPYING"'

test_expect_success \
'adding another file' \
'cp ../../README path0/README &&
git-add path0/README &&
git-commit -m add2 -a'

test_expect_success \
'moving whole subdirectory' \
'git-mv path0 path2'

test_expect_success \
'commiting the change' \
'git-commit -m dir-move -a'

test_expect_success \
'checking the commit' \
'git-diff-tree -r -M --name-status HEAD^ HEAD | \
grep -E "^R100.+path0/COPYING.+path2/COPYING" &&
git-diff-tree -r -M --name-status HEAD^ HEAD | \
grep -E "^R100.+path0/README.+path2/README"'

test_expect_success \
'moving whole subdirectory into subdirectory' \
'git-mv path2 path1'

test_expect_success \
'commiting the change' \
'git-commit -m dir-move -a'

test_expect_success \
'checking the commit' \
'git-diff-tree -r -M --name-status HEAD^ HEAD | \
grep -E "^R100.+path2/COPYING.+path1/path2/COPYING" &&
git-diff-tree -r -M --name-status HEAD^ HEAD | \
grep -E "^R100.+path2/README.+path1/path2/README"'

test_expect_failure \
'do not move directory over existing directory' \
'mkdir path0 && mkdir path0/path2 && git-mv path2 path0'

test_done

5
unpack-objects.c

@ -241,11 +241,6 @@ static void unpack_one(unsigned nr, unsigned total) @@ -241,11 +241,6 @@ static void unpack_one(unsigned nr, unsigned total)
}
}

/*
* We unpack from the end, older files first. Now, usually
* there are deltas etc, so we'll not actually write the
* objects in that order, but we might as well try..
*/
static void unpack_all(void)
{
int i;

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save