GIT 1.0.0
authorJunio C Hamano <junkio@cox.net>
Wed, 21 Dec 2005 08:01:00 +0000 (00:01 -0800)
committerJunio C Hamano <junkio@cox.net>
Wed, 21 Dec 2005 08:01:00 +0000 (00:01 -0800)
Signed-off-by: Junio C Hamano <junkio@cox.net>
66 files changed:
.gitignore
Documentation/diff-options.txt
Documentation/everyday.txt
Documentation/git-archimport.txt
Documentation/git-check-ref-format.txt
Documentation/git-clone-pack.txt
Documentation/git-commit.txt
Documentation/git-fetch-pack.txt
Documentation/git-merge.txt
Documentation/git-octopus.txt [deleted file]
Documentation/git-pull.txt
Documentation/git-reset.txt
Documentation/git-update-server-info.txt
Documentation/git.txt
Documentation/hooks.txt
Documentation/howto/rebuild-from-update-hook.txt
Documentation/howto/using-topic-branches.txt
Documentation/tutorial.txt
Makefile
apply.c
cache.h
cat-file.c
clone-pack.c
cmd-rename.sh [deleted file]
copy.c
csum-file.c
debian/changelog
diff-delta.c
diff-tree.c
diff.c
diff.h
fetch-clone.c [new file with mode: 0644]
fetch-pack.c
git-am.sh
git-applypatch.sh
git-archimport.perl
git-branch.sh
git-checkout.sh
git-compat-util.h
git-diff.sh
git-format-patch.sh
git-log.sh
git-octopus.sh [deleted file]
git-svnimport.perl
git-whatchanged.sh
git.c
mktag.c
pkt-line.c
read-cache.c
refs.c
rev-list.c
send-pack.c
sha1_name.c
show-branch.c
t/t0010-racy-git.sh [new file with mode: 0755]
t/t1200-tutorial.sh [changed mode: 0644->0755]
t/t1300-repo-config.sh [changed mode: 0644->0755]
t/t3101-ls-tree-dirname.sh [changed mode: 0644->0755]
t/t4103-apply-binary.sh [changed mode: 0644->0755]
t/t4109-apply-multifrag.sh [changed mode: 0644->0755]
t/t4110-apply-scan.sh [changed mode: 0644->0755]
t/t5500-fetch-pack.sh [changed mode: 0644->0755]
t/t6101-rev-parse-parents.sh [changed mode: 0644->0755]
t/test-lib.sh
tar-tree.c
unpack-objects.c
index 8a6bd02d4ff1628af4c47d8c0c35d835607832d1..6bd508e4be252d5afeb24db9b4ca7f0541f895ce 100644 (file)
@@ -60,7 +60,6 @@ git-merge-stupid
 git-mktag
 git-name-rev
 git-mv
-git-octopus
 git-pack-redundant
 git-pack-objects
 git-parse-remote
index 6b496ede2550cf573a3a7ce37db908e6b3ab631e..9e574a04d3904228f835eca2ab698c66b92bf2a8 100644 (file)
        object name of pre- and post-image blob on the "index"
        line when generating a patch format output.     
 
+--abbrev[=<n>]::
+       Instead of showing the full 40-byte hexadecimal object
+       name in diff-raw format output and diff-tree header
+       lines, show only handful dhexigits prefix.  This is
+       independent of --full-index option above, which controls
+       the diff-patch output format.  Non default number of
+       digits can be specified with --abbrev=<n>.
+
 -B::
        Break complete rewrite changes into pairs of delete and create.
 
index d8d7a6441a8d1ebd146936569e7b1ccdbd4ac598..3ab9b916c290570518b568edef97a12ea2119408 100644 (file)
@@ -211,10 +211,12 @@ $ git fetch --tags <8>
 
 <1> repeat as needed.
 <2> extract patches from your branch for e-mail submission.
-<3> "pull" fetches from "origin" by default and merges.
-<4> look at the changes since last time we checked, only in the
+<3> "pull" fetches from "origin" by default and merges into the
+current branch.
+<4> immediately after pulling, look at the changes done upstream
+since last time we checked, only in the
 area we are interested in.
-<5> fetch from a specific branch from a specific repository and and merge.
+<5> fetch from a specific branch from a specific repository and merge.
 <6> revert the pull.
 <7> garbage collect leftover objects from reverted pull.
 <8> from time to time, obtain official tags from the "origin"
@@ -330,16 +332,18 @@ master, nor exposed as a part of a stable branch.
 <8> and bundle topic branches still cooking.
 <9> backport a critical fix.
 <10> create a signed tag.
-<11> make sure I did not accidentally rewound master beyond what I
+<11> make sure I did not accidentally rewind master beyond what I
 already pushed out.  "ko" shorthand points at the repository I have
 at kernel.org, and looks like this:
-$ cat .git/remotes/ko
-URL: kernel.org:/pub/scm/git/git.git
-Pull: master:refs/tags/ko-master
-Pull: maint:refs/tags/ko-maint
-Push: master
-Push: +pu
-Push: maint
+    $ cat .git/remotes/ko
+    URL: kernel.org:/pub/scm/git/git.git
+    Pull: master:refs/tags/ko-master
+    Pull: maint:refs/tags/ko-maint
+    Push: master
+    Push: +pu
+    Push: maint
+In the output from "git show-branch", "master" should have
+everything "ko-master" has.
 <12> push out the bleeding edge.
 <13> push the tag out, too.
 ------------
@@ -357,8 +361,8 @@ and maintain access to the repository by developers.
   * gitlink:git-shell[1] can be used as a 'restricted login shell'
     for shared central repository users.
 
-  * link:howto/update-hook-example.txt[update hook howto] has a
-    good example of managing a shared central repository.
+link:howto/update-hook-example.txt[update hook howto] has a good
+example of managing a shared central repository.
 
 
 Examples
@@ -424,3 +428,14 @@ for branch policy control.
 david is the release manager and is the only person who can
 create and push version tags.
 ------------
+
+HTTP server to support dumb protocol transfer.::
++
+------------
+dev$ git update-server-info <1>
+dev$ ftp user@isp.example.com <2>
+ftp> cp -r .git /home/user/myproject.git
+
+<1> make sure your info/refs and objects/info/packs are up-to-date
+<2> upload to public HTTP server hosted by your ISP.
+------------
index fcda0125af92ff9c3d72d711a78d23118787608c..a2bd788f379d7d7bec542d3c7538f02934bec844 100644 (file)
@@ -8,7 +8,8 @@ git-archimport - Import an Arch repository into git
 
 SYNOPSIS
 --------
-`git-archimport` [ -h ] [ -v ] [ -T ] [ -t tempdir ] 
+`git-archimport` [ -h ] [ -v ] [ -o ] [ -a ] [ -f ] [ -T ]
+                 [ -D depth ] [ -t tempdir ] 
                  <archive/branch> [ <archive/branch> ]
 
 DESCRIPTION
@@ -63,6 +64,26 @@ OPTIONS
        Many tags. Will create a tag for every commit, reflecting the commit 
        name in the Arch repository.
 
+-f::
+       Use the fast patchset import strategy.  This can be significantly
+       faster for large trees, but cannot handle directory renames or
+       permissions changes.  The default strategy is slow and safe.
+
+-o::
+       Use this for compatibility with old-style branch names used by
+       earlier versions of git-archimport.  Old-style branch names
+       were category--branch, whereas new-style branch names are
+       archive,category--branch--version.
+
+-D <depth>::
+       Follow merge ancestry and attempt to import trees that have been
+       merged from.  Specify a depth greater than 1 if patch logs have been
+       pruned.
+
+-a::
+       Attempt to auto-register archives at http://mirrors.sourcecontrol.net
+       This is particularly useful with the -D option.
+
 -t <tmpdir>::
        Override the default tempdir.
 
index 636e9516b09674d8d40516e1015931cacc54f210..f7f84c644ec6baddcdc5cc0b997c23409bb9a1d9 100644 (file)
@@ -26,13 +26,15 @@ imposes the following rules on how refs are named:
 
 . It cannot have ASCII control character (i.e. bytes whose
   values are lower than \040, or \177 `DEL`), space, tilde `~`,
-  caret `{caret}`, or colon `:` anywhere;
+  caret `{caret}`, colon `:`, question-mark `?`, asterisk `*`,
+  or open bracket `[` anywhere;
 
 . It cannot end with a slash `/`.
 
 These rules makes it easy for shell script based tools to parse
-refnames, and also avoids ambiguities in certain refname
-expressions (see gitlink:git-rev-parse[1]).  Namely:
+refnames, pathname expansion by the shell when a refname is used
+unquoted (by mistake), and also avoids ambiguities in certain
+refname expressions (see gitlink:git-rev-parse[1]).  Namely:
 
 . double-dot `..` are often used as in `ref1..ref2`, and in some
   context this notation means `{caret}ref1 ref2` (i.e. not in
index cfc7b62f31b6470b9d9011b49d73d135a0623dd9..39906fc450150ee0e9213a31c8a7c3e50d01b5b3 100644 (file)
@@ -43,7 +43,11 @@ OPTIONS
        The heads to update.  This is relative to $GIT_DIR
        (e.g. "HEAD", "refs/heads/master").  When unspecified,
        all heads are updated to match the remote repository.
-
++
+Usually all the refs from existing repository are stored
+under the same name in the new repository.  Giving explicit
+<head> arguments instead writes the object names and refs to
+the standard output, just like get-fetch-pack does.
 
 Author
 ------
index b92cf483152d7d393b20537d5407479aa13fefc1..8b91f221fe0ea4dacd1f373fbd90d023ddc766b3 100644 (file)
@@ -66,6 +66,10 @@ OPTIONS
        Update specified paths in the index file before committing.
 
 
+If you make a commit and then found a mistake immediately after
+that, you can recover from it with gitlink:git-reset[1].
+
+
 Author
 ------
 Written by Linus Torvalds <torvalds@osdl.org> and
index ea6faab059810e8eef858d58c041b7d98a7de841..b507e9b64863d2b9b4abc43ddb635b83ae67dcea 100644 (file)
@@ -8,7 +8,7 @@ git-fetch-pack - Receive missing objects from another repository.
 
 SYNOPSIS
 --------
-git-fetch-pack [-q] [--exec=<git-upload-pack>] [<host>:]<directory> [<refs>...]
+git-fetch-pack [-q] [-k] [--exec=<git-upload-pack>] [<host>:]<directory> [<refs>...]
 
 DESCRIPTION
 -----------
@@ -29,6 +29,11 @@ OPTIONS
        Pass '-q' flag to 'git-unpack-objects'; this makes the
        cloning process less verbose.
 
+-k::
+       Do not invoke 'git-unpack-objects' on received data, but
+       create a single packfile out of it instead, and store it
+       in the object database.
+
 --exec=<git-upload-pack>::
        Use this to specify the path to 'git-upload-pack' on the
        remote side, if is not found on your $PATH.
index 0cac563d40f17361569923aebb51e454fd24f92e..4ce799b520b501b1ea6dddd5643bf3aec2aca344 100644 (file)
@@ -37,6 +37,11 @@ include::merge-options.txt[]
 include::merge-strategies.txt[]
 
 
+If you tried a merge which resulted in a complex conflicts and
+would want to start over, you can recover with
+gitlink:git-reset[1].
+
+
 HOW MERGE WORKS
 ---------------
 
diff --git a/Documentation/git-octopus.txt b/Documentation/git-octopus.txt
deleted file mode 100644 (file)
index 6e32ea3..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-git-octopus(1)
-==============
-
-NAME
-----
-git-octopus - Merge more than two commits.
-
-
-SYNOPSIS
---------
-'git-octopus'
-
-DESCRIPTION
------------
-After running 'git fetch', $GIT_DIR/FETCH_HEAD contains the
-following information, one line per remote ref:
-
-------------------------------------------------
-<object name>  <ref name> from <repository>
-------------------------------------------------
-
-Using this information, create and commit an Octopus merge on
-top of the current HEAD.
-
-
-Author
-------
-Written by Junio C Hamano <junkio@cox.net>
-
-
-Documentation
---------------
-Documentation by Junio C Hamano and the git-list <git@vger.kernel.org>.
-
-GIT
----
-Part of the gitlink:git[7] suite
-
index c65ca9a5300096d69d540657ffd963070f429874..3a7d385225754d5c865ac333a5a65e71c4e7fb65 100644 (file)
@@ -104,6 +104,11 @@ merge the remote `origin` head into the current,
 local `master` branch.
 
 
+If you tried a pull which resulted in a complex conflicts and
+would want to start over, you can recover with
+gitlink:git-reset[1].
+
+
 SEE ALSO
 --------
 gitlink:git-fetch[1], gitlink:git-merge[1]
index 02048918bf70fd3391e635badfbc771856e3bcc3..c6a269b7ef56d830ad493467a63637b2afee9e83 100644 (file)
@@ -111,6 +111,39 @@ remain there.
 changes still in the working tree.
 ------------
 
+Undo a merge or pull::
++
+------------
+$ git pull <1>
+Trying really trivial in-index merge...
+fatal: Merge requires file-level merging
+Nope.
+...
+Auto-merging nitfol
+CONFLICT (content): Merge conflict in nitfol
+Automatic merge failed/prevented; fix up by hand
+$ git reset --hard <2>
+
+<1> try to update from the upstream resulted in a lot of
+conflicts; you were not ready to spend a lot of time merging
+right now, so you decide to do that later.
+<2> "pull" has not made merge commit, so "git reset --hard"
+which is a synonym for "git reset --hard HEAD" clears the mess
+from the index file and the working tree.
+
+$ git pull . topic/branch <3>
+Updating from 41223... to 13134...
+Fast forward
+$ git reset --hard ORIG_HEAD <4>
+
+<3> merge a topic branch into the current branch, which resulted
+in a fast forward.
+<4> but you decided that the topic branch is not ready for public
+consumption yet.  "pull" or "merge" always leaves the original
+tip of the current branch in ORIG_HEAD, so resetting hard to it
+brings your index file and the working tree back to that state,
+and resets the tip of the branch to that commit.
+------------
 
 Author
 ------
index 527fb303ebc57a089c5265b66f9f800d3cf48b81..88a03c7c5ed4935fc10764d0f56326f0436a6f26 100644 (file)
@@ -12,11 +12,11 @@ SYNOPSIS
 
 DESCRIPTION
 -----------
-A dumb server that does not do on-the-fly pack generations can
+A dumb server that does not do on-the-fly pack generations must
 have some auxiliary information files in $GIT_DIR/info and
 $GIT_OBJECT_DIRECTORY/info directories to help clients discover
-what references and packs the server has and make optimized
-pull decisions.  This command generates such auxiliary files.
+what references and packs the server has.  This command
+generates such auxiliary files.
 
 
 OPTIONS
index 482eba7eba29b2bad53380a1eba4c4aa16083fab..5f068c2a1ab225755a443f6a34e3c4797481cd16 100644 (file)
@@ -297,9 +297,6 @@ gitlink:git-merge[1]::
 gitlink:git-mv[1]::
        Move or rename a file, a directory, or a symlink.
 
-gitlink:git-octopus[1]::
-       Merge more than two commits.
-
 gitlink:git-pull[1]::
        Fetch from and merge with a remote repository.
 
index 7ee3571bc09642f07ec50d5b3cfc9d802119889e..4ad1920ec10cf4b7733ebeae1424f003cc3fe9eb 100644 (file)
@@ -111,6 +111,10 @@ Another use suggested on the mailing list is to use this hook to
 implement access control which is finer grained than the one
 based on filesystem group.
 
+The standard output of this hook is sent to /dev/null; if you
+want to report something to the git-send-pack on the other end,
+you can redirect your output to your stderr.
+
 post-update
 -----------
 
@@ -125,3 +129,7 @@ the outcome of `git-receive-pack`.
 The default post-update hook, when enabled, runs
 `git-update-server-info` to keep the information used by dumb
 transport up-to-date.
+
+The standard output of this hook is sent to /dev/null; if you
+want to report something to the git-send-pack on the other end,
+you can redirect your output to your stderr.
index ebd025db85d6424760528b64dfdbd7a520411fe4..02621b54a03ce5771eab1c49d121a07ba31cbf16 100644 (file)
@@ -10,7 +10,7 @@ The pages under http://www.kernel.org/pub/software/scm/git/docs/
 are built from Documentation/ directory of the git.git project
 and needed to be kept up-to-date.  The www.kernel.org/ servers
 are mirrored and I was told that the origin of the mirror is on
-the machine master.kernel.org, on which I was given an account
+the machine $some.kernel.org, on which I was given an account
 when I took over git maintainership from Linus.
 
 The directories relevant to this how-to are these two:
@@ -63,7 +63,7 @@ like this:
     EOF
     $ chmod +x /pub/scm/git/git.git/hooks/post-update
 
-There are three things worth mentioning:
+There are four things worth mentioning:
 
  - The update-hook is run after the repository accepts a "git
    push", under my user privilege.  It is given the full names
@@ -77,6 +77,10 @@ There are three things worth mentioning:
    pull" it does into $HOME/doc-git/docgen/ repository would not
    work correctly.
 
+ - The stdout of update hook script is not connected to git
+   push; I run the heavy part of the command inside "at", to
+   receive the execution report via e-mail.
+
  - This is still crude and does not protect against simultaneous
    make invocations stomping on each other.  I would need to add
    some locking mechanism for this.
index 494429738f8f86bbe21f38b5f90cc94344ad0630..b3d592fc3e1796643f8771bbd549ced5532d7a96 100644 (file)
@@ -42,8 +42,7 @@ So here is the step-by-step guide how this all works for me.
 
 First create your work tree by cloning Linus's public tree:
 
- $ git clone \
- master.kernel.org:/pub/scm/linux/kernel/git/torvalds/linux-2.6.git work
+ $ git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git work
 
 Change directory into the cloned tree you just created
 
@@ -53,7 +52,7 @@ Set up a remotes file so that you can fetch the latest from Linus' master
 branch into a local branch named "linus":
 
  $ cat > .git/remotes/linus
- URL: master.kernel.org:/pub/scm/linux/kernel/git/torvalds/linux-2.6.git
+ URL: git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git
  Pull: master:linus
  ^D
 
index a61b824443bdb565f22c45366f1c62622564cd3a..3a5c56e24edfe7a970e6dcd346f8c0a346cdbfd8 100644 (file)
@@ -27,6 +27,12 @@ SCM, you can skip them during your first pass.
 [NOTE]
 And those "too deep" descriptions are often marked as Note.
 
+[NOTE]
+If you are already familiar with another version control system,
+like CVS, you may want to take a look at
+link:everyday.html[Everyday GIT in 20 commands or so] first
+before reading this.
+
 
 Creating a git repository
 -------------------------
@@ -1085,9 +1091,10 @@ lacks and transfers (close to) minimum set of objects.
 HTTP(S)::
        `http://remote.machine/path/to/repo.git/`
 +
-HTTP and HTTPS transport are used only for downloading.  They
-first obtain the topmost commit object name from the remote site
-by looking at `repo.git/info/refs` file, tries to obtain the
+Downloader from http and https URL
+first obtains the topmost commit object name from the remote site
+by looking at the specified refname under `repo.git/refs/` directory,
+and then tries to obtain the
 commit object by downloading from `repo.git/objects/xx/xxx\...`
 using the object name of that commit object.  Then it reads the
 commit object to find out its parent commits and the associate
@@ -1098,7 +1105,9 @@ sometimes also called 'commit walkers'.
 The 'commit walkers' are sometimes also called 'dumb
 transports', because they do not require any git aware smart
 server like git Native transport does.  Any stock HTTP server
-would suffice.
+that does not even support directory index would suffice.  But
+you must prepare your repository with `git-update-server-info`
+to help dumb transport downloaders.
 +
 There are (confusingly enough) `git-ssh-fetch` and `git-ssh-upload`
 programs, which are 'commit walkers'; they outlived their
@@ -1511,12 +1520,13 @@ A recommended workflow for a "project lead" goes like this:
 2. Prepare a public repository accessible to others.
 +
 If other people are pulling from your repository over dumb
-transport protocols, you need to keep this repository 'dumb
-transport friendly'.  After `git init-db`,
+transport protocols (HTTP), you need to keep this repository
+'dumb transport friendly'.  After `git init-db`,
 `$GIT_DIR/hooks/post-update` copied from the standard templates
 would contain a call to `git-update-server-info` but the
 `post-update` hook itself is disabled by default -- enable it
-with `chmod +x post-update`.
+with `chmod +x post-update`.  This makes sure `git-update-server-info`
+keeps the necessary files up-to-date.
 
 3. Push into the public repository from your primary
    repository.
@@ -1615,7 +1625,9 @@ cooperation you are probably more familiar with as well.
 For this, set up a public repository on a machine that is
 reachable via SSH by people with "commit privileges".  Put the
 committers in the same user group and make the repository
-writable by that group.
+writable by that group.  Make sure their umasks are set up to
+allow group members to write into directories other members
+have created.
 
 You, as an individual committer, then:
 
index 92cfee4333313cc52f500e2a02c9cf8b90ad6371..e9bf860f6db62e68784c4eac0a867b92b93e8bdf 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -55,7 +55,7 @@ all:
 # 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.
 
-GIT_VERSION = 0.99.9n
+GIT_VERSION = 1.0.0
 
 # CFLAGS and LDFLAGS are for the users to override from the command line.
 
@@ -89,7 +89,7 @@ SCRIPT_SH = \
        git-cherry.sh git-clone.sh git-commit.sh \
        git-count-objects.sh git-diff.sh git-fetch.sh \
        git-format-patch.sh git-log.sh git-ls-remote.sh \
-       git-merge-one-file.sh git-octopus.sh git-parse-remote.sh \
+       git-merge-one-file.sh git-parse-remote.sh \
        git-prune.sh git-pull.sh git-push.sh git-rebase.sh \
        git-repack.sh git-request-pull.sh git-reset.sh \
        git-resolve.sh git-revert.sh git-sh-setup.sh git-status.sh \
@@ -175,6 +175,7 @@ LIB_OBJS = \
        quote.o read-cache.o refs.o run-command.o \
        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 \
        $(DIFF_OBJS)
 
 LIBS = $(LIB_FILE)
@@ -497,7 +498,7 @@ clean:
        rm -f *.o mozilla-sha1/*.o arm/*.o ppc/*.o compat/*.o $(LIB_FILE)
        rm -f $(PROGRAMS) $(SIMPLE_PROGRAMS) git$X
        rm -f $(filter-out gitk,$(SCRIPTS))
-       rm -f *.spec *.pyc *.pyo
+       rm -f *.spec *.pyc *.pyo */*.pyc */*.pyo
        rm -rf $(GIT_TARNAME)
        rm -f $(GIT_TARNAME).tar.gz git-core_$(GIT_VERSION)-*.tar.gz
        rm -f git-core_$(GIT_VERSION)-*.dsc
@@ -505,3 +506,4 @@ clean:
        $(MAKE) -C Documentation/ clean
        $(MAKE) -C templates clean
        $(MAKE) -C t/ clean
+
diff --git a/apply.c b/apply.c
index 1742ab28e95936eed52e910930a8a04869c5418b..d5e7bfdb4de1fe7990ae11e190537fd1c490d54c 100644 (file)
--- a/apply.c
+++ b/apply.c
@@ -84,14 +84,11 @@ static void *read_patch_file(int fd, unsigned long *sizep)
                        buffer = xrealloc(buffer, alloc);
                        nr = alloc - size;
                }
-               nr = read(fd, buffer + size, nr);
+               nr = xread(fd, buffer + size, nr);
                if (!nr)
                        break;
-               if (nr < 0) {
-                       if (errno == EAGAIN)
-                               continue;
+               if (nr < 0)
                        die("git-apply: read returned %s", strerror(errno));
-               }
                size += nr;
        }
        *sizep = size;
@@ -1006,13 +1003,8 @@ static int read_old_data(struct stat *st, const char *path, void *buf, unsigned
                        return error("unable to open %s", path);
                got = 0;
                for (;;) {
-                       int ret = read(fd, buf + got, size - got);
-                       if (ret < 0) {
-                               if (errno == EAGAIN)
-                                       continue;
-                               break;
-                       }
-                       if (!ret)
+                       int ret = xread(fd, buf + got, size - got);
+                       if (ret <= 0)
                                break;
                        got += ret;
                }
@@ -1600,12 +1592,9 @@ static int try_create_file(const char *path, unsigned int mode, const char *buf,
        if (fd < 0)
                return -1;
        while (size) {
-               int written = write(fd, buf, size);
-               if (written < 0) {
-                       if (errno == EINTR || errno == EAGAIN)
-                               continue;
+               int written = xwrite(fd, buf, size);
+               if (written < 0)
                        die("writing file %s: %s", path, strerror(errno));
-               }
                if (!written)
                        die("out of space writing file %s", path);
                buf += written;
diff --git a/cache.h b/cache.h
index c78d8aea415d476800b4eab1fb12b67e3f1e253c..cb87becb3aaea75915a65e99565c418d6765174b 100644 (file)
--- a/cache.h
+++ b/cache.h
@@ -338,4 +338,9 @@ extern char git_default_name[MAX_GITNAME];
 extern char git_commit_encoding[MAX_ENCODING_LENGTH];
 
 extern int copy_fd(int ifd, int ofd);
+
+/* Finish off pack transfer receiving end */
+extern int receive_unpack_pack(int fd[2], const char *me, int quiet);
+extern int receive_keep_pack(int fd[2], const char *me);
+
 #endif /* CACHE_H */
index 7594108c6e5f7d8830c7b5ca6f45951b8b4bcc23..96d66b43043ee1e2381bfb80bb2bc1c7063ecc38 100644 (file)
@@ -55,10 +55,8 @@ int main(int argc, char **argv)
                die("git-cat-file %s: bad file", argv[2]);
 
        while (size > 0) {
-               long ret = write(1, buf, size);
+               long ret = xwrite(1, buf, size);
                if (ret < 0) {
-                       if (errno == EAGAIN)
-                               continue;
                        /* Ignore epipe */
                        if (errno == EPIPE)
                                break;
index a99a95c5f26718bd509a1c8906663fd73447f16d..f634431be1f6ba3fa518d987a227c33f19543fb6 100644 (file)
@@ -1,7 +1,6 @@
 #include "cache.h"
 #include "refs.h"
 #include "pkt-line.h"
-#include <sys/wait.h>
 
 static const char clone_pack_usage[] =
 "git-clone-pack [--exec=<git-upload-pack>] [<host>:]<directory> [<heads>]*";
@@ -112,139 +111,6 @@ static void write_refs(struct ref *ref)
        free(head_path);
 }
 
-static int finish_pack(const char *pack_tmp_name)
-{
-       int pipe_fd[2];
-       pid_t pid;
-       char idx[PATH_MAX];
-       char final[PATH_MAX];
-       char hash[41];
-       unsigned char sha1[20];
-       char *cp;
-       int err = 0;
-
-       if (pipe(pipe_fd) < 0)
-               die("git-clone-pack: unable to set up pipe");
-
-       strcpy(idx, pack_tmp_name); /* ".git/objects/pack-XXXXXX" */
-       cp = strrchr(idx, '/');
-       memcpy(cp, "/pidx", 5);
-
-       pid = fork();
-       if (pid < 0)
-               die("git-clone-pack: unable to fork off git-index-pack");
-       if (!pid) {
-               close(0);
-               dup2(pipe_fd[1], 1);
-               close(pipe_fd[0]);
-               close(pipe_fd[1]);
-               execlp("git-index-pack","git-index-pack",
-                      "-o", idx, pack_tmp_name, NULL);
-               error("cannot exec git-index-pack <%s> <%s>",
-                     idx, pack_tmp_name);
-               exit(1);
-       }
-       close(pipe_fd[1]);
-       if (read(pipe_fd[0], hash, 40) != 40) {
-               error("git-clone-pack: unable to read from git-index-pack");
-               err = 1;
-       }
-       close(pipe_fd[0]);
-
-       for (;;) {
-               int status, code;
-               int retval = waitpid(pid, &status, 0);
-
-               if (retval < 0) {
-                       if (errno == EINTR)
-                               continue;
-                       error("waitpid failed (%s)", strerror(retval));
-                       goto error_die;
-               }
-               if (WIFSIGNALED(status)) {
-                       int sig = WTERMSIG(status);
-                       error("git-index-pack died of signal %d", sig);
-                       goto error_die;
-               }
-               if (!WIFEXITED(status)) {
-                       error("git-index-pack died of unnatural causes %d",
-                             status);
-                       goto error_die;
-               }
-               code = WEXITSTATUS(status);
-               if (code) {
-                       error("git-index-pack died with error code %d", code);
-                       goto error_die;
-               }
-               if (err)
-                       goto error_die;
-               break;
-       }
-       hash[40] = 0;
-       if (get_sha1_hex(hash, sha1)) {
-               error("git-index-pack reported nonsense '%s'", hash);
-               goto error_die;
-       }
-       /* Now we have pack in pack_tmp_name[], and
-        * idx in idx[]; rename them to their final names.
-        */
-       snprintf(final, sizeof(final),
-                "%s/pack/pack-%s.pack", get_object_directory(), hash);
-       move_temp_to_file(pack_tmp_name, final);
-       chmod(final, 0444);
-       snprintf(final, sizeof(final),
-                "%s/pack/pack-%s.idx", get_object_directory(), hash);
-       move_temp_to_file(idx, final);
-       chmod(final, 0444);
-       return 0;
-
- error_die:
-       unlink(idx);
-       unlink(pack_tmp_name);
-       exit(1);
-}
-
-static int clone_without_unpack(int fd[2])
-{
-       char tmpfile[PATH_MAX];
-       int ofd, ifd;
-
-       ifd = fd[0];
-       snprintf(tmpfile, sizeof(tmpfile),
-                "%s/pack/tmp-XXXXXX", get_object_directory());
-       ofd = mkstemp(tmpfile);
-       if (ofd < 0)
-               return error("unable to create temporary file %s", tmpfile);
-
-       while (1) {
-               char buf[8192];
-               ssize_t sz, wsz, pos;
-               sz = read(ifd, buf, sizeof(buf));
-               if (sz == 0)
-                       break;
-               if (sz < 0) {
-                       error("error reading pack (%s)", strerror(errno));
-                       close(ofd);
-                       unlink(tmpfile);
-                       return -1;
-               }
-               pos = 0;
-               while (pos < sz) {
-                       wsz = write(ofd, buf + pos, sz - pos);
-                       if (wsz < 0) {
-                               error("error writing pack (%s)",
-                                     strerror(errno));
-                               close(ofd);
-                               unlink(tmpfile);
-                               return -1;
-                       }
-                       pos += wsz;
-               }
-       }
-       close(ofd);
-       return finish_pack(tmpfile);
-}
-
 static int clone_pack(int fd[2], int nr_match, char **match)
 {
        struct ref *refs;
@@ -257,10 +123,19 @@ static int clone_pack(int fd[2], int nr_match, char **match)
        }
        clone_handshake(fd, refs);
 
-       status = clone_without_unpack(fd);
-
-       if (!status)
-               write_refs(refs);
+       status = receive_keep_pack(fd, "git-clone-pack");
+
+       if (!status) {
+               if (nr_match == 0)
+                       write_refs(refs);
+               else
+                       while (refs) {
+                               printf("%s %s\n",
+                                      sha1_to_hex(refs->old_sha1),
+                                      refs->name);
+                               refs = refs->next;
+                       }
+       }
        return status;
 }
 
@@ -285,8 +160,6 @@ int main(int argc, char **argv)
                                exec = arg + 7;
                                continue;
                        }
-                       if (!strcmp("--keep", arg))
-                               continue;
                        usage(clone_pack_usage);
                }
                dest = arg;
diff --git a/cmd-rename.sh b/cmd-rename.sh
deleted file mode 100755 (executable)
index 992493d..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-#!/bin/sh
-#
-# If you installed git by hand previously, you may find this
-# script useful to remove the symbolic links that we shipped
-# for backward compatibility.
-#
-# Running this script with the previous installation directory
-# like this:
-#
-# $ cmd-rename.sh /usr/local/bin/
-#
-# would clean them.
-
-d="$1"
-test -d "$d" || exit
-while read old new
-do
-       rm -f "$d/$old"
-done <<\EOF
-git-add-script git-add
-git-archimport-script  git-archimport
-git-bisect-script      git-bisect
-git-branch-script      git-branch
-git-checkout-script    git-checkout
-git-cherry-pick-script git-cherry-pick
-git-clone-script       git-clone
-git-commit-script      git-commit
-git-count-objects-script       git-count-objects
-git-cvsimport-script   git-cvsimport
-git-diff-script        git-diff
-git-send-email-script  git-send-email
-git-fetch-script       git-fetch
-git-format-patch-script        git-format-patch
-git-log-script git-log
-git-ls-remote-script   git-ls-remote
-git-merge-one-file-script      git-merge-one-file
-git-octopus-script     git-octopus
-git-parse-remote-script        git-parse-remote
-git-prune-script       git-prune
-git-pull-script        git-pull
-git-push-script        git-push
-git-rebase-script      git-rebase
-git-relink-script      git-relink
-git-rename-script      git-rename
-git-repack-script      git-repack
-git-request-pull-script        git-request-pull
-git-reset-script       git-reset
-git-resolve-script     git-resolve
-git-revert-script      git-revert
-git-sh-setup-script    git-sh-setup
-git-status-script      git-status
-git-tag-script git-tag
-git-verify-tag-script  git-verify-tag
-git-http-pull  git-http-fetch
-git-local-pull git-local-fetch
-git-checkout-cache     git-checkout-index
-git-diff-cache git-diff-index
-git-merge-cache        git-merge-index
-git-update-cache       git-update-index
-git-convert-cache      git-convert-objects
-git-fsck-cache git-fsck-objects
-EOF
diff --git a/copy.c b/copy.c
index e1cd5d06503d93f6b400a3911e6b61ff327190ca..7100eedbc3277b9b0997311459d054ba06950b61 100644 (file)
--- a/copy.c
+++ b/copy.c
@@ -6,32 +6,27 @@ int copy_fd(int ifd, int ofd)
                int len;
                char buffer[8192];
                char *buf = buffer;
-               len = read(ifd, buffer, sizeof(buffer));
+               len = xread(ifd, buffer, sizeof(buffer));
                if (!len)
                        break;
                if (len < 0) {
                        int read_error;
-                       if (errno == EAGAIN)
-                               continue;
                        read_error = errno;
                        close(ifd);
                        return error("copy-fd: read returned %s",
                                     strerror(read_error));
                }
-               while (1) {
-                       int written = write(ofd, buf, len);
+               while (len) {
+                       int written = xwrite(ofd, buf, len);
                        if (written > 0) {
                                buf += written;
                                len -= written;
-                               if (!len)
-                                       break;
                        }
-                       if (!written)
+                       else if (!written)
                                return error("copy-fd: write returned 0");
-                       if (errno == EAGAIN || errno == EINTR)
-                               continue;
-                       return error("copy-fd: write returned %s",
-                                    strerror(errno));
+                       else
+                               return error("copy-fd: write returned %s",
+                                            strerror(errno));
                }
        }
        close(ifd);
index c66b9eb10bfad8fee8b7b779cbb4a8e7c86480af..5f9249aeedfa7d4156cf412da6a7e7d77f33ff86 100644 (file)
@@ -15,7 +15,7 @@ static int sha1flush(struct sha1file *f, unsigned int count)
        void *buf = f->buffer;
 
        for (;;) {
-               int ret = write(f->fd, buf, count);
+               int ret = xwrite(f->fd, buf, count);
                if (ret > 0) {
                        buf += ret;
                        count -= ret;
@@ -25,8 +25,6 @@ static int sha1flush(struct sha1file *f, unsigned int count)
                }
                if (!ret)
                        die("sha1 file '%s' write error. Out of diskspace", f->name);
-               if (errno == EAGAIN || errno == EINTR)
-                       continue;
                die("sha1 file '%s' write error (%s)", f->name, strerror(errno));
        }
 }
index d36904cd6b30c2c4097a538ffe154f8984cfd871..4fa6c16e8e106b291c466d894f17db0218ef91c9 100644 (file)
@@ -1,3 +1,9 @@
+git-core (1.0.0-0) unstable; urgency=low
+
+  * GIT 1.0.0
+
+ -- Junio C Hamano <junkio@cox.net>  Wed, 21 Dec 2005 00:01:00 -0800
+
 git-core (0.99.9n-0) unstable; urgency=low
 
   * GIT 0.99.9n aka 1.0rc6
index b2ae7b5e6c3b4aa409ccfa60f67d5c8eb1690504..890986eeb022816da078794555a9a0135783bd40 100644 (file)
@@ -84,20 +84,15 @@ typedef struct s_chanode {
 } chanode_t;
 
 typedef struct s_chastore {
-       chanode_t *head, *tail;
        int isize, nsize;
        chanode_t *ancur;
-       chanode_t *sncur;
-       int scurr;
 } chastore_t;
 
 static void cha_init(chastore_t *cha, int isize, int icount)
 {
-       cha->head = cha->tail = NULL;
        cha->isize = isize;
        cha->nsize = icount * isize;
-       cha->ancur = cha->sncur = NULL;
-       cha->scurr = 0;
+       cha->ancur = NULL;
 }
 
 static void *cha_alloc(chastore_t *cha)
@@ -111,12 +106,7 @@ static void *cha_alloc(chastore_t *cha)
                if (!ancur)
                        return NULL;
                ancur->icurr = 0;
-               ancur->next = NULL;
-               if (cha->tail)
-                       cha->tail->next = ancur;
-               if (!cha->head)
-                       cha->head = ancur;
-               cha->tail = ancur;
+               ancur->next = cha->ancur;
                cha->ancur = ancur;
        }
 
@@ -127,7 +117,7 @@ static void *cha_alloc(chastore_t *cha)
 
 static void cha_free(chastore_t *cha)
 {
-       chanode_t *cur = cha->head;
+       chanode_t *cur = cha->ancur;
        while (cur) {
                chanode_t *tmp = cur;
                cur = cur->next;
@@ -142,7 +132,6 @@ typedef struct s_bdrecord {
 } bdrecord_t;
 
 typedef struct s_bdfile {
-       const unsigned char *data, *top;
        chastore_t cha;
        unsigned int fphbits;
        bdrecord_t **fphash;
@@ -152,7 +141,7 @@ static int delta_prepare(const unsigned char *buf, int bufsize, bdfile_t *bdf)
 {
        unsigned int fphbits;
        int i, hsize;
-       const unsigned char *base, *data, *top;
+       const unsigned char *data, *top;
        bdrecord_t *brec;
        bdrecord_t **fphash;
 
@@ -165,13 +154,12 @@ static int delta_prepare(const unsigned char *buf, int bufsize, bdfile_t *bdf)
                fphash[i] = NULL;
        cha_init(&bdf->cha, sizeof(bdrecord_t), hsize / 4 + 1);
 
-       bdf->data = data = base = buf;
-       bdf->top = top = buf + bufsize;
-       data += (bufsize / BLK_SIZE) * BLK_SIZE;
+       top = buf + bufsize;
+       data = buf + (bufsize / BLK_SIZE) * BLK_SIZE;
        if (data == top)
                data -= BLK_SIZE;
 
-       for ( ; data >= base; data -= BLK_SIZE) {
+       for ( ; data >= buf; data -= BLK_SIZE) {
                brec = cha_alloc(&bdf->cha);
                if (!brec) {
                        cha_free(&bdf->cha);
@@ -208,7 +196,7 @@ void *diff_delta(void *from_buf, unsigned long from_size,
 {
        int i, outpos, outsize, inscnt, csize, msize, moff;
        unsigned int fp;
-       const unsigned char *data, *top, *ptr1, *ptr2;
+       const unsigned char *ref_data, *ref_top, *data, *top, *ptr1, *ptr2;
        unsigned char *out, *orig;
        bdrecord_t *brec;
        bdfile_t bdf;
@@ -224,6 +212,8 @@ void *diff_delta(void *from_buf, unsigned long from_size,
                return NULL;
        }
 
+       ref_data = from_buf;
+       ref_top = from_buf + from_size;
        data = to_buf;
        top = to_buf + to_size;
 
@@ -253,7 +243,7 @@ void *diff_delta(void *from_buf, unsigned long from_size,
                i = HASH(fp, bdf.fphbits);
                for (brec = bdf.fphash[i]; brec; brec = brec->next) {
                        if (brec->fp == fp) {
-                               csize = bdf.top - brec->ptr;
+                               csize = ref_top - brec->ptr;
                                if (csize > top - data)
                                        csize = top - data;
                                for (ptr1 = brec->ptr, ptr2 = data; 
@@ -262,7 +252,7 @@ void *diff_delta(void *from_buf, unsigned long from_size,
 
                                csize = ptr1 - brec->ptr;
                                if (csize > msize) {
-                                       moff = brec->ptr - bdf.data;
+                                       moff = brec->ptr - ref_data;
                                        msize = csize;
                                        if (msize >= 0x10000) {
                                                msize = 0x10000;
index d56d921585d5cd48b88bfbb36bcde016e10f8fd5..efa2b9476eae679b7f98a4605b07b6637e49de5a 100644 (file)
@@ -14,11 +14,6 @@ static enum cmit_fmt commit_format = CMIT_FMT_RAW;
 
 static struct diff_options diff_options;
 
-static void call_diff_setup_done(void)
-{
-       diff_setup_done(&diff_options);
-}
-
 static int call_diff_flush(void)
 {
        diffcore_std(&diff_options);
@@ -43,7 +38,6 @@ static int diff_tree_sha1_top(const unsigned char *old,
 {
        int ret;
 
-       call_diff_setup_done();
        ret = diff_tree_sha1(old, new, base, &diff_options);
        call_diff_flush();
        return ret;
@@ -55,7 +49,6 @@ static int diff_root_tree(const unsigned char *new, const char *base)
        void *tree;
        struct tree_desc empty, real;
 
-       call_diff_setup_done();
        tree = read_object_with_reference(new, "tree", &real.size, NULL);
        if (!tree)
                die("unable to read root tree (%s)", sha1_to_hex(new));
@@ -69,18 +62,29 @@ static int diff_root_tree(const unsigned char *new, const char *base)
        return retval;
 }
 
-static const char *generate_header(const char *commit, const char *parent, const char *msg)
+static const char *generate_header(const unsigned char *commit_sha1,
+                                  const unsigned char *parent_sha1,
+                                  const char *msg)
 {
        static char this_header[16384];
        int offset;
        unsigned long len;
+       int abbrev = diff_options.abbrev;
 
        if (!verbose_header)
-               return commit;
+               return sha1_to_hex(commit_sha1);
 
        len = strlen(msg);
-       offset = sprintf(this_header, "%s%s (from %s)\n", header_prefix, commit, parent);
-       offset += pretty_print_commit(commit_format, msg, len, this_header + offset, sizeof(this_header) - offset);
+
+       offset = sprintf(this_header, "%s%s ",
+                        header_prefix,
+                        diff_unique_abbrev(commit_sha1, abbrev));
+       offset += sprintf(this_header + offset, "(from %s)\n",
+                        parent_sha1 ?
+                        diff_unique_abbrev(parent_sha1, abbrev) : "root");
+       offset += pretty_print_commit(commit_format, msg, len,
+                                     this_header + offset,
+                                     sizeof(this_header) - offset);
        return this_header;
 }
 
@@ -99,18 +103,18 @@ static int diff_tree_commit(const unsigned char *commit_sha1)
        
        /* Root commit? */
        if (show_root_diff && !commit->parents) {
-               header = generate_header(name, "root", commit->buffer);
+               header = generate_header(sha1, NULL, commit->buffer);
                diff_root_tree(commit_sha1, "");
        }
 
        /* More than one parent? */
        if (ignore_merges && commit->parents && commit->parents->next)
-                       return 0;
+               return 0;
 
        for (parents = commit->parents; parents; parents = parents->next) {
                struct commit *parent = parents->item;
-               header = generate_header(name,
-                                        sha1_to_hex(parent->object.sha1),
+               header = generate_header(sha1,
+                                        parent->object.sha1,
                                         commit->buffer);
                diff_tree_sha1_top(parent->object.sha1, commit_sha1, "");
                if (!header && verbose_header) {
@@ -129,6 +133,7 @@ static int diff_tree_stdin(char *line)
        int len = strlen(line);
        unsigned char commit[20], parent[20];
        static char this_header[1000];
+       int abbrev = diff_options.abbrev;
 
        if (!len || line[len-1] != '\n')
                return -1;
@@ -138,7 +143,9 @@ static int diff_tree_stdin(char *line)
        if (isspace(line[40]) && !get_sha1_hex(line+41, parent)) {
                line[40] = 0;
                line[81] = 0;
-               sprintf(this_header, "%s (from %s)\n", line, line+41);
+               sprintf(this_header, "%s (from %s)\n",
+                       diff_unique_abbrev(commit, abbrev),
+                       diff_unique_abbrev(parent, abbrev));
                header = this_header;
                return diff_tree_sha1_top(parent, commit, "");
        }
@@ -239,6 +246,7 @@ int main(int argc, const char **argv)
                diff_options.recursive = 1;
 
        diff_tree_setup_paths(get_pathspec(prefix, argv));
+       diff_setup_done(&diff_options);
 
        switch (nr_sha1) {
        case 0:
diff --git a/diff.c b/diff.c
index 2e0797bf3ee651a644be50aee10ee125fe96368f..c8159183dac830bf7cba20edf480712f039d7135 100644 (file)
--- a/diff.c
+++ b/diff.c
@@ -723,11 +723,13 @@ static void run_diff(struct diff_filepair *p, struct diff_options *o)
 
        if (memcmp(one->sha1, two->sha1, 20)) {
                char one_sha1[41];
-               const char *index_fmt = o->full_index ? "index %s..%s" : "index %.7s..%.7s";
+               int abbrev = o->full_index ? 40 : DIFF_DEFAULT_INDEX_ABBREV;
                memcpy(one_sha1, sha1_to_hex(one->sha1), 41);
 
                len += snprintf(msg + len, sizeof(msg) - len,
-                               index_fmt, one_sha1, sha1_to_hex(two->sha1));
+                               "index %.*s..%.*s",
+                               abbrev, one_sha1, abbrev,
+                               sha1_to_hex(two->sha1));
                if (one->mode == two->mode)
                        len += snprintf(msg + len, sizeof(msg) - len,
                                        " %06o", one->mode);
@@ -791,6 +793,8 @@ int diff_setup_done(struct diff_options *options)
        }
        if (options->setup & DIFF_SETUP_USE_SIZE_CACHE)
                use_size_cache = 1;
+       if (options->abbrev <= 0 || 40 < options->abbrev)
+               options->abbrev = 40; /* full */
 
        return 0;
 }
@@ -841,6 +845,10 @@ int diff_opt_parse(struct diff_options *options, const char **av, int ac)
        }
        else if (!strcmp(arg, "--find-copies-harder"))
                options->find_copies_harder = 1;
+       else if (!strcmp(arg, "--abbrev"))
+               options->abbrev = DIFF_DEFAULT_ABBREV;
+       else if (!strncmp(arg, "--abbrev=", 9))
+               options->abbrev = strtoul(arg + 9, NULL, 10);
        else
                return 0;
        return 1;
@@ -947,14 +955,49 @@ void diff_free_filepair(struct diff_filepair *p)
        free(p);
 }
 
+/* This is different from find_unique_abbrev() in that
+ * it needs to deal with 0{40} SHA1.
+ */
+const char *diff_unique_abbrev(const unsigned char *sha1, int len)
+{
+       int abblen;
+       const char *abbrev;
+       if (len == 40)
+               return sha1_to_hex(sha1);
+
+       abbrev = find_unique_abbrev(sha1, len);
+       if (!abbrev) {
+               if (!memcmp(sha1, null_sha1, 20)) {
+                       char *buf = sha1_to_hex(null_sha1);
+                       if (len < 37)
+                               strcpy(buf + len, "...");
+                       return buf;
+               }
+               else 
+                       return sha1_to_hex(sha1);
+       }
+       abblen = strlen(abbrev);
+       if (abblen < 37) {
+               static char hex[41];
+               if (len < abblen && abblen <= len + 2)
+                       sprintf(hex, "%s%.*s", abbrev, len+3-abblen, "..");
+               else
+                       sprintf(hex, "%s...", abbrev);
+               return hex;
+       }
+       return sha1_to_hex(sha1);
+}
+
 static void diff_flush_raw(struct diff_filepair *p,
                           int line_termination,
                           int inter_name_termination,
-                          int output_format)
+                          struct diff_options *options)
 {
        int two_paths;
        char status[10];
+       int abbrev = options->abbrev;
        const char *path_one, *path_two;
+       int output_format = options->output_format;
 
        path_one = p->one->path;
        path_two = p->two->path;
@@ -985,8 +1028,10 @@ static void diff_flush_raw(struct diff_filepair *p,
        }
        if (output_format != DIFF_FORMAT_NAME_STATUS) {
                printf(":%06o %06o %s ",
-                      p->one->mode, p->two->mode, sha1_to_hex(p->one->sha1));
-               printf("%s ", sha1_to_hex(p->two->sha1));
+                      p->one->mode, p->two->mode,
+                      diff_unique_abbrev(p->one->sha1, abbrev));
+               printf("%s ",
+                      diff_unique_abbrev(p->two->sha1, abbrev));
        }
        printf("%s%c%s", status, inter_name_termination, path_one);
        if (two_paths)
@@ -1194,7 +1239,7 @@ void diff_flush(struct diff_options *options)
                case DIFF_FORMAT_NAME_STATUS:
                        diff_flush_raw(p, line_termination,
                                       inter_name_termination,
-                                      diff_output_format);
+                                      options);
                        break;
                case DIFF_FORMAT_NAME:
                        diff_flush_name(p,
diff --git a/diff.h b/diff.h
index 32b4780173d78bfd0e77a37f82df4a59aa502ec1..5696f2aff0644f331507679e0a58d7fcdc3501ec 100644 (file)
--- a/diff.h
+++ b/diff.h
@@ -44,6 +44,7 @@ struct diff_options {
        int reverse_diff;
        int rename_limit;
        int setup;
+       int abbrev;
 
        change_fn_t change;
        add_remove_fn_t add_remove;
@@ -87,6 +88,9 @@ extern int diff_setup_done(struct diff_options *);
 
 #define DIFF_PICKAXE_ALL       1
 
+#define DIFF_DEFAULT_INDEX_ABBREV      7 /* hex digits */
+#define DIFF_DEFAULT_ABBREV    7 /* hex digits */
+
 extern void diffcore_std(struct diff_options *);
 
 extern void diffcore_std_no_resolve(struct diff_options *);
@@ -98,7 +102,8 @@ extern void diffcore_std_no_resolve(struct diff_options *);
 "  -u            synonym for -p.\n" \
 "  --name-only   show only names of changed files.\n" \
 "  --name-status show names and status of changed files.\n" \
-"  --full-index  show full object name on index ines.\n" \
+"  --full-index  show full object name on index lines.\n" \
+"  --abbrev=<n>  abbreviate object names in diff-tree header and diff-raw.\n" \
 "  -R            swap input file pairs.\n" \
 "  -B            detect complete rewrites.\n" \
 "  -M            detect renames.\n" \
@@ -137,4 +142,6 @@ extern void diff_flush(struct diff_options*);
 #define DIFF_STATUS_FILTER_AON         '*'
 #define DIFF_STATUS_FILTER_BROKEN      'B'
 
+extern const char *diff_unique_abbrev(const unsigned char *, int);
+
 #endif /* DIFF_H */
diff --git a/fetch-clone.c b/fetch-clone.c
new file mode 100644 (file)
index 0000000..2b2aa15
--- /dev/null
@@ -0,0 +1,172 @@
+#include "cache.h"
+#include <sys/wait.h>
+
+static int finish_pack(const char *pack_tmp_name, const char *me)
+{
+       int pipe_fd[2];
+       pid_t pid;
+       char idx[PATH_MAX];
+       char final[PATH_MAX];
+       char hash[41];
+       unsigned char sha1[20];
+       char *cp;
+       int err = 0;
+
+       if (pipe(pipe_fd) < 0)
+               die("%s: unable to set up pipe", me);
+
+       strcpy(idx, pack_tmp_name); /* ".git/objects/pack-XXXXXX" */
+       cp = strrchr(idx, '/');
+       memcpy(cp, "/pidx", 5);
+
+       pid = fork();
+       if (pid < 0)
+               die("git-clone-pack: unable to fork off git-index-pack");
+       if (!pid) {
+               close(0);
+               dup2(pipe_fd[1], 1);
+               close(pipe_fd[0]);
+               close(pipe_fd[1]);
+               execlp("git-index-pack","git-index-pack",
+                      "-o", idx, pack_tmp_name, NULL);
+               error("cannot exec git-index-pack <%s> <%s>",
+                     idx, pack_tmp_name);
+               exit(1);
+       }
+       close(pipe_fd[1]);
+       if (read(pipe_fd[0], hash, 40) != 40) {
+               error("%s: unable to read from git-index-pack", me);
+               err = 1;
+       }
+       close(pipe_fd[0]);
+
+       for (;;) {
+               int status, code;
+               int retval = waitpid(pid, &status, 0);
+
+               if (retval < 0) {
+                       if (errno == EINTR)
+                               continue;
+                       error("waitpid failed (%s)", strerror(retval));
+                       goto error_die;
+               }
+               if (WIFSIGNALED(status)) {
+                       int sig = WTERMSIG(status);
+                       error("git-index-pack died of signal %d", sig);
+                       goto error_die;
+               }
+               if (!WIFEXITED(status)) {
+                       error("git-index-pack died of unnatural causes %d",
+                             status);
+                       goto error_die;
+               }
+               code = WEXITSTATUS(status);
+               if (code) {
+                       error("git-index-pack died with error code %d", code);
+                       goto error_die;
+               }
+               if (err)
+                       goto error_die;
+               break;
+       }
+       hash[40] = 0;
+       if (get_sha1_hex(hash, sha1)) {
+               error("git-index-pack reported nonsense '%s'", hash);
+               goto error_die;
+       }
+       /* Now we have pack in pack_tmp_name[], and
+        * idx in idx[]; rename them to their final names.
+        */
+       snprintf(final, sizeof(final),
+                "%s/pack/pack-%s.pack", get_object_directory(), hash);
+       move_temp_to_file(pack_tmp_name, final);
+       chmod(final, 0444);
+       snprintf(final, sizeof(final),
+                "%s/pack/pack-%s.idx", get_object_directory(), hash);
+       move_temp_to_file(idx, final);
+       chmod(final, 0444);
+       return 0;
+
+ error_die:
+       unlink(idx);
+       unlink(pack_tmp_name);
+       exit(1);
+}
+
+int receive_unpack_pack(int fd[2], const char *me, int quiet)
+{
+       int status;
+       pid_t pid;
+
+       pid = fork();
+       if (pid < 0)
+               die("%s: unable to fork off git-unpack-objects", me);
+       if (!pid) {
+               dup2(fd[0], 0);
+               close(fd[0]);
+               close(fd[1]);
+               execlp("git-unpack-objects", "git-unpack-objects",
+                      quiet ? "-q" : NULL, NULL);
+               die("git-unpack-objects exec failed");
+       }
+       close(fd[0]);
+       close(fd[1]);
+       while (waitpid(pid, &status, 0) < 0) {
+               if (errno != EINTR)
+                       die("waiting for git-unpack-objects: %s",
+                           strerror(errno));
+       }
+       if (WIFEXITED(status)) {
+               int code = WEXITSTATUS(status);
+               if (code)
+                       die("git-unpack-objects died with error code %d",
+                           code);
+               return 0;
+       }
+       if (WIFSIGNALED(status)) {
+               int sig = WTERMSIG(status);
+               die("git-unpack-objects died of signal %d", sig);
+       }
+       die("git-unpack-objects died of unnatural causes %d", status);
+}
+
+int receive_keep_pack(int fd[2], const char *me)
+{
+       char tmpfile[PATH_MAX];
+       int ofd, ifd;
+
+       ifd = fd[0];
+       snprintf(tmpfile, sizeof(tmpfile),
+                "%s/pack/tmp-XXXXXX", get_object_directory());
+       ofd = mkstemp(tmpfile);
+       if (ofd < 0)
+               return error("unable to create temporary file %s", tmpfile);
+
+       while (1) {
+               char buf[8192];
+               ssize_t sz, wsz, pos;
+               sz = read(ifd, buf, sizeof(buf));
+               if (sz == 0)
+                       break;
+               if (sz < 0) {
+                       error("error reading pack (%s)", strerror(errno));
+                       close(ofd);
+                       unlink(tmpfile);
+                       return -1;
+               }
+               pos = 0;
+               while (pos < sz) {
+                       wsz = write(ofd, buf + pos, sz - pos);
+                       if (wsz < 0) {
+                               error("error writing pack (%s)",
+                                     strerror(errno));
+                               close(ofd);
+                               unlink(tmpfile);
+                               return -1;
+                       }
+                       pos += wsz;
+               }
+       }
+       close(ofd);
+       return finish_pack(tmpfile, me);
+}
index 58ba2094dc6eda7e0429cf83730f8c4c84e4c084..d34f322477a9a072da3981c7ba49c87232ed8bc4 100644 (file)
@@ -3,13 +3,12 @@
 #include "pkt-line.h"
 #include "commit.h"
 #include "tag.h"
-#include <time.h>
-#include <sys/wait.h>
 
+static int keep_pack;
 static int quiet;
 static int verbose;
 static const char fetch_pack_usage[] =
-"git-fetch-pack [-q] [-v] [--exec=upload-pack] [host:]directory <refs>...";
+"git-fetch-pack [-q] [-v] [-k] [--exec=upload-pack] [host:]directory <refs>...";
 static const char *exec = "git-upload-pack";
 
 #define COMPLETE       (1U << 0)
@@ -363,7 +362,6 @@ static int fetch_pack(int fd[2], int nr_match, char **match)
        struct ref *ref;
        unsigned char sha1[20];
        int status;
-       pid_t pid;
 
        get_remote_heads(fd[0], &ref, 0, NULL, 0);
        if (server_supports("multi_ack")) {
@@ -381,40 +379,22 @@ static int fetch_pack(int fd[2], int nr_match, char **match)
        }
        if (find_common(fd, sha1, ref) < 0)
                fprintf(stderr, "warning: no common commits\n");
-       pid = fork();
-       if (pid < 0)
-               die("git-fetch-pack: unable to fork off git-unpack-objects");
-       if (!pid) {
-               dup2(fd[0], 0);
-               close(fd[0]);
-               close(fd[1]);
-               execlp("git-unpack-objects", "git-unpack-objects",
-                      quiet ? "-q" : NULL, NULL);
-               die("git-unpack-objects exec failed");
-       }
-       close(fd[0]);
-       close(fd[1]);
-       while (waitpid(pid, &status, 0) < 0) {
-               if (errno != EINTR)
-                       die("waiting for git-unpack-objects: %s", strerror(errno));
-       }
-       if (WIFEXITED(status)) {
-               int code = WEXITSTATUS(status);
-               if (code)
-                       die("git-unpack-objects died with error code %d", code);
-all_done:
-               while (ref) {
-                       printf("%s %s\n",
-                              sha1_to_hex(ref->old_sha1), ref->name);
-                       ref = ref->next;
-               }
-               return 0;
-       }
-       if (WIFSIGNALED(status)) {
-               int sig = WTERMSIG(status);
-               die("git-unpack-objects died of signal %d", sig);
+
+       if (keep_pack)
+               status = receive_keep_pack(fd, "git-fetch-pack");
+       else
+               status = receive_unpack_pack(fd, "git-fetch-pack", quiet);
+
+       if (status)
+               die("git-fetch-pack: fetch failed.");
+
+ all_done:
+       while (ref) {
+               printf("%s %s\n",
+                      sha1_to_hex(ref->old_sha1), ref->name);
+               ref = ref->next;
        }
-       die("Sherlock Holmes! git-unpack-objects died of unnatural causes %d!", status);
+       return 0;
 }
 
 int main(int argc, char **argv)
@@ -436,10 +416,14 @@ int main(int argc, char **argv)
                                exec = arg + 7;
                                continue;
                        }
-                       if (!strcmp("-q", arg)) {
+                       if (!strcmp("--quiet", arg) || !strcmp("-q", arg)) {
                                quiet = 1;
                                continue;
                        }
+                       if (!strcmp("--keep", arg) || !strcmp("-k", arg)) {
+                               keep_pack = 1;
+                               continue;
+                       }
                        if (!strcmp("-v", arg)) {
                                verbose = 1;
                                continue;
index 1a114bcc0809836ed4edaa0866704b899e587cd2..731ab1fffa4fbe563ab5e2c09cbbdca07e16cac4 100755 (executable)
--- a/git-am.sh
+++ b/git-am.sh
@@ -211,6 +211,7 @@ this=`cat "$dotest/next"`
 if test "$skip" = t
 then
        this=`expr "$this" + 1`
+       resume=
 fi
 
 if test "$this" -gt "$last"
@@ -225,6 +226,7 @@ do
        msgnum=`printf "%0${prec}d" $this`
        next=`expr "$this" + 1`
        test -f "$dotest/$msgnum" || {
+               resume=
                go_next
                continue
        }
index e8ba34a0ad4a466083c8462cc038de9d8ad6a4ab..12cab1e0d4ceb1f1c58c418f96358b252713bf58 100755 (executable)
@@ -14,7 +14,7 @@
 USAGE='<msg> <patch> <info> [<signoff>]'
 . git-sh-setup
 
-case "$#" in 3|4) usage ;; esac
+case "$#" in 3|4) ;; *) usage ;; esac
 
 final=.dotest/final-commit
 ##
index aab4e38440ef0d9d757f3df09406901a9693a356..841738d5c755209fe24aa5026cda13423d226ad9 100755 (executable)
@@ -9,7 +9,8 @@
 
 =head1 Invocation
 
-    git-archimport [ -h ] [ -v ] [ -T ] [ -t tempdir ] <archive>/<branch> [ <archive>/<branch> ]
+    git-archimport [ -h ] [ -v ] [ -o ] [ -a ] [ -f ] [ -T ] 
+       [ -D depth] [ -t tempdir ] <archive>/<branch> [ <archive>/<branch> ]
 
 Imports a project from one or more Arch repositories. It will follow branches
 and repositories within the namespaces defined by the <archive/branch>
@@ -74,7 +75,7 @@ =head1 Devel Notes
 sub usage() {
     print STDERR <<END;
 Usage: ${\basename $0}     # fetch/update GIT from Arch
-       [ -f ] [ -o ] [ -h ] [ -v ] [ -T ] [ -a ] [ -D depth  ] [ -t tempdir ]
+       [ -h ] [ -v ] [ -o ] [ -a ] [ -f ] [ -T ] [ -D depth ] [ -t tempdir ]
        repository/arch-branch [ repository/arch-branch] ...
 END
     exit(1);
index 0266f46223c2f20973bbbcb78f4825ff880d9bd3..b0e54ed2af9dbf06e79b7230a62029ee2ee8a269 100755 (executable)
@@ -32,11 +32,11 @@ delete_branch () {
            case " $mbs " in
            *' '$branch' '*)
                # the merge base of branch and HEAD contains branch --
-               # which means that the HEAD contains everything in the HEAD.
+               # which means that the HEAD contains everything in both.
                ;;
            *)
                echo >&2 "The branch '$branch_name' is not a strict subset of your current HEAD.
-    If you are sure you want to delete it, run 'git branch -D $branch_name'."
+If you are sure you want to delete it, run 'git branch -D $branch_name'."
                exit 1
                ;;
            esac
index f241d4ba6ba5a988f801e3307022d188204ff572..36308d22c6a72b9ad53ced60bd3c70a2e17520b6 100755 (executable)
@@ -116,7 +116,7 @@ else
 fi
 
 # 
-# Switch the HEAD pointer to the new branch if it we
+# Switch the HEAD pointer to the new branch if we
 # checked out a branch head, and remove any potential
 # old MERGE_HEAD's (subsequent commits will clearly not
 # be based on them, since we re-set the index)
index ead0ede5872e3c1ca10596010d4827ed726ff394..0c98c9937df14bfa8be4f58cae84aa16029be883 100644 (file)
@@ -84,6 +84,28 @@ static inline void *xcalloc(size_t nmemb, size_t size)
        return ret;
 }
 
+static inline ssize_t xread(int fd, void *buf, size_t len)
+{
+       ssize_t nr;
+       while (1) {
+               nr = read(fd, buf, len);
+               if ((nr < 0) && (errno == EAGAIN || errno == EINTR))
+                       continue;
+               return nr;
+       }
+}
+
+static inline ssize_t xwrite(int fd, const void *buf, size_t len)
+{
+       ssize_t nr;
+       while (1) {
+               nr = write(fd, buf, len);
+               if ((nr < 0) && (errno == EAGAIN || errno == EINTR))
+                       continue;
+               return nr;
+       }
+}
+
 /* Sane ctype - no locale, and works with signed chars */
 #undef isspace
 #undef isdigit
index b62e58341cd9d11fc893613949426126871531e2..4812ae4c1ff937ded49334a97ee1dc2c1732e433 100755 (executable)
@@ -3,15 +3,14 @@
 # Copyright (c) 2005 Linus Torvalds
 # Copyright (c) 2005 Junio C Hamano
 
+USAGE='[ --diff-options ] <ent>{0,2} [<path>...]'
+SUBDIRECTORY_OK='Yes'
+. git-sh-setup
+
 rev=$(git-rev-parse --revs-only --no-flags --sq "$@") || exit
 flags=$(git-rev-parse --no-revs --flags --sq "$@")
 files=$(git-rev-parse --no-revs --no-flags --sq "$@")
 
-die () {
-    echo >&2 "$*"
-    exit 1
-}
-
 # I often say 'git diff --cached -p' and get scolded by git-diff-files, but
 # obviously I mean 'git diff --cached -p HEAD' in that case.
 case "$rev" in
@@ -40,8 +39,7 @@ esac
 
 case "$rev" in
 ?*' '?*' '?*)
-       echo >&2 "I don't understand"
-       exit 1
+       usage
        ;;
 ?*' '^?*)
        begin=$(expr "$rev" : '.*^.\([0-9a-f]*\).*') &&
@@ -58,7 +56,7 @@ case "$rev" in
        cmd="git-diff-files $flags -- $files"
        ;;
 *)
-       die "I don't understand $*"
+       usage
        ;;
 esac
 
index 01508e3b04f91bba3e960eb74eaff3e349e209bd..daa3caea778e13e946c4ffe53c876f5222ce7dfe 100755 (executable)
@@ -210,6 +210,8 @@ Date: '"$ad"
        }
 
        mailScript="$mailScript"'
+       a\
+
        : body
        p
        n
index b36c4e95343aeefd436ac5b4a9d80a85ddc6ec56..c2ea71cf14a6a96c2f9124fb57425e682f735995 100755 (executable)
@@ -3,13 +3,13 @@
 # Copyright (c) 2005 Linus Torvalds
 #
 
-# This one uses only subdirectory-aware commands, so no need to
-# include sh-setup-script.
+USAGE='[--max-count=<n>] [<since>..<limit>] [--pretty=<format>] [git-rev-list options]'
+SUBDIRECTORY_OK='Yes'
+. git-sh-setup
 
 revs=$(git-rev-parse --revs-only --no-flags --default HEAD "$@") || exit
 [ "$revs" ] || {
-       echo >&2 "No HEAD ref"
-       exit 1
+       die "No HEAD ref"
 }
 git-rev-list --pretty $(git-rev-parse --default HEAD "$@") |
 LESS=-S ${PAGER:-less}
diff --git a/git-octopus.sh b/git-octopus.sh
deleted file mode 100755 (executable)
index 2edbf52..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
-#!/bin/sh
-#
-# Copyright (c) 2005 Junio C Hamano
-#
-# Resolve two or more trees recorded in $GIT_DIR/FETCH_HEAD.
-#
-. git-sh-setup
-
-usage () {
-    die "usage: git octopus"
-}
-
-# Sanity check the heads early.
-while read SHA1 REPO
-do
-       test $(git-cat-file -t $SHA1) = "commit" ||
-               die "$REPO given to octopus is not a commit"
-done <"$GIT_DIR/FETCH_HEAD"
-
-head=$(git-rev-parse --verify HEAD) || exit
-
-git-update-index --refresh ||
-       die "Your working tree is dirty."
-test "$(git-diff-index --cached "$head")" = "" ||
-       die "Your working tree does not match HEAD."
-
-# MRC is the current "merge reference commit"
-# MRT is the current "merge result tree"
-
-MRC=$head PARENT="-p $head"
-MRT=$(git-write-tree)
-CNT=1 ;# counting our head
-NON_FF_MERGE=0
-while read SHA1 REPO
-do
-       common=$(git-merge-base $MRC $SHA1) ||
-               die "Unable to find common commit with $SHA1 from $REPO"
-
-       if test "$common" = $SHA1
-       then
-               echo "Already up-to-date: $REPO"
-               continue
-       fi
-
-       CNT=`expr $CNT + 1`
-       PARENT="$PARENT -p $SHA1"
-
-       if test "$common,$NON_FF_MERGE" = "$MRC,0"
-       then
-               # The first head being merged was a fast-forward.
-               # Advance MRC to the head being merged, and use that
-               # tree as the intermediate result of the merge.
-               # We still need to count this as part of the parent set.
-
-               echo "Fast forwarding to: $REPO"
-               git-read-tree -u -m $head $SHA1 || exit
-               MRC=$SHA1 MRT=$(git-write-tree)
-               continue
-       fi
-
-       NON_FF_MERGE=1
-
-       echo "Trying simple merge with $REPO"
-       git-read-tree -u -m $common $MRT $SHA1 || exit
-       next=$(git-write-tree 2>/dev/null)
-       if test $? -ne 0
-       then
-               echo "Simple merge did not work, trying automatic merge."
-               git-merge-index -o git-merge-one-file -a || {
-               git-read-tree --reset "$head"
-               git-checkout-index -f -q -u -a
-               die "Automatic merge failed; should not be doing Octopus"
-               }
-               next=$(git-write-tree 2>/dev/null)
-       fi
-       MRC=$common
-       MRT=$next
-done <"$GIT_DIR/FETCH_HEAD"
-
-# Just to be careful in case the user feeds nonsense to us.
-case "$CNT" in
-1)
-       echo "No changes."
-       exit 0 ;;
-esac
-result_commit=$(git-fmt-merge-msg <"$GIT_DIR/FETCH_HEAD" |
-               git-commit-tree $MRT $PARENT)
-echo "Committed merge $result_commit"
-git-update-ref HEAD $result_commit $head
-git-diff-tree -p $head $result_commit | git-apply --stat
index 65868a91e5f88c41942da89b84f169ed4264615d..cb241d1b5174fad6b6eb081635e614d251688f0d 100755 (executable)
@@ -736,6 +736,13 @@ sub commit_all {
 }
 
 $opt_l = $svn->{'maxrev'} if not defined $opt_l or $opt_l > $svn->{'maxrev'};
+
+if ($svn->{'maxrev'} < $current_rev) {
+    print "Up to date: no new revisions to fetch!\n" if $opt_v;
+    unlink("$git_dir/SVN2GIT_HEAD");
+    exit;
+}
+
 print "Fetching from $current_rev to $opt_l ...\n" if $opt_v;
 
 my $pool=SVN::Pool->new;
index 85a49fcd8e7754cc37960c997a200b61c85892b4..b170f74a94e42dbf82f2e94b831f1cf6b49a2b4c 100755 (executable)
@@ -1,4 +1,9 @@
 #!/bin/sh
+
+USAGE='[-p] [--max-count=<n>] [<since>..<limit>] [--pretty=<format>] [-m] [git-diff-tree options] [git-rev-list options]'
+SUBDIRECTORY_OK='Yes'
+. git-sh-setup
+
 rev_list_args=$(git-rev-parse --sq --default HEAD --revs-only "$@") &&
 diff_tree_args=$(git-rev-parse --sq --no-revs "$@") &&
 
diff --git a/git.c b/git.c
index c26cac6555e940e1ae5573a99350388f09118b87..0fd95bf751cd5abfeb8a95f3b828adde4537dfde 100644 (file)
--- a/git.c
+++ b/git.c
@@ -8,6 +8,7 @@
 #include <errno.h>
 #include <limits.h>
 #include <stdarg.h>
+#include <sys/ioctl.h>
 #include "git-compat-util.h"
 
 #ifndef PATH_MAX
@@ -26,6 +27,16 @@ static int term_columns(void)
        if (col_string && (n_cols = atoi(col_string)) > 0)
                return n_cols;
 
+#ifdef TIOCGWINSZ
+       {
+               struct winsize ws;
+               if (!ioctl(1, TIOCGWINSZ, &ws)) {
+                       if (ws.ws_col)
+                               return ws.ws_col;
+               }
+       }
+#endif
+
        return 80;
 }
 
@@ -74,25 +85,28 @@ static int cmdname_compare(const void *a_, const void *b_)
 
 static void pretty_print_string_list(struct cmdname **cmdname, int longest)
 {
-       int cols = 1;
+       int cols = 1, rows;
        int space = longest + 1; /* min 1 SP between words */
        int max_cols = term_columns() - 1; /* don't print *on* the edge */
-       int i;
+       int i, j;
 
        if (space < max_cols)
                cols = max_cols / space;
+       rows = (cmdname_cnt + cols - 1) / cols;
 
        qsort(cmdname, cmdname_cnt, sizeof(*cmdname), cmdname_compare);
 
-       for (i = 0; i < cmdname_cnt; ) {
-               int c;
+       for (i = 0; i < rows; i++) {
                printf("  ");
 
-               for (c = cols; c && i < cmdname_cnt; i++) {
-                       printf("%s", cmdname[i]->name);
-
-                       if (--c)
-                               mput_char(' ', space - cmdname[i]->len);
+               for (j = 0; j < cols; j++) {
+                       int n = j * rows + i;
+                       int size = space;
+                       if (n >= cmdname_cnt)
+                               break;
+                       if (j == cols-1 || n + rows >= cmdname_cnt)
+                               size = 1;
+                       printf("%-*s", size, cmdname[n]->name);
                }
                putchar('\n');
        }
diff --git a/mktag.c b/mktag.c
index 97e270a5761f071aeb3666b595b5cd6a8cbd4098..fc6a9bf5f34158605add585439848367deaefac5 100644 (file)
--- a/mktag.c
+++ b/mktag.c
@@ -116,14 +116,9 @@ int main(int argc, char **argv)
        // Read the signature
        size = 0;
        for (;;) {
-               int ret = read(0, buffer + size, MAXSIZE - size);
-               if (!ret)
+               int ret = xread(0, buffer + size, MAXSIZE - size);
+               if (ret <= 0)
                        break;
-               if (ret < 0) {
-                       if (errno == EAGAIN)
-                               continue;
-                       break;
-               }
                size += ret;
        }
 
index 69473046bf717c9b97470d7652c15377dd9fc9d5..bb3bab05cd203e114b24b778cb5f55218abdec95 100644 (file)
@@ -19,7 +19,7 @@
 static void safe_write(int fd, const void *buf, unsigned n)
 {
        while (n) {
-               int ret = write(fd, buf, n);
+               int ret = xwrite(fd, buf, n);
                if (ret > 0) {
                        buf += ret;
                        n -= ret;
@@ -27,8 +27,6 @@ static void safe_write(int fd, const void *buf, unsigned n)
                }
                if (!ret)
                        die("write error (disk full?)");
-               if (errno == EAGAIN || errno == EINTR)
-                       continue;
                die("write error (%s)", strerror(errno));
        }
 }
@@ -68,12 +66,9 @@ static void safe_read(int fd, void *buffer, unsigned size)
        int n = 0;
 
        while (n < size) {
-               int ret = read(fd, buffer + n, size - n);
-               if (ret < 0) {
-                       if (errno == EINTR || errno == EAGAIN)
-                               continue;
+               int ret = xread(fd, buffer + n, size - n);
+               if (ret < 0)
                        die("read error (%s)", strerror(errno));
-               }
                if (!ret)
                        die("unexpected EOF");
                n += ret;
index 693273620370e0500bc9ea2adba98a88cafc39cd..c5474d49758b640f8942b1e3eb1a1c8f47c78ed8 100644 (file)
@@ -6,6 +6,7 @@
 #include "cache.h"
 
 struct cache_entry **active_cache = NULL;
+static time_t index_file_timestamp;
 unsigned int active_nr = 0, active_alloc = 0, active_cache_changed = 0;
 
 /*
@@ -28,7 +29,65 @@ void fill_stat_cache_info(struct cache_entry *ce, struct stat *st)
        ce->ce_size = htonl(st->st_size);
 }
 
-int ce_match_stat(struct cache_entry *ce, struct stat *st)
+static int ce_compare_data(struct cache_entry *ce, struct stat *st)
+{
+       int match = -1;
+       int fd = open(ce->name, O_RDONLY);
+
+       if (fd >= 0) {
+               unsigned char sha1[20];
+               if (!index_fd(sha1, fd, st, 0, NULL))
+                       match = memcmp(sha1, ce->sha1, 20);
+               close(fd);
+       }
+       return match;
+}
+
+static int ce_compare_link(struct cache_entry *ce, unsigned long expected_size)
+{
+       int match = -1;
+       char *target;
+       void *buffer;
+       unsigned long size;
+       char type[10];
+       int len;
+
+       target = xmalloc(expected_size);
+       len = readlink(ce->name, target, expected_size);
+       if (len != expected_size) {
+               free(target);
+               return -1;
+       }
+       buffer = read_sha1_file(ce->sha1, type, &size);
+       if (!buffer) {
+               free(target);
+               return -1;
+       }
+       if (size == expected_size)
+               match = memcmp(buffer, target, size);
+       free(buffer);
+       free(target);
+       return match;
+}
+
+static int ce_modified_check_fs(struct cache_entry *ce, struct stat *st)
+{
+       switch (st->st_mode & S_IFMT) {
+       case S_IFREG:
+               if (ce_compare_data(ce, st))
+                       return DATA_CHANGED;
+               break;
+       case S_IFLNK:
+               if (ce_compare_link(ce, st->st_size))
+                       return DATA_CHANGED;
+               break;
+       default:
+               return TYPE_CHANGED;
+       }
+       return 0;
+}
+
+static int ce_match_stat_basic(struct cache_entry *ce, struct stat *st)
 {
        unsigned int changed = 0;
 
@@ -83,57 +142,44 @@ int ce_match_stat(struct cache_entry *ce, struct stat *st)
 
        if (ce->ce_size != htonl(st->st_size))
                changed |= DATA_CHANGED;
+
        return changed;
 }
 
-static int ce_compare_data(struct cache_entry *ce, struct stat *st)
+int ce_match_stat(struct cache_entry *ce, struct stat *st)
 {
-       int match = -1;
-       int fd = open(ce->name, O_RDONLY);
+       unsigned int changed = ce_match_stat_basic(ce, st);
 
-       if (fd >= 0) {
-               unsigned char sha1[20];
-               if (!index_fd(sha1, fd, st, 0, NULL))
-                       match = memcmp(sha1, ce->sha1, 20);
-               close(fd);
-       }
-       return match;
-}
-
-static int ce_compare_link(struct cache_entry *ce, unsigned long expected_size)
-{
-       int match = -1;
-       char *target;
-       void *buffer;
-       unsigned long size;
-       char type[10];
-       int len;
+       /*
+        * Within 1 second of this sequence:
+        *      echo xyzzy >file && git-update-index --add file
+        * running this command:
+        *      echo frotz >file
+        * would give a falsely clean cache entry.  The mtime and
+        * length match the cache, and other stat fields do not change.
+        *
+        * We could detect this at update-index time (the cache entry
+        * being registered/updated records the same time as "now")
+        * and delay the return from git-update-index, but that would
+        * effectively mean we can make at most one commit per second,
+        * which is not acceptable.  Instead, we check cache entries
+        * whose mtime are the same as the index file timestamp more
+        * careful than others.
+        */
+       if (!changed &&
+           index_file_timestamp &&
+           index_file_timestamp <= ntohl(ce->ce_mtime.sec))
+               changed |= ce_modified_check_fs(ce, st);
 
-       target = xmalloc(expected_size);
-       len = readlink(ce->name, target, expected_size);
-       if (len != expected_size) {
-               free(target);
-               return -1;
-       }
-       buffer = read_sha1_file(ce->sha1, type, &size);
-       if (!buffer) {
-               free(target);
-               return -1;
-       }
-       if (size == expected_size)
-               match = memcmp(buffer, target, size);
-       free(buffer);
-       free(target);
-       return match;
+       return changed;
 }
 
 int ce_modified(struct cache_entry *ce, struct stat *st)
 {
-       int changed;
+       int changed, changed_fs;
        changed = ce_match_stat(ce, st);
        if (!changed)
                return 0;
-
        /*
         * If the mode or type has changed, there's no point in trying
         * to refresh the entry - it's not going to match
@@ -148,18 +194,9 @@ int ce_modified(struct cache_entry *ce, struct stat *st)
        if ((changed & DATA_CHANGED) && ce->ce_size != htonl(0))
                return changed;
 
-       switch (st->st_mode & S_IFMT) {
-       case S_IFREG:
-               if (ce_compare_data(ce, st))
-                       return changed | DATA_CHANGED;
-               break;
-       case S_IFLNK:
-               if (ce_compare_link(ce, st->st_size))
-                       return changed | DATA_CHANGED;
-               break;
-       default:
-               return changed | TYPE_CHANGED;
-       }
+       changed_fs = ce_modified_check_fs(ce, st);
+       if (changed_fs)
+               return changed | changed_fs;
        return 0;
 }
 
@@ -471,6 +508,7 @@ int read_cache(void)
                return active_nr;
 
        errno = ENOENT;
+       index_file_timestamp = 0;
        fd = open(get_index_file(), O_RDONLY);
        if (fd < 0) {
                if (errno == ENOENT)
@@ -504,6 +542,7 @@ int read_cache(void)
                offset = offset + ce_size(ce);
                active_cache[i] = ce;
        }
+       index_file_timestamp = st.st_mtime;
        return active_nr;
 
 unmap:
@@ -562,6 +601,50 @@ static int ce_flush(SHA_CTX *context, int fd)
        return 0;
 }
 
+static void ce_smudge_racily_clean_entry(struct cache_entry *ce)
+{
+       /*
+        * The only thing we care about in this function is to smudge the
+        * falsely clean entry due to touch-update-touch race, so we leave
+        * everything else as they are.  We are called for entries whose
+        * ce_mtime match the index file mtime.
+        */
+       struct stat st;
+
+       if (lstat(ce->name, &st) < 0)
+               return;
+       if (ce_match_stat_basic(ce, &st))
+               return;
+       if (ce_modified_check_fs(ce, &st)) {
+               /* This is "racily clean"; smudge it.  Note that this
+                * is a tricky code.  At first glance, it may appear
+                * that it can break with this sequence:
+                *
+                * $ echo xyzzy >frotz
+                * $ git-update-index --add frotz
+                * $ : >frotz
+                * $ sleep 3
+                * $ echo filfre >nitfol
+                * $ git-update-index --add nitfol
+                *
+                * but it does not.  Whe the second update-index runs,
+                * it notices that the entry "frotz" has the same timestamp
+                * as index, and if we were to smudge it by resetting its
+                * size to zero here, then the object name recorded
+                * in index is the 6-byte file but the cached stat information
+                * becomes zero --- which would then match what we would
+                * obtain from the filesystem next time we stat("frotz"). 
+                *
+                * However, the second update-index, before calling
+                * this function, notices that the cached size is 6
+                * bytes and what is on the filesystem is an empty
+                * file, and never calls us, so the cached size information
+                * for "frotz" stays 6 which does not match the filesystem.
+                */
+               ce->ce_size = htonl(0);
+       }
+}
+
 int write_cache(int newfd, struct cache_entry **cache, int entries)
 {
        SHA_CTX c;
@@ -584,6 +667,9 @@ int write_cache(int newfd, struct cache_entry **cache, int entries)
                struct cache_entry *ce = cache[i];
                if (!ce->ce_mode)
                        continue;
+               if (index_file_timestamp &&
+                   index_file_timestamp <= ntohl(ce->ce_mtime.sec))
+                       ce_smudge_racily_clean_entry(ce);
                if (ce_write(&c, newfd, ce, ce_size(ce)) < 0)
                        return -1;
        }
diff --git a/refs.c b/refs.c
index d2aec73edcbe06cf63009ac7dd85fa53b6c995b9..c33729c54a001423fb682cc920b72e5b1d03f8ea 100644 (file)
--- a/refs.c
+++ b/refs.c
@@ -313,7 +313,9 @@ int write_ref_sha1(const char *ref, int fd, const unsigned char *sha1)
 static inline int bad_ref_char(int ch)
 {
        return (((unsigned) ch) <= ' ' ||
-               ch == '~' || ch == '^' || ch == ':');
+               ch == '~' || ch == '^' || ch == ':' ||
+               /* 2.13 Pattern Matching Notation */
+               ch == '?' || ch == '*' || ch == '[');
 }
 
 int check_ref_format(const char *ref)
index 8020d974f2fc84d477920bd10ea450c44fce0a77..d0609666a1c5732aa9bc9359d70fd3cf65555c29 100644 (file)
@@ -850,7 +850,8 @@ int main(int argc, const char **argv)
                handle_one_commit(commit, &list);
        }
 
-       if (!list)
+       if (!list &&
+           (!(tag_objects||tree_objects||blob_objects) && !pending_objects))
                usage(rev_list_usage);
 
        paths = get_pathspec(prefix, argv + i);
index 6ce0d9f7884e34c9dc6c90f98bc9f7745c07e12a..a41bbe5ecfdff6fd7cea1bfc3d3415ba57867f2b 100644 (file)
@@ -8,6 +8,7 @@ static const char send_pack_usage[] =
 "git-send-pack [--all] [--exec=git-receive-pack] <remote> [<head>...]\n"
 "  --all and explicit <head> specification are mutually exclusive.";
 static const char *exec = "git-receive-pack";
+static int verbose = 0;
 static int send_all = 0;
 static int force_update = 0;
 
@@ -206,7 +207,8 @@ static int send_pack(int in, int out, int nr_refspec, char **refspec)
                if (!ref->peer_ref)
                        continue;
                if (!memcmp(ref->old_sha1, ref->peer_ref->new_sha1, 20)) {
-                       fprintf(stderr, "'%s': up-to-date\n", ref->name);
+                       if (verbose)
+                               fprintf(stderr, "'%s': up-to-date\n", ref->name);
                        continue;
                }
 
@@ -270,6 +272,8 @@ static int send_pack(int in, int out, int nr_refspec, char **refspec)
        packet_flush(out);
        if (new_refs)
                pack_objects(out, remote_refs);
+       else
+               fprintf(stderr, "Everything up-to-date\n");
        close(out);
        return ret;
 }
@@ -301,6 +305,10 @@ int main(int argc, char **argv)
                                force_update = 1;
                                continue;
                        }
+                       if (!strcmp(arg, "--verbose")) {
+                               verbose = 1;
+                               continue;
+                       }
                        usage(send_pack_usage);
                }
                if (!dest) {
index faac158b16ca978914696ed5d2801770a122cce2..b13ed78cee0ee7f6d5ed3b45acee7b308a02c3f6 100644 (file)
@@ -188,7 +188,10 @@ const char *find_unique_abbrev(const unsigned char *sha1, int len)
 {
        int status;
        static char hex[41];
+
        memcpy(hex, sha1_to_hex(sha1), 40);
+       if (len == 40)
+               return hex;
        while (len < 40) {
                unsigned char sha1_ret[20];
                status = get_short_sha1(hex, len, sha1_ret, 1);
@@ -203,11 +206,12 @@ const char *find_unique_abbrev(const unsigned char *sha1, int len)
        return NULL;
 }
 
-static int ambiguous_path(const char *path)
+static int ambiguous_path(const char *path, int len)
 {
        int slash = 1;
+       int cnt;
 
-       for (;;) {
+       for (cnt = 0; cnt < len; cnt++) {
                switch (*path++) {
                case '\0':
                        break;
@@ -222,8 +226,9 @@ static int ambiguous_path(const char *path)
                        slash = 0;
                        continue;
                }
-               return slash;
+               break;
        }
+       return slash;
 }
 
 static int get_sha1_basic(const char *str, int len, unsigned char *sha1)
@@ -236,31 +241,19 @@ static int get_sha1_basic(const char *str, int len, unsigned char *sha1)
                NULL
        };
        const char **p;
-       int found = 0;
 
        if (len == 40 && !get_sha1_hex(str, sha1))
                return 0;
 
        /* Accept only unambiguous ref paths. */
-       if (ambiguous_path(str))
+       if (ambiguous_path(str, len))
                return -1;
 
        for (p = prefix; *p; p++) {
                char *pathname = git_path("%s/%.*s", *p, len, str);
-               if (!read_ref(pathname, sha1)) {
-                       /* Must be unique; i.e. when heads/foo and
-                        * tags/foo are both present, reject "foo".
-                        * Note that read_ref() eventually calls
-                        * get_sha1_hex() which can smudge initial
-                        * part of the buffer even if what is read
-                        * is found to be invalid halfway.
-                        */
-                       if (1 < found++)
-                               return -1;
-               }
+               if (!read_ref(pathname, sha1))
+                       return 0;
        }
-       if (found == 1)
-               return 0;
        return -1;
 }
 
index ab158eb7d08e9f6fe5c93d660a92c4b97914e516..c7422460be0a68dc34baa1dc8b66aa44559d56de 100644 (file)
@@ -450,6 +450,8 @@ static void append_one_rev(const char *av)
                if (saved_matches == ref_name_cnt &&
                    ref_name_cnt < MAX_REVS)
                        error("no matching refs with %s", av);
+               if (saved_matches + 1 < ref_name_cnt)
+                       sort_ref_range(saved_matches, ref_name_cnt);
                return;
        }
        die("bad sha1 reference %s", av);
diff --git a/t/t0010-racy-git.sh b/t/t0010-racy-git.sh
new file mode 100755 (executable)
index 0000000..e45a9e4
--- /dev/null
@@ -0,0 +1,33 @@
+#!/bin/sh
+
+test_description='racy GIT'
+
+. ./test-lib.sh
+
+# This test can give false success if your machine is sufficiently
+# slow or your trial happened to happen on second boundary.
+
+for trial in 0 1 2 3 4
+do
+       rm -f .git/index
+       echo frotz >infocom
+       git update-index --add infocom
+       echo xyzzy >infocom
+
+       files=`git diff-files -p`
+       test_expect_success \
+       "Racy GIT trial #$trial part A" \
+       'test "" != "$files"'
+
+       sleep 1
+       echo xyzzy >cornerstone
+       git update-index --add cornerstone
+
+       files=`git diff-files -p`
+       test_expect_success \
+       "Racy GIT trial #$trial part B" \
+       'test "" != "$files"'
+
+done
+
+test_done
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
old mode 100644 (file)
new mode 100755 (executable)
index 2819bef1c4a80954be121bde3c44fce9221fcdfa..a97d259e26bc269c8f370f1d3bfa82e7d6cb9831 100755 (executable)
@@ -18,6 +18,7 @@ unset GIT_ALTERNATE_OBJECT_DIRECTORIES
 unset GIT_AUTHOR_DATE
 unset GIT_AUTHOR_EMAIL
 unset GIT_AUTHOR_NAME
+unset GIT_COMMITTER_DATE
 unset GIT_COMMITTER_EMAIL
 unset GIT_COMMITTER_NAME
 unset GIT_DIFF_OPTS
index bacb23ae6365767dfdc93c6041aa9f3cb673b27b..96bd1438d9033e5bca3841fb85a531ea27070faf 100644 (file)
@@ -34,10 +34,8 @@ struct path_prefix {
 static void reliable_write(void *buf, unsigned long size)
 {
        while (size > 0) {
-               long ret = write(1, buf, size);
+               long ret = xwrite(1, buf, size);
                if (ret < 0) {
-                       if (errno == EAGAIN)
-                               continue;
                        if (errno == EPIPE)
                                exit(0);
                        die("git-tar-tree: %s", strerror(errno));
index cfd61ae6b08c0635da4044ec3ab09f40c3178632..5c5cb12f6fa2a9a8fe061c2e75380c8b9e7ebaf1 100644 (file)
@@ -31,12 +31,10 @@ static void * fill(int min)
                offset = 0;
        }
        do {
-               int ret = read(0, buffer + len, sizeof(buffer) - len);
+               int ret = xread(0, buffer + len, sizeof(buffer) - len);
                if (ret <= 0) {
                        if (!ret)
                                die("early EOF");
-                       if (errno == EAGAIN || errno == EINTR)
-                               continue;
                        die("read error on input: %s", strerror(errno));
                }
                len += ret;
@@ -299,14 +297,9 @@ int main(int argc, char **argv)
 
        /* Write the last part of the buffer to stdout */
        while (len) {
-               int ret = write(1, buffer + offset, len);
-               if (!ret)
-                       break;
-               if (ret < 0) {
-                       if (errno == EAGAIN || errno == EINTR)
-                               continue;
+               int ret = xwrite(1, buffer + offset, len);
+               if (ret <= 0)
                        break;
-               }
                len -= ret;
                offset += ret;
        }