]> git.ipfire.org Git - thirdparty/git.git/commitdiff
Merge branch 'ho/dashless' into maint
authorJunio C Hamano <gitster@pobox.com>
Wed, 3 Sep 2008 21:51:56 +0000 (14:51 -0700)
committerJunio C Hamano <gitster@pobox.com>
Wed, 3 Sep 2008 21:51:56 +0000 (14:51 -0700)
* ho/dashless:
  tests: use "git xyzzy" form (t7200 - t9001)
  tests: use "git xyzzy" form (t7000 - t7199)
  tests: use "git xyzzy" form (t3600 - t6999)
  tests: use "git xyzzy" form (t0000 - t3599)
  'git foo' program identifies itself without dash in die() messages
  Start conforming code to "git subcmd" style

27 files changed:
Documentation/config.txt
Documentation/diff-options.txt
Documentation/git-commit-tree.txt
Documentation/git-for-each-ref.txt
Documentation/git-name-rev.txt
Documentation/git-send-email.txt
Documentation/git-stash.txt
Documentation/git-var.txt
Documentation/gitattributes.txt
Documentation/gitmodules.txt
Documentation/i18n.txt
Makefile
builtin-apply.c
builtin-checkout.c
builtin-clone.c
builtin-pack-objects.c
builtin-verify-pack.c
pack-revindex.c
pack-revindex.h
sha1_file.c
shell.c
sideband.c
t/t4104-apply-boundary.sh
t/t5300-pack-object.sh
t/t5306-pack-nobase.sh [new file with mode: 0755]
t/t5505-remote.sh
t/t5601-clone.sh

index 81f981509a2b9c129b31772dee5b859b3f1a2315..3727239891321a52d16fa7f9ed73bf172b758c48 100644 (file)
@@ -693,7 +693,7 @@ gitcvs.logfile::
        Path to a log file where the CVS server interface well... logs
        various stuff. See linkgit:git-cvsserver[1].
 
-gitcvs.usecrlfattr
+gitcvs.usecrlfattr::
        If true, the server will look up the `crlf` attribute for
        files to determine the '-k' modes to use. If `crlf` is set,
        the '-k' mode will be left blank, so cvs clients will
index cba90fd27c6a1baaca884328e96adc8a6da8fc36..746646bb3d09a16a5880fa6bff286389aae98870 100644 (file)
@@ -59,12 +59,11 @@ endif::git-format-patch[]
        lines.
 
 --dirstat[=limit]::
-       Output only the sub-directories that are impacted by a diff,
-       and to what degree they are impacted.  You can override the
-       default cut-off in percent (3) by "--dirstat=limit".  If you
-       want to enable "cumulative" directory statistics, you can use
-       the "--cumulative" flag, which adds up percentages recursively
-       even when they have been already reported for a sub-directory.
+       Output the distribution of relative amount of changes (number of lines added or
+       removed) for each sub-directory. Directories with changes below
+       a cut-off percent (3% by default) are not shown. The cut-off percent
+       can be set with "--dirstat=limit". Changes in a child directory is not
+       counted for the parent directory, unless "--cumulative" is used.
 
 --summary::
        Output a condensed summary of extended header information
index 92ab3ab4a80a71808ad19a80c82ecb6d032bdea9..b8834baced4b25d6df47eb578c4d745d23e8cc73 100644 (file)
@@ -79,9 +79,9 @@ Diagnostics
 You don't exist. Go away!::
     The passwd(5) gecos field couldn't be read
 Your parents must have hated you!::
-    The password(5) gecos field is longer than a giant static buffer.
+    The passwd(5) gecos field is longer than a giant static buffer.
 Your sysadmin must hate you!::
-    The password(5) name field is longer than a giant static buffer.
+    The passwd(5) name field is longer than a giant static buffer.
 
 Discussion
 ----------
index eae6c0e7bcad5708442d10a7bc73eac3ec90bcbd..ebd7c5fbb34576fd2af98b00d9045340ff77ee2b 100644 (file)
@@ -16,7 +16,7 @@ DESCRIPTION
 
 Iterate over all refs that match `<pattern>` and show them
 according to the given `<format>`, after sorting them according
-to the given set of `<key>`.  If `<max>` is given, stop after
+to the given set of `<key>`.  If `<count>` is given, stop after
 showing that many refs.  The interpolated values in `<format>`
 can optionally be quoted as string literals in the specified
 host language allowing their direct evaluation in that language.
index abd2237e51dfd86bcea98320edfff8922bc04eb6..7ca8a7b48cea191b58db93581f02fa4ff265acdc 100644 (file)
@@ -59,7 +59,7 @@ Enter 'git-name-rev':
 
 ------------
 % git name-rev 33db5f4d9027a10e477ccf054b2c1ab94f74c85a
-33db5f4d9027a10e477ccf054b2c1ab94f74c85a tags/v0.99^0~940
+33db5f4d9027a10e477ccf054b2c1ab94f74c85a tags/v0.99~940
 ------------
 
 Now you are wiser, because you know that it happened 940 revisions before v0.99.
index e2437f30ca1314dc00a55f72c4e2a325cc75c7b6..3c3e1b0e77abe171ac7531b8098ea2af7d6809dd 100644 (file)
@@ -179,6 +179,9 @@ user is prompted for a password while the input is masked for privacy.
        This is useful if your default address is not the address that is
        subscribed to a list. If you use the sendmail binary, you must have
        suitable privileges for the -f parameter.
+       Default is the value of the 'sendemail.envelopesender' configuration
+       variable; if that is unspecified, choosing the envelope sender is left
+       to your MTA.
 
 --to::
        Specify the primary recipient of the emails generated.
index 49e2296a24825b2ea3a0976ff9073e7b44e976d8..051f94d26f9f057cbd4db0d6886ca1a4d33c912c 100644 (file)
@@ -159,7 +159,7 @@ perform a pull, and then unstash, like this:
 +
 ----------------------------------------------------------------
 $ git pull
-...
+ ...
 file foobar not up to date, cannot merge.
 $ git stash
 $ git pull
@@ -174,7 +174,7 @@ make a commit to a temporary branch to store your changes away, and
 return to your original branch to make the emergency fix, like this:
 +
 ----------------------------------------------------------------
-... hack hack hack ...
+... hack hack hack ...
 $ git checkout -b my_wip
 $ git commit -a -m "WIP"
 $ git checkout master
@@ -182,18 +182,18 @@ $ edit emergency fix
 $ git commit -a -m "Fix in a hurry"
 $ git checkout my_wip
 $ git reset --soft HEAD^
-... continue hacking ...
+... continue hacking ...
 ----------------------------------------------------------------
 +
 You can use 'git-stash' to simplify the above, like this:
 +
 ----------------------------------------------------------------
-... hack hack hack ...
+... hack hack hack ...
 $ git stash
 $ edit emergency fix
 $ git commit -a -m "Fix in a hurry"
 $ git stash apply
-... continue hacking ...
+... continue hacking ...
 ----------------------------------------------------------------
 
 Testing partial commits::
@@ -203,13 +203,13 @@ more commits out of the changes in the work tree, and you want to test
 each change before committing:
 +
 ----------------------------------------------------------------
-... hack hack hack ...
+... hack hack hack ...
 $ git add --patch foo            # add just first part to the index
 $ git stash save --keep-index    # save all other changes to the stash
 $ edit/build/test first part
-$ git commit foo -m 'First part' # commit fully tested change
+$ git commit -m 'First part'     # commit fully tested change
 $ git stash pop                  # prepare to work on all other changes
-... repeat above five steps until one commit remains ...
+... repeat above five steps until one commit remains ...
 $ edit/build/test remaining parts
 $ git commit foo -m 'Remaining parts'
 ----------------------------------------------------------------
index 3647dd6c8f9c74a688f7a143119386ba89a8f13d..e2f4c0901bcb4bcc5361e400ff40d70062c77ae6 100644 (file)
@@ -20,7 +20,7 @@ OPTIONS
        Cause the logical variables to be listed. In addition, all the
        variables of the git configuration file .git/config are listed
        as well. (However, the configuration variables listing functionality
-       is deprecated in favor of 'git-config -l'.)
+       is deprecated in favor of 'git config -l'.)
 
 EXAMPLE
 --------
@@ -41,9 +41,9 @@ Diagnostics
 You don't exist. Go away!::
     The passwd(5) gecos field couldn't be read
 Your parents must have hated you!::
-    The password(5) gecos field is longer than a giant static buffer.
+    The passwd(5) gecos field is longer than a giant static buffer.
 Your sysadmin must hate you!::
-    The password(5) name field is longer than a giant static buffer.
+    The passwd(5) name field is longer than a giant static buffer.
 
 SEE ALSO
 --------
index db16b0ca5b8146361a379de894a1394e0950fd38..49a167f241f0832e62fb905390715e45ef5be3c4 100644 (file)
@@ -7,7 +7,7 @@ gitattributes - defining attributes per path
 
 SYNOPSIS
 --------
-$GIT_DIR/info/attributes, gitattributes
+$GIT_DIR/info/attributes, .gitattributes
 
 
 DESCRIPTION
@@ -105,9 +105,8 @@ Set::
 
 Unset::
 
-       Unsetting the `crlf` attribute on a path is meant to
-       mark the path as a "binary" file.  The path never goes
-       through line endings conversion upon checkin/checkout.
+       Unsetting the `crlf` attribute on a path tells git not to
+       attempt any end-of-line conversion upon checkin or checkout.
 
 Unspecified::
 
@@ -482,6 +481,41 @@ in the file.  E.g. the string `$Format:%H$` will be replaced by the
 commit hash.
 
 
+USING ATTRIBUTE MACROS
+----------------------
+
+You do not want any end-of-line conversions applied to, nor textual diffs
+produced for, any binary file you track.  You would need to specify e.g.
+
+------------
+*.jpg -crlf -diff
+------------
+
+but that may become cumbersome, when you have many attributes.  Using
+attribute macros, you can specify groups of attributes set or unset at
+the same time.  The system knows a built-in attribute macro, `binary`:
+
+------------
+*.jpg binary
+------------
+
+which is equivalent to the above.  Note that the attribute macros can only
+be "Set" (see the above example that sets "binary" macro as if it were an
+ordinary attribute --- setting it in turn unsets "crlf" and "diff").
+
+
+DEFINING ATTRIBUTE MACROS
+-------------------------
+
+Custom attribute macros can be defined only in the `.gitattributes` file
+at the toplevel (i.e. not in any subdirectory).  The built-in attribute
+macro "binary" is equivalent to:
+
+------------
+[attr]binary -diff -crlf
+------------
+
+
 EXAMPLE
 -------
 
index f8d122a8b90ca7cb4920768ca23fd9a27574ffdf..d1a17e2625890245341a2099cc2b058e63564da2 100644 (file)
@@ -7,7 +7,7 @@ gitmodules - defining submodule properties
 
 SYNOPSIS
 --------
-gitmodules
+$GIT_WORK_DIR/.gitmodules
 
 
 DESCRIPTION
index fb0d7da56b902217f8f1f4d4bc85186d6bf0dc4c..d2970f8357505f5973989f2e118b812d3d3dde67 100644 (file)
@@ -21,7 +21,7 @@ project find it more convenient to use legacy encodings, git
 does not forbid it.  However, there are a few things to keep in
 mind.
 
-. 'git-commit-tree' (hence, 'git-commit' which uses it) issues
+. 'git-commit' and 'git-commit-tree' issues
   a warning if the commit log message given to it does not look
   like a valid UTF-8 string, unless you explicitly say your
   project uses a legacy encoding.  The way to say this is to
index 2cef0187d1d28ef2b466c1231499409f5cc1532f..672ea74233537ffce0e1b35a6ace6a06ece747ec 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -333,7 +333,6 @@ endif
 export PERL_PATH
 
 LIB_FILE=libgit.a
-COMPAT_LIB = compat/lib.a
 XDIFF_LIB=xdiff/lib.a
 
 LIB_H += archive.h
@@ -359,6 +358,7 @@ LIB_H += list-objects.h
 LIB_H += ll-merge.h
 LIB_H += log-tree.h
 LIB_H += mailmap.h
+LIB_H += merge-recursive.h
 LIB_H += object.h
 LIB_H += pack.h
 LIB_H += pack-refs.h
@@ -1099,7 +1099,10 @@ help.o: help.c common-cmds.h GIT-CFLAGS
                '-DGIT_INFO_PATH="$(infodir_SQ)"' $<
 
 $(BUILT_INS): git$X
-       $(QUIET_BUILT_IN)$(RM) $@ && ln git$X $@
+       $(QUIET_BUILT_IN)$(RM) $@ && \
+       ln git$X $@ 2>/dev/null || \
+       ln -s git$X $@ 2>/dev/null || \
+       cp git$X $@
 
 common-cmds.h: ./generate-cmdlist.sh command-list.txt
 
@@ -1224,12 +1227,6 @@ git-http-push$X: revision.o http.o http-push.o $(GITLIBS)
        $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \
                $(LIBS) $(CURL_LIBCURL) $(EXPAT_LIBEXPAT)
 
-$(COMPAT_LIB): $(COMPAT_OBJS)
-       $(QUIET_AR)$(RM) $@ && $(AR) rcs $@ $(COMPAT_OBJS)
-
-git-shell$X: abspath.o ctype.o exec_cmd.o quote.o strbuf.o usage.o wrapper.o shell.o $(COMPAT_LIB)
-       $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) $(COMPAT_LIB)
-
 $(LIB_OBJS) $(BUILTIN_OBJS): $(LIB_H)
 $(patsubst git-%$X,%.o,$(PROGRAMS)): $(LIB_H) $(wildcard */*.h)
 builtin-revert.o wt-status.o: wt-status.h
@@ -1364,16 +1361,13 @@ ifneq (,$X)
 endif
        bindir=$$(cd '$(DESTDIR_SQ)$(bindir_SQ)' && pwd) && \
        execdir=$$(cd '$(DESTDIR_SQ)$(gitexec_instdir_SQ)' && pwd) && \
-       if test "z$$bindir" != "z$$execdir"; \
-       then \
-               ln -f "$$bindir/git$X" "$$execdir/git$X" || \
-               cp "$$bindir/git$X" "$$execdir/git$X"; \
-       fi && \
-       { $(foreach p,$(BUILT_INS), $(RM) "$$execdir/$p" && ln "$$execdir/git$X" "$$execdir/$p" ;) } && \
-       if test "z$$bindir" != "z$$execdir"; \
-       then \
-               $(RM) "$$execdir/git$X"; \
-       fi && \
+       { $(RM) "$$execdir/git-add$X" && \
+               ln git-add$X "$$execdir/git-add$X" 2>/dev/null || \
+               cp git-add$X "$$execdir/git-add$X"; } && \
+       { $(foreach p,$(filter-out git-add$X,$(BUILT_INS)), $(RM) "$$execdir/$p" && \
+               ln "$$execdir/git-add$X" "$$execdir/$p" 2>/dev/null || \
+               ln -s "git-add$X" "$$execdir/$p" 2>/dev/null || \
+               cp "$$execdir/git-add$X" "$$execdir/$p" || exit;) } && \
        ./check_bindir "z$$bindir" "z$$execdir" "$$bindir/git-add$X"
 
 install-doc:
@@ -1442,7 +1436,7 @@ distclean: clean
 
 clean:
        $(RM) *.o mozilla-sha1/*.o arm/*.o ppc/*.o compat/*.o xdiff/*.o \
-               $(LIB_FILE) $(XDIFF_LIB) $(COMPAT_LIB)
+               $(LIB_FILE) $(XDIFF_LIB)
        $(RM) $(ALL_PROGRAMS) $(BUILT_INS) git$X
        $(RM) $(TEST_PROGRAMS)
        $(RM) *.spec *.pyc *.pyo */*.pyc */*.pyo common-cmds.h TAGS tags cscope*
index 4eb263ec5807a771b3a61c147b74a6f2f68dddee..20bef1f21d393b0ddf36b8336af85a70c9b8c39c 100644 (file)
@@ -1996,6 +1996,8 @@ static int apply_one_fragment(struct image *img, struct fragment *frag,
        /*
         * A hunk to change lines at the beginning would begin with
         * @@ -1,L +N,M @@
+        * but we need to be careful.  -U0 that inserts before the second
+        * line also has this pattern.
         *
         * And a hunk to add to an empty file would begin with
         * @@ -0,0 +N,M @@
@@ -2003,7 +2005,8 @@ static int apply_one_fragment(struct image *img, struct fragment *frag,
         * In other words, a hunk that is (frag->oldpos <= 1) with or
         * without leading context must match at the beginning.
         */
-       match_beginning = frag->oldpos <= 1;
+       match_beginning = (!frag->oldpos ||
+                          (frag->oldpos == 1 && !unidiff_zero));
 
        /*
         * A hunk without trailing lines must match at the end.
index 411cc513c65ba854221ad52dd6aeaaac7d213c9d..f6f8f086de980b5bc19ca59985a2b0d8201831d9 100644 (file)
@@ -386,13 +386,11 @@ static int switch_branches(struct checkout_opts *opts, struct branch_info *new)
        }
 
        /*
-        * If the new thing isn't a branch and isn't HEAD and we're
-        * not starting a new branch, and we want messages, and we
-        * weren't on a branch, and we're moving to a new commit,
-        * describe the old commit.
+        * If we were on a detached HEAD, but we are now moving to
+        * a new commit, we want to mention the old commit once more
+        * to remind the user that it might be lost.
         */
-       if (!new->path && strcmp(new->name, "HEAD") && !opts->new_branch &&
-           !opts->quiet && !old.path && new->commit != old.commit)
+       if (!opts->quiet && !old.path && new->commit != old.commit)
                describe_detached_head("Previous HEAD position was", old.commit);
 
        if (!old.commit) {
index c0e3086437ced05d1b81d4098e3a4c7c3031b0ee..c8435295cedd920f34a13ec686c73d6b835b28ee 100644 (file)
@@ -147,6 +147,15 @@ static int is_directory(const char *path)
        return !stat(path, &buf) && S_ISDIR(buf.st_mode);
 }
 
+static void strip_trailing_slashes(char *dir)
+{
+       char *end = dir + strlen(dir);
+
+       while (dir < end - 1 && is_dir_sep(end[-1]))
+               end--;
+       *end = '\0';
+}
+
 static void setup_reference(const char *repo)
 {
        const char *ref_git;
@@ -387,7 +396,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
 
        path = get_repo_path(repo_name, &is_bundle);
        if (path)
-               repo = path;
+               repo = xstrdup(make_nonrelative_path(repo_name));
        else if (!strchr(repo_name, ':'))
                repo = xstrdup(make_absolute_path(repo_name));
        else
@@ -397,6 +406,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
                dir = xstrdup(argv[1]);
        else
                dir = guess_dir_name(repo_name, is_bundle, option_bare);
+       strip_trailing_slashes(dir);
 
        if (!stat(dir, &buf))
                die("destination directory '%s' already exists.", dir);
@@ -422,10 +432,11 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
        if (!option_bare) {
                junk_work_tree = work_tree;
                if (safe_create_leading_directories_const(work_tree) < 0)
-                       die("could not create leading directories of '%s'",
-                                       work_tree);
+                       die("could not create leading directories of '%s': %s",
+                                       work_tree, strerror(errno));
                if (mkdir(work_tree, 0755))
-                       die("could not create work tree dir '%s'.", work_tree);
+                       die("could not create work tree dir '%s': %s.",
+                                       work_tree, strerror(errno));
                set_git_work_tree(work_tree);
        }
        junk_git_dir = git_dir;
index d394c494a55d45a7af6506371f3432374dffe424..ef3befe57b3b8298798e51627f076e2a40319cb1 100644 (file)
@@ -1095,9 +1095,12 @@ static void check_object(struct object_entry *entry)
        }
 
        entry->type = sha1_object_info(entry->idx.sha1, &entry->size);
-       if (entry->type < 0)
-               die("unable to get type of object %s",
-                   sha1_to_hex(entry->idx.sha1));
+       /*
+        * The error condition is checked in prepare_pack().  This is
+        * to permit a missing preferred base object to be ignored
+        * as a preferred base.  Doing so can result in a larger
+        * pack file, but the transfer will still take place.
+        */
 }
 
 static int pack_offset_sort(const void *_a, const void *_b)
@@ -1721,8 +1724,12 @@ static void prepare_pack(int window, int depth)
                if (entry->no_try_delta)
                        continue;
 
-               if (!entry->preferred_base)
+               if (!entry->preferred_base) {
                        nr_deltas++;
+                       if (entry->type < 0)
+                               die("unable to get type of object %s",
+                                   sha1_to_hex(entry->idx.sha1));
+               }
 
                delta_list[n++] = entry;
        }
index f4ac595695b1fff1317ff7d14ea9427780327aea..25a29f11a4b9642c1bd367b81779d8f09ae04604 100644 (file)
@@ -1,7 +1,7 @@
 #include "builtin.h"
 #include "cache.h"
 #include "pack.h"
-
+#include "pack-revindex.h"
 
 #define MAX_CHAIN 50
 
@@ -129,6 +129,7 @@ int cmd_verify_pack(int argc, const char **argv, const char *prefix)
                else {
                        if (verify_one_pack(argv[1], verbose))
                                err = 1;
+                       discard_revindex();
                        nothing_done = 0;
                }
                argc--; argv++;
index cd300bdff5b524a4d509ba5276e9ef21f443013d..6096b6224ad551086afa346617eb714c15a51f78 100644 (file)
@@ -142,3 +142,15 @@ struct revindex_entry *find_pack_revindex(struct packed_git *p, off_t ofs)
        } while (lo < hi);
        die("internal error: pack revindex corrupt");
 }
+
+void discard_revindex(void)
+{
+       if (pack_revindex_hashsz) {
+               int i;
+               for (i = 0; i < pack_revindex_hashsz; i++)
+                       if (pack_revindex[i].revindex)
+                               free(pack_revindex[i].revindex);
+               free(pack_revindex);
+               pack_revindex_hashsz = 0;
+       }
+}
index 36a514a6cf600e7e77794e50998a9d160e30c8e9..8d5027ad917224f689e786e9a0b4e9a387e59dfe 100644 (file)
@@ -7,5 +7,6 @@ struct revindex_entry {
 };
 
 struct revindex_entry *find_pack_revindex(struct packed_git *p, off_t ofs);
+void discard_revindex(void);
 
 #endif
index 32e4664b1b52542bbd77218a4b88cef610f49649..477d3fb4b06bcbcdd3f75a9e48d5945f91e1f3e6 100644 (file)
@@ -990,6 +990,7 @@ void prepare_packed_git(void)
 
 void reprepare_packed_git(void)
 {
+       discard_revindex();
        prepare_packed_git_run_once = 0;
        prepare_packed_git();
 }
diff --git a/shell.c b/shell.c
index ad60200d28e9957f54a34435f5dc59fce412666c..e3393690dd3b79af80e6b95710583e744fd574d4 100644 (file)
--- a/shell.c
+++ b/shell.c
@@ -3,14 +3,6 @@
 #include "exec_cmd.h"
 #include "strbuf.h"
 
-/* Stubs for functions that make no sense for git-shell. These stubs
- * are provided here to avoid linking in external redundant modules.
- */
-void release_pack_memory(size_t need, int fd){}
-void trace_argv_printf(const char **argv, const char *fmt, ...){}
-void trace_printf(const char *fmt, ...){}
-
-
 static int do_generic_cmd(const char *me, char *arg)
 {
        const char *my_argv[4];
index b6777812cb92c1c169ee395164d53a0c2e6eceb2..cca3360546dabf9f018b882f690bd1dea9de534d 100644 (file)
@@ -25,6 +25,7 @@ int recv_sideband(const char *me, int in_stream, int out, int err)
        unsigned sf;
        char buf[LARGE_PACKET_MAX + 2*FIX_SIZE];
        char *suffix, *term;
+       int skip_pf = 0;
 
        memcpy(buf, PREFIX, pf);
        term = getenv("TERM");
@@ -54,39 +55,58 @@ int recv_sideband(const char *me, int in_stream, int out, int err)
                        return SIDEBAND_REMOTE_ERROR;
                case 2:
                        buf[pf] = ' ';
-                       len += pf+1;
-                       while (1) {
-                               int brk = pf+1;
+                       do {
+                               char *b = buf;
+                               int brk = 0;
 
-                               /* Break the buffer into separate lines. */
-                               while (brk < len) {
+                               /*
+                                * If the last buffer didn't end with a line
+                                * break then we should not print a prefix
+                                * this time around.
+                                */
+                               if (skip_pf) {
+                                       b += pf+1;
+                               } else {
+                                       len += pf+1;
+                                       brk += pf+1;
+                               }
+
+                               /* Look for a line break. */
+                               for (;;) {
                                        brk++;
-                                       if (buf[brk-1] == '\n' ||
-                                           buf[brk-1] == '\r')
+                                       if (brk > len) {
+                                               brk = 0;
+                                               break;
+                                       }
+                                       if (b[brk-1] == '\n' ||
+                                           b[brk-1] == '\r')
                                                break;
                                }
 
                                /*
                                 * Let's insert a suffix to clear the end
-                                * of the screen line, but only if current
-                                * line data actually contains something.
+                                * of the screen line if a line break was
+                                * found.  Also, if we don't skip the
+                                * prefix, then a non-empty string must be
+                                * present too.
                                 */
-                               if (brk > pf+1 + 1) {
+                               if (brk > (skip_pf ? 0 : (pf+1 + 1))) {
                                        char save[FIX_SIZE];
-                                       memcpy(save, buf + brk, sf);
-                                       buf[brk + sf - 1] = buf[brk - 1];
-                                       memcpy(buf + brk - 1, suffix, sf);
-                                       safe_write(err, buf, brk + sf);
-                                       memcpy(buf + brk, save, sf);
-                               } else
-                                       safe_write(err, buf, brk);
+                                       memcpy(save, b + brk, sf);
+                                       b[brk + sf - 1] = b[brk - 1];
+                                       memcpy(b + brk - 1, suffix, sf);
+                                       safe_write(err, b, brk + sf);
+                                       memcpy(b + brk, save, sf);
+                                       len -= brk;
+                               } else {
+                                       int l = brk ? brk : len;
+                                       safe_write(err, b, l);
+                                       len -= l;
+                               }
 
-                               if (brk < len) {
-                                       memmove(buf + pf+1, buf + brk, len - brk);
-                                       len = len - brk + pf+1;
-                               } else
-                                       break;
-                       }
+                               skip_pf = !brk;
+                               memmove(buf + pf+1, b + brk, len);
+                       } while (len);
                        continue;
                case 1:
                        safe_write(out, buf + pf+1, len);
index e7e2913de745cc9f7639103757933f6238fdd564..0e3ce3611d9e83ab290ce034f2439961864ce30a 100755 (executable)
@@ -27,6 +27,15 @@ test_expect_success setup '
        git diff victim >add-a-patch.with &&
        git diff --unified=0 >add-a-patch.without &&
 
+       : insert at line two
+       for i in b a '"$L"' y
+       do
+               echo $i
+       done >victim &&
+       cat victim >insert-a-expect &&
+       git diff victim >insert-a-patch.with &&
+       git diff --unified=0 >insert-a-patch.without &&
+
        : modify at the head
        for i in a '"$L"' y
        do
@@ -55,7 +64,7 @@ test_expect_success setup '
        git diff --unified=0 >add-z-patch.without &&
 
        : modify at the tail
-       for i in a '"$L"' y
+       for i in b '"$L"' z
        do
                echo $i
        done >victim &&
@@ -81,7 +90,7 @@ do
        with) u= ;;
        without) u='--unidiff-zero ' ;;
        esac
-       for kind in add-a add-z mod-a mod-z del-a del-z
+       for kind in add-a add-z insert-a mod-a mod-z del-a del-z
        do
                test_expect_success "apply $kind-patch $with context" '
                        cat original >victim &&
@@ -95,7 +104,7 @@ do
        done
 done
 
-for kind in add-a add-z mod-a mod-z del-a del-z
+for kind in add-a add-z insert-a mod-a mod-z del-a del-z
 do
        rm -f $kind-ng.without
        sed     -e "s/^diff --git /diff /" \
index 482bc7ae6842ccf082f05f65c691d001cad2b148..3a0ef8759c9d7a55b95c56ca38cd3c37ac2432fa 100755 (executable)
@@ -186,6 +186,12 @@ test_expect_success \
                        test-2-${packname_2}.idx \
                        test-3-${packname_3}.idx'
 
+test_expect_success \
+    'verify pack -v' \
+    'git verify-pack -v        test-1-${packname_1}.idx \
+                       test-2-${packname_2}.idx \
+                       test-3-${packname_3}.idx'
+
 test_expect_success \
     'verify-pack catches mismatched .idx and .pack files' \
     'cat test-1-${packname_1}.idx >test-3.idx &&
diff --git a/t/t5306-pack-nobase.sh b/t/t5306-pack-nobase.sh
new file mode 100755 (executable)
index 0000000..f4931c0
--- /dev/null
@@ -0,0 +1,80 @@
+#!/bin/sh
+#
+# Copyright (c) 2008 Google Inc.
+#
+
+test_description='git-pack-object with missing base
+
+'
+. ./test-lib.sh
+
+# Create A-B chain
+#
+test_expect_success \
+    'setup base' \
+    'for a in a b c d e f g h i; do echo $a >>text; done &&
+     echo side >side &&
+     git update-index --add text side &&
+     A=$(echo A | git commit-tree $(git write-tree)) &&
+
+     echo m >>text &&
+     git update-index text &&
+     B=$(echo B | git commit-tree $(git write-tree) -p $A) &&
+     git update-ref HEAD $B
+    '
+
+# Create repository with C whose parent is B.
+# Repository contains C, C^{tree}, C:text, B, B^{tree}.
+# Repository is missing B:text (best delta base for C:text).
+# Repository is missing A (parent of B).
+# Repository is missing A:side.
+#
+test_expect_success \
+    'setup patch_clone' \
+    'base_objects=$(pwd)/.git/objects &&
+     (mkdir patch_clone &&
+      cd patch_clone &&
+      git init &&
+      echo "$base_objects" >.git/objects/info/alternates &&
+      echo q >>text &&
+      git read-tree $B &&
+      git update-index text &&
+      git update-ref HEAD $(echo C | git commit-tree $(git write-tree) -p $B) &&
+      rm .git/objects/info/alternates &&
+
+      git --git-dir=../.git cat-file commit $B |
+      git hash-object -t commit -w --stdin &&
+
+      git --git-dir=../.git cat-file tree "$B^{tree}" |
+      git hash-object -t tree -w --stdin
+     ) &&
+     C=$(git --git-dir=patch_clone/.git rev-parse HEAD)
+    '
+
+# Clone patch_clone indirectly by cloning base and fetching.
+#
+test_expect_success \
+    'indirectly clone patch_clone' \
+    '(mkdir user_clone &&
+      cd user_clone &&
+      git init &&
+      git pull ../.git &&
+      test $(git rev-parse HEAD) = $B &&
+
+      git pull ../patch_clone/.git &&
+      test $(git rev-parse HEAD) = $C
+     )
+    '
+
+# Cloning the patch_clone directly should fail.
+#
+test_expect_success \
+    'clone of patch_clone is incomplete' \
+    '(mkdir user_direct &&
+      cd user_direct &&
+      git init &&
+      test_must_fail git fetch ../patch_clone/.git
+     )
+    '
+
+test_done
index be9ee9326fc4590dcc875e31b6cf64b800451bc5..c4496635dfba85b0e9fc105c4516096d433881a4 100755 (executable)
@@ -109,7 +109,7 @@ test_expect_success 'remove remote' '
 
 cat > test/expect << EOF
 * remote origin
-  URL: $(pwd)/one/.git
+  URL: $(pwd)/one
   Remote branch merged with 'git pull' while on branch master
     master
   New remote branch (next fetch will store in remotes/origin)
@@ -140,7 +140,7 @@ test_expect_success 'show' '
 
 cat > test/expect << EOF
 * remote origin
-  URL: $(pwd)/one/.git
+  URL: $(pwd)/one
   Remote branch merged with 'git pull' while on branch master
     master
   Tracked remote branches
@@ -169,7 +169,7 @@ test_expect_success 'prune' '
 
 cat > test/expect << EOF
 Pruning origin
-URL: $(pwd)/one/.git
+URL: $(pwd)/one
  * [would prune] origin/side2
 EOF
 
index 59c65fef286ad8d52a15c942f6975607f0347f66..78a3fa639c97b7dce054d89c74c67a855d0d7954 100755 (executable)
@@ -107,4 +107,22 @@ test_expect_success 'clone --mirror does not repeat tags' '
 
 '
 
+test_expect_success 'clone to destination with trailing /' '
+
+       git clone src target-1/ &&
+       T=$( cd target-1 && git rev-parse HEAD ) &&
+       S=$( cd src && git rev-parse HEAD ) &&
+       test "$T" = "$S"
+
+'
+
+test_expect_success 'clone to destination with extra trailing /' '
+
+       git clone src target-2/// &&
+       T=$( cd target-2 && git rev-parse HEAD ) &&
+       S=$( cd src && git rev-parse HEAD ) &&
+       test "$T" = "$S"
+
+'
+
 test_done