]> asedeno.scripts.mit.edu Git - git.git/commitdiff
Merge branch 'rr/cvsexport'
authorJunio C Hamano <junkio@cox.net>
Tue, 29 May 2007 07:37:23 +0000 (00:37 -0700)
committerJunio C Hamano <junkio@cox.net>
Tue, 29 May 2007 07:37:23 +0000 (00:37 -0700)
* rr/cvsexport:
  Add option to cvs update before export

24 files changed:
Documentation/git-cvsserver.txt
Documentation/git-ls-files.txt
Documentation/glossary.txt
Documentation/user-manual.txt
Makefile
builtin-mailsplit.c
builtin-pack-refs.c
contrib/workdir/git-new-workdir
convert.c
diff.c
git-am.sh
git-commit.sh
git-cvsserver.perl
git-gui/Makefile
git-gui/git-gui.sh
git-merge.sh
git-svn.perl
git-tag.sh
pack-check.c
t/t0021-conversion.sh
t/t4014-format-patch.sh
t/t9112-git-svn-md5less-file.sh [new file with mode: 0755]
t/t9400-git-cvsserver-server.sh
tag.c

index d22844ba49859b9a189317744e0f14431267e60a..e5005f02f997437da3251f6c52c6efbdf06557b4 100644 (file)
@@ -46,16 +46,28 @@ INSTALLATION
    cvspserver stream tcp nowait nobody git-cvsserver pserver
 
 ------
-Note: In some cases, you need to pass the 'pserver' argument twice for
-git-cvsserver to see it. So the line would look like
+Note: Some inetd servers let you specify the name of the executable
+independently of the value of argv[0] (i.e. the name the program assumes
+it was executed with). In this case the correct line in /etc/inetd.conf
+looks like
 
 ------
-   cvspserver stream tcp nowait nobody git-cvsserver pserver pserver
+   cvspserver stream tcp nowait nobody /usr/bin/git-cvsserver git-cvsserver pserver
 
 ------
 No special setup is needed for SSH access, other than having GIT tools
 in the PATH. If you have clients that do not accept the CVS_SERVER
-env variable, you can rename git-cvsserver to cvs.
+environment variable, you can rename git-cvsserver to cvs.
+
+Note: Newer cvs versions (>= 1.12.11) also support specifying
+CVS_SERVER directly in CVSROOT like
+
+------
+cvs -d ":ext;CVS_SERVER=git-cvsserver:user@server/path/repo.git" co <HEAD_name>
+------
+This has the advantage that it will be saved in your 'CVS/Root' files and
+you don't need to worry about always setting the correct environment
+variable.
 --
 2. For each repo that you want accessible from CVS you need to edit config in
    the repo and add the following section.
@@ -74,7 +86,7 @@ write access to the log file and to the database (see
 SSH, the users of course also need write access to the git repository itself.
 
 [[configaccessmethod]]
-All configuration variables can also be overriden for a specific method of
+All configuration variables can also be overridden for a specific method of
 access. Valid method names are "ext" (for SSH access) and "pserver". The
 following example configuration would disable pserver access while still
 allowing access over SSH.
@@ -116,7 +128,7 @@ Database Backend
 
 git-cvsserver uses one database per git head (i.e. CVS module) to
 store information about the repository for faster access. The
-database doesn't contain any persitent data and can be completly
+database doesn't contain any persistent data and can be completely
 regenerated from the git repository at any time. The database
 needs to be updated (i.e. written to) after every commit.
 
index 076cebca1747ed8e35b71aefa2cae9d428a0d1e4..43e0d2266c04e6039095dbee709d736275b02838 100644 (file)
@@ -124,7 +124,7 @@ which case it outputs:
 detailed information on unmerged paths.
 
 For an unmerged path, instead of recording a single mode/SHA1 pair,
-the dircache records up to three such pairs; one from tree O in stage
+the index records up to three such pairs; one from tree O in stage
 1, A in stage 2, and B in stage 3.  This information can be used by
 the user (or the porcelain) to see what should eventually be recorded at the
 path. (see git-read-tree for more information on state)
index 489c3e9d5bacab14fdd0c6fec0aaca65b5efc3a4..e903abfeb874f3d185bbf26e21b2ce529084b305 100644 (file)
@@ -10,7 +10,7 @@ GIT Glossary
        A bare repository is normally an appropriately
        named <<def_directory,directory>> with a `.git` suffix that does not
        have a locally checked-out copy of any of the files under
-       <<def_revision,revision>> control. That is, all of the `git`
+       revision control. That is, all of the `git`
        administrative and control files that would normally be present in the
        hidden `.git` sub-directory are directly present in the
        `repository.git` directory instead,
@@ -37,7 +37,7 @@ GIT Glossary
 [[def_chain]]chain::
        A list of objects, where each <<def_object,object>> in the list contains
        a reference to its successor (for example, the successor of a
-       <<def_commit,commit>> could be one of its parents).
+       <<def_commit,commit>> could be one of its <<def_parent,parents>>).
 
 [[def_changeset]]changeset::
        BitKeeper/cvsps speak for "<<def_commit,commit>>". Since git does not
@@ -77,10 +77,10 @@ to point at the new commit.
 
 [[def_commit_object]]commit object::
        An <<def_object,object>> which contains the information about a
-       particular <<def_revision,revision>>, such as parents, committer,
+       particular <<def_revision,revision>>, such as <<def_parent,parents>>, committer,
        author, date and the <<def_tree_object,tree object>> which corresponds
        to the top <<def_directory,directory>> of the stored
-       <<def_revision,revision>>.
+       revision.
 
 [[def_core_git]]core git::
        Fundamental data structures and utilities of git. Exposes only limited
@@ -101,19 +101,19 @@ to point at the new commit.
 
 [[def_detached_HEAD]]detached HEAD::
        Normally the <<def_HEAD,HEAD>> stores the name of a
-       <<def_branch,branch>>.  However, git also allows you to check
-       out an arbitrary commit that isn't necessarily the tip of any
+       <<def_branch,branch>>.  However, git also allows you to <<def_checkout,check out>>
+       an arbitrary <<def_commit,commit>> that isn't necessarily the tip of any
        particular branch.  In this case HEAD is said to be "detached".
 
 [[def_dircache]]dircache::
-       You are *waaaaay* behind.
+       You are *waaaaay* behind. See <<def_index,index>>.
 
 [[def_directory]]directory::
        The list you get with "ls" :-)
 
 [[def_dirty]]dirty::
        A <<def_working_tree,working tree>> is said to be "dirty" if
-       it contains modifications which have not been committed to the current
+       it contains modifications which have not been <<def_commit,committed>> to the current
        <<def_branch,branch>>.
 
 [[def_ent]]ent::
@@ -121,6 +121,10 @@ to point at the new commit.
        `http://en.wikipedia.org/wiki/Ent_(Middle-earth)` for an in-depth
        explanation. Avoid this term, not to confuse people.
 
+[[def_evil_merge]]evil merge::
+       An evil merge is a <<def_merge,merge>> that introduces changes that
+       do not appear in any <<def_parent,parent>>.
+
 [[def_fast_forward]]fast forward::
        A fast-forward is a special type of <<def_merge,merge>> where you have a
        <<def_revision,revision>> and you are "merging" another
@@ -149,7 +153,7 @@ to point at the new commit.
 [[def_grafts]]grafts::
        Grafts enables two otherwise different lines of development to be joined
        together by recording fake ancestry information for commits. This way
-       you can make git pretend the set of parents a <<def_commit,commit>> has
+       you can make git pretend the set of <<def_parent,parents>> a <<def_commit,commit>> has
        is different from what was recorded when the commit was
        created. Configured via the `.git/info/grafts` file.
 
@@ -157,13 +161,13 @@ to point at the new commit.
        In git's context, synonym to <<def_object_name,object name>>.
 
 [[def_head]]head::
-       A named reference to the <<def_commit,commit>> at the tip of a
+       A <<def_ref,named reference>> to the <<def_commit,commit>> at the tip of a
        <<def_branch,branch>>.  Heads are stored in
        `$GIT_DIR/refs/heads/`, except when using packed refs. (See
        gitlink:git-pack-refs[1].)
 
 [[def_HEAD]]HEAD::
-       The current branch.  In more detail: Your <<def_working_tree,
+       The current <<def_branch,branch>>.  In more detail: Your <<def_working_tree,
        working tree>> is normally derived from the state of the tree
        referred to by HEAD.  HEAD is a reference to one of the
        <<def_head,heads>> in your repository, except when using a
@@ -179,15 +183,15 @@ to point at the new commit.
        checking. Typically, the hooks allow for a command to be pre-verified
        and potentially aborted, and allow for a post-notification after the
        operation is done. The hook scripts are found in the
-       `$GIT_DIR/hooks/` <<def_directory,directory>>, and are enabled by simply
+       `$GIT_DIR/hooks/` directory, and are enabled by simply
        making them executable.
 
 [[def_index]]index::
        A collection of files with stat information, whose contents are stored
-       as objects. The index is a stored version of your working
-       <<def_tree,tree>>. Truth be told, it can also contain a second, and even
-       a third version of a <<def_working_tree,working tree>>, which are used
-       when merging.
+       as objects. The index is a stored version of your
+       <<def_working_tree,working tree>>. Truth be told, it can also contain a second, and even
+       a third version of a working tree, which are used
+       when <<def_merge,merging>>.
 
 [[def_index_entry]]index entry::
        The information regarding a particular file, stored in the
@@ -249,16 +253,16 @@ This commit is referred to as a "merge commit", or sometimes just a
        describing the type of an <<def_object,object>>.
 
 [[def_octopus]]octopus::
-       To <<def_merge,merge>> more than two branches. Also denotes an
+       To <<def_merge,merge>> more than two <<def_branch,branches>>. Also denotes an
        intelligent predator.
 
 [[def_origin]]origin::
        The default upstream <<def_repository,repository>>. Most projects have
        at least one upstream project which they track. By default
        'origin' is used for that purpose. New upstream updates
-       will be fetched into remote tracking branches named
+       will be fetched into remote <<def_tracking_branch,tracking branches>> named
        origin/name-of-upstream-branch, which you can see using
-       "git <<def_branch,branch>> -r".
+       "`git branch -r`".
 
 [[def_pack]]pack::
        A set of objects which have been compressed into one file (to save space
@@ -327,7 +331,7 @@ This commit is referred to as a "merge commit", or sometimes just a
        `$GIT_DIR/refs/`.
 
 [[def_refspec]]refspec::
-       A <<def_refspec,refspec>> is used by <<def_fetch,fetch>> and
+       A "refspec" is used by <<def_fetch,fetch>> and
        <<def_push,push>> to describe the mapping between remote
        <<def_ref,ref>> and local ref. They are combined with a colon in
        the format <src>:<dst>, preceded by an optional plus sign, +.
@@ -340,11 +344,12 @@ This commit is referred to as a "merge commit", or sometimes just a
        gitlink:git-push[1]
 
 [[def_repository]]repository::
-       A collection of refs together with an
+       A collection of <<def_ref,refs>> together with an
        <<def_object_database,object database>> containing all objects
        which are <<def_reachable,reachable>> from the refs, possibly
-       accompanied by meta data from one or more porcelains. A
-       repository can share an object database with other repositories.
+       accompanied by meta data from one or more <<def_porcelain,porcelains>>. A
+       repository can share an object database with other repositories
+       via <<def_alternate_object_database,alternates mechanism>>.
 
 [[def_resolve]]resolve::
        The action of fixing up manually what a failed automatic
@@ -366,8 +371,8 @@ This commit is referred to as a "merge commit", or sometimes just a
        Synonym for <<def_object_name,object name>>.
 
 [[def_shallow_repository]]shallow repository::
-       A shallow repository has an incomplete
-       history some of whose commits have parents cauterized away (in other
+       A shallow <<def_repository,repository>> has an incomplete
+       history some of whose <<def_commit,commits>> have <<def_parent,parents>> cauterized away (in other
        words, git is told to pretend that these commits do not have the
        parents, even though they are recorded in the <<def_commit_object,commit
        object>>). This is sometimes useful when you are interested only in the
@@ -385,7 +390,7 @@ This commit is referred to as a "merge commit", or sometimes just a
        command.
 
 [[def_tag]]tag::
-       A <<def_ref,ref>> pointing to a tag or
+       A <<def_ref,ref>> pointing to a <<def_tag_object,tag>> or
        <<def_commit_object,commit object>>. In contrast to a <<def_head,head>>,
        a tag is not changed by a <<def_commit,commit>>. Tags (not
        <<def_tag_object,tag objects>>) are stored in `$GIT_DIR/refs/tags/`. A
@@ -398,8 +403,7 @@ This commit is referred to as a "merge commit", or sometimes just a
        An <<def_object,object>> containing a <<def_ref,ref>> pointing to
        another object, which can contain a message just like a
        <<def_commit_object,commit object>>. It can also contain a (PGP)
-       signature, in which case it is called a "signed <<def_tag_object,tag
-       object>>".
+       signature, in which case it is called a "signed tag object".
 
 [[def_topic_branch]]topic branch::
        A regular git <<def_branch,branch>> that is used by a developer to
@@ -418,7 +422,7 @@ This commit is referred to as a "merge commit", or sometimes just a
 
 [[def_tree]]tree::
        Either a <<def_working_tree,working tree>>, or a <<def_tree_object,tree
-       object>> together with the dependent blob and tree objects
+       object>> together with the dependent <<def_blob_object,blob>> and tree objects
        (i.e. a stored representation of a working tree).
 
 [[def_tree_object]]tree object::
index 52247aa7134345e94b3c2cc131d33224073f6eeb..4fabb8e2a9e601c82b55ac25b1b9d8cfb9a06d3a 100644 (file)
@@ -872,7 +872,7 @@ Obviously, endless variations are possible; for example, to see all
 commits reachable from some head but not from any tag in the repository:
 
 -------------------------------------------------
-$ gitk ($ git show-ref --heads ) --not  $( git show-ref --tags )
+$ gitk $( git show-ref --heads ) --not  $( git show-ref --tags )
 -------------------------------------------------
 
 (See gitlink:git-rev-parse[1] for explanations of commit-selecting
index 29243c6e8b49958ddcb08df0eb4223b14fd3e19f..fb11fa1987e162c13a9fba492da41e26fdad7195 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -235,7 +235,7 @@ endif
 
 # ... and all the rest that could be moved out of bindir to gitexecdir
 PROGRAMS = \
-       git-convert-objects$X git-fetch-pack$X git-fsck$X \
+       git-convert-objects$X git-fetch-pack$X \
        git-hash-object$X git-index-pack$X git-local-fetch$X \
        git-fast-import$X \
        git-merge-base$X \
@@ -246,7 +246,7 @@ PROGRAMS = \
        git-show-index$X git-ssh-fetch$X \
        git-ssh-upload$X git-unpack-file$X \
        git-update-server-info$X \
-       git-upload-pack$X git-verify-pack$X \
+       git-upload-pack$X \
        git-pack-redundant$X git-var$X \
        git-merge-tree$X git-imap-send$X \
        git-merge-recursive$X \
index 97ae004ab7939f565733e463a2b53afd63eff9df..c9384255551f316f2416ce49372b820a6d8e3632 100644 (file)
@@ -261,7 +261,8 @@ int cmd_mailsplit(int argc, const char **argv, const char *prefix)
                                error("cannot split patches from stdin");
                                return 1;
                        }
-                       num += ret;
+                       num += (ret - nr);
+                       nr = ret;
                        continue;
                }
 
@@ -279,7 +280,8 @@ int cmd_mailsplit(int argc, const char **argv, const char *prefix)
                        error("cannot split patches from %s", arg);
                        return 1;
                }
-               num += ret;
+               num += (ret - nr);
+               nr = ret;
        }
 
        printf("%d\n", num);
index d080e30d67a913529d46e0da169faa4b0be75580..1952950c9a4bf13dc728bb8d6a79493dad36df06 100644 (file)
@@ -12,9 +12,11 @@ struct ref_to_prune {
        char name[FLEX_ARRAY];
 };
 
+#define PACK_REFS_PRUNE        0x0001
+#define PACK_REFS_ALL  0x0002
+
 struct pack_refs_cb_data {
-       int prune;
-       int all;
+       unsigned int flags;
        struct ref_to_prune *ref_to_prune;
        FILE *refs_file;
 };
@@ -39,7 +41,7 @@ static int handle_one_ref(const char *path, const unsigned char *sha1,
        is_tag_ref = !prefixcmp(path, "refs/tags/");
 
        /* ALWAYS pack refs that were already packed or are tags */
-       if (!cb->all && !is_tag_ref && !(flags & REF_ISPACKED))
+       if (!(cb->flags & PACK_REFS_ALL) && !is_tag_ref && !(flags & REF_ISPACKED))
                return 0;
 
        fprintf(cb->refs_file, "%s %s\n", sha1_to_hex(sha1), path);
@@ -53,7 +55,7 @@ static int handle_one_ref(const char *path, const unsigned char *sha1,
                }
        }
 
-       if (cb->prune && !do_not_prune(flags)) {
+       if ((cb->flags & PACK_REFS_PRUNE) && !do_not_prune(flags)) {
                int namelen = strlen(path) + 1;
                struct ref_to_prune *n = xcalloc(1, sizeof(*n) + namelen);
                hashcpy(n->sha1, sha1);
@@ -85,26 +87,51 @@ static void prune_refs(struct ref_to_prune *r)
 
 static struct lock_file packed;
 
-int cmd_pack_refs(int argc, const char **argv, const char *prefix)
+static int pack_refs(unsigned int flags)
 {
-       int fd, i;
+       int fd;
        struct pack_refs_cb_data cbdata;
 
        memset(&cbdata, 0, sizeof(cbdata));
+       cbdata.flags = flags;
+
+       fd = hold_lock_file_for_update(&packed, git_path("packed-refs"), 1);
+       cbdata.refs_file = fdopen(fd, "w");
+       if (!cbdata.refs_file)
+               die("unable to create ref-pack file structure (%s)",
+                   strerror(errno));
+
+       /* perhaps other traits later as well */
+       fprintf(cbdata.refs_file, "# pack-refs with: peeled \n");
+
+       for_each_ref(handle_one_ref, &cbdata);
+       if (fflush(cbdata.refs_file) || fsync(fd) || fclose(cbdata.refs_file))
+               die("failed to write ref-pack file (%s)", strerror(errno));
+       if (commit_lock_file(&packed) < 0)
+               die("unable to overwrite old ref-pack file (%s)", strerror(errno));
+       if (cbdata.flags & PACK_REFS_PRUNE)
+               prune_refs(cbdata.ref_to_prune);
+       return 0;
+}
 
-       cbdata.prune = 1;
+int cmd_pack_refs(int argc, const char **argv, const char *prefix)
+{
+       int i;
+       unsigned int flags;
+
+       flags = PACK_REFS_PRUNE;
        for (i = 1; i < argc; i++) {
                const char *arg = argv[i];
                if (!strcmp(arg, "--prune")) {
-                       cbdata.prune = 1; /* now the default */
+                       flags |= PACK_REFS_PRUNE; /* now the default */
                        continue;
                }
                if (!strcmp(arg, "--no-prune")) {
-                       cbdata.prune = 0;
+                       flags &= ~PACK_REFS_PRUNE;
                        continue;
                }
                if (!strcmp(arg, "--all")) {
-                       cbdata.all = 1;
+                       flags |= PACK_REFS_ALL;
                        continue;
                }
                /* perhaps other parameters later... */
@@ -113,22 +140,5 @@ int cmd_pack_refs(int argc, const char **argv, const char *prefix)
        if (i != argc)
                usage(builtin_pack_refs_usage);
 
-       fd = hold_lock_file_for_update(&packed, git_path("packed-refs"), 1);
-       cbdata.refs_file = fdopen(fd, "w");
-       if (!cbdata.refs_file)
-               die("unable to create ref-pack file structure (%s)",
-                   strerror(errno));
-
-       /* perhaps other traits later as well */
-       fprintf(cbdata.refs_file, "# pack-refs with: peeled \n");
-
-       for_each_ref(handle_one_ref, &cbdata);
-       fflush(cbdata.refs_file);
-       fsync(fd);
-       fclose(cbdata.refs_file);
-       if (commit_lock_file(&packed) < 0)
-               die("unable to overwrite old ref-pack file (%s)", strerror(errno));
-       if (cbdata.prune)
-               prune_refs(cbdata.ref_to_prune);
-       return 0;
+       return pack_refs(flags);
 }
index 9877b98508497c9377876bd08e8f130660b9ba05..f2a3615bbc44ed4edbee4014683621a91c1a7ab9 100755 (executable)
@@ -20,17 +20,19 @@ new_workdir=$2
 branch=$3
 
 # want to make sure that what is pointed to has a .git directory ...
-test -d "$orig_git/.git" || die "\"$orig_git\" is not a git repository!"
+git_dir=$(cd "$orig_git" 2>/dev/null &&
+  git rev-parse --git-dir 2>/dev/null) ||
+  die "\"$orig_git\" is not a git repository!"
 
 # don't link to a workdir
-if test -L "$orig_git/.git/config"
+if test -L "$git_dir/config"
 then
        die "\"$orig_git\" is a working directory only, please specify" \
                "a complete repository."
 fi
 
 # make sure the the links use full paths
-orig_git=$(cd "$orig_git"; pwd)
+git_dir=$(cd "$git_dir"; pwd)
 
 # create the workdir
 mkdir -p "$new_workdir/.git" || die "unable to create \"$new_workdir\"!"
@@ -45,13 +47,13 @@ do
                mkdir -p "$(dirname "$new_workdir/.git/$x")"
                ;;
        esac
-       ln -s "$orig_git/.git/$x" "$new_workdir/.git/$x"
+       ln -s "$git_dir/$x" "$new_workdir/.git/$x"
 done
 
 # now setup the workdir
 cd "$new_workdir"
 # copy the HEAD from the original repository as a default branch
-cp "$orig_git/.git/HEAD" .git/HEAD
+cp "$git_dir/HEAD" .git/HEAD
 # checkout the branch (either the same as HEAD from the original repository, or
 # the one that was asked for)
 git checkout -f $branch
index 4b26b1a9b9979c2a7753afdad107c73f3e1aae4c..21908b10398492c0b07f705ed3b1ce7a06ac6b44 100644 (file)
--- a/convert.c
+++ b/convert.c
@@ -509,36 +509,71 @@ static char *ident_to_worktree(const char *path, const char *src, unsigned long
 
        for (dst = buf; size; size--) {
                const char *cp;
+               /* Fetch next source character, move the pointer on */
                char ch = *src++;
+               /* Copy the current character to the destination */
                *dst++ = ch;
+               /* If the current character is "$" or there are less than three
+                * remaining bytes or the two bytes following this one are not
+                * "Id", then simply read the next character */
                if ((ch != '$') || (size < 3) || memcmp("Id", src, 2))
                        continue;
+               /*
+                * Here when
+                *  - There are more than 2 bytes remaining
+                *  - The current three bytes are "$Id"
+                * with
+                *  - ch == "$"
+                *  - src[0] == "I"
+                */
 
+               /*
+                * It's possible that an expanded Id has crept its way into the
+                * repository, we cope with that by stripping the expansion out
+                */
                if (src[2] == ':') {
+                       /* Expanded keywords have "$Id:" at the front */
+
                        /* discard up to but not including the closing $ */
                        unsigned long rem = size - 3;
+                       /* Point at first byte after the ":" */
                        cp = src + 3;
+                       /*
+                        * Throw away characters until either
+                        *  - we reach a "$"
+                        *  - we run out of bytes (rem == 0)
+                        */
                        do {
-                               ch = *cp++;
+                               ch = *cp;
                                if (ch == '$')
                                        break;
+                               cp++;
                                rem--;
                        } while (rem);
+                       /* If the above finished because it ran out of characters, then
+                        * this is an incomplete keyword, so don't run the expansion */
                        if (!rem)
                                continue;
-                       size -= (cp - src);
                } else if (src[2] == '$')
                        cp = src + 2;
                else
+                       /* Anything other than "$Id:XXX$" or $Id$ and we skip the
+                        * expansion */
                        continue;
 
+               /* cp is now pointing at the last $ of the keyword */
+
                memcpy(dst, "Id: ", 4);
                dst += 4;
                memcpy(dst, sha1_to_hex(sha1), 40);
                dst += 40;
                *dst++ = ' ';
+
+               /* Adjust for the characters we've discarded */
                size -= (cp - src);
                src = cp;
+
+               /* Copy the final "$" */
                *dst++ = *src++;
                size--;
        }
diff --git a/diff.c b/diff.c
index 0e260490d7fd74aa9761f286f1ad671a6ea39841..508bc51ed59998be463fd429ee074654baaad76a 100644 (file)
--- a/diff.c
+++ b/diff.c
@@ -1349,7 +1349,7 @@ void fill_filespec(struct diff_filespec *spec, const unsigned char *sha1,
 }
 
 /*
- * Given a name and sha1 pair, if the dircache tells us the file in
+ * Given a name and sha1 pair, if the index tells us the file in
  * the work tree has that object contents, return true, so that
  * prepare_temp_file() does not have to inflate and extract.
  */
index c9f66e278454374714794477be7ff8b93cd05a0f..8b5712968ebcfe3f8fb5426e5104de2e7d2d3334 100755 (executable)
--- a/git-am.sh
+++ b/git-am.sh
@@ -18,7 +18,7 @@ stop_here () {
 
 stop_here_user_resolve () {
     if [ -n "$resolvemsg" ]; then
-           echo "$resolvemsg"
+           printf '%s\n' "$resolvemsg"
            stop_here $1
     fi
     cmdline=$(basename $0)
@@ -146,7 +146,7 @@ do
        git_apply_opt="$git_apply_opt $1"; shift ;;
 
        --resolvemsg=*)
-       resolvemsg=$(echo "$1" | sed -e "s/^--resolvemsg=//"); shift ;;
+       resolvemsg=${1#--resolvemsg=}; shift ;;
 
        --)
        shift; break ;;
@@ -331,7 +331,7 @@ do
                ADD_SIGNOFF=
            fi
            {
-               echo "$SUBJECT"
+               printf '%s\n' "$SUBJECT"
                if test -s "$dotest/msg-clean"
                then
                        echo
@@ -394,7 +394,7 @@ do
        fi
 
        echo
-       echo "Applying '$SUBJECT'"
+       printf 'Applying %s\n' "$SUBJECT"
        echo
 
        case "$resolved" in
index f28fc242241d3f0f5c88b287da0c59417667a013..e8b60f70497c71bd66b96115b9bba78cee523a8c 100755 (executable)
@@ -376,12 +376,12 @@ t,)
                        rm -f "$TMP_INDEX"
                fi || exit
 
-               echo "$commit_only" |
+               printf '%s\n' "$commit_only" |
                GIT_INDEX_FILE="$TMP_INDEX" \
                git-update-index --add --remove --stdin &&
 
                save_index &&
-               echo "$commit_only" |
+               printf '%s\n' "$commit_only" |
                (
                        GIT_INDEX_FILE="$NEXT_INDEX"
                        export GIT_INDEX_FILE
@@ -432,7 +432,7 @@ fi
 
 if test "$log_message" != ''
 then
-       echo "$log_message"
+       printf '%s\n' "$log_message"
 elif test "$logfile" != ""
 then
        if test "$logfile" = -
@@ -475,7 +475,7 @@ if test -f "$GIT_DIR/MERGE_HEAD" && test -z "$no_edit"; then
        echo "#"
        echo "# It looks like you may be committing a MERGE."
        echo "# If this is not correct, please remove the file"
-       echo "# $GIT_DIR/MERGE_HEAD"
+       printf '%s\n' "#        $GIT_DIR/MERGE_HEAD"
        echo "# and try again"
        echo "#"
 fi >>"$GIT_DIR"/COMMIT_EDITMSG
index 1de517791f8a293a9c770f6260ff48f9719845ad..2b4825a8eebad57fa9857593d0a8aa5928b313fe 100755 (executable)
@@ -95,9 +95,10 @@ $state->{method} = 'ext';
 if (@ARGV && $ARGV[0] eq 'pserver') {
     $state->{method} = 'pserver';
     my $line = <STDIN>; chomp $line;
-    unless( $line eq 'BEGIN AUTH REQUEST') {
+    unless( $line =~ /^BEGIN (AUTH|VERIFICATION) REQUEST$/) {
        die "E Do not understand $line - expecting BEGIN AUTH REQUEST\n";
     }
+    my $request = $1;
     $line = <STDIN>; chomp $line;
     req_Root('root', $line) # reuse Root
        or die "E Invalid root $line \n";
@@ -109,10 +110,11 @@ if (@ARGV && $ARGV[0] eq 'pserver') {
     }
     $line = <STDIN>; chomp $line;    # validate the password?
     $line = <STDIN>; chomp $line;
-    unless ($line eq 'END AUTH REQUEST') {
-       die "E Do not understand $line -- expecting END AUTH REQUEST\n";
+    unless ($line eq "END $request REQUEST") {
+       die "E Do not understand $line -- expecting END $request REQUEST\n";
     }
     print "I LOVE YOU\n";
+    exit if $request eq 'VERIFICATION'; # cvs login
     # and now back to our regular programme...
 }
 
index ee564219c0f911025b9bf850539b87edae2d13c4..3de0de1a2341eedd67de5210fbf216d62fe9e464 100644 (file)
@@ -22,7 +22,7 @@ ifndef gitexecdir
 endif
 
 ifndef sharedir
-       sharedir := $(dir $(gitexecdir))/share
+       sharedir := $(dir $(gitexecdir))share
 endif
 
 ifndef INSTALL
@@ -53,12 +53,19 @@ TCLTK_PATH_SQ = $(subst ','\'',$(TCLTK_PATH))
 libdir   ?= $(sharedir)/git-gui/lib
 libdir_SQ = $(subst ','\'',$(libdir))
 
+exedir    = $(dir $(gitexecdir))share/git-gui/lib
+exedir_SQ = $(subst ','\'',$(exedir))
+
 $(patsubst %.sh,%,$(SCRIPT_SH)) : % : %.sh
        $(QUIET_GEN)rm -f $@ $@+ && \
+       if test '$(exedir_SQ)' = '$(libdir_SQ)'; then \
+               GITGUI_RELATIVE=1; \
+       fi && \
        sed -e '1s|#!.*/sh|#!$(SHELL_PATH_SQ)|' \
                -e 's|^exec wish "$$0"|exec $(subst |,'\|',$(TCLTK_PATH_SQ)) "$$0"|' \
                -e 's/@@GITGUI_VERSION@@/$(GITGUI_VERSION)/g' \
-               -e 's|@@GITGUI_LIBDIR@@|$(libdir_SQ)|' \
+               -e 's|@@GITGUI_RELATIVE@@|'$$GITGUI_RELATIVE'|' \
+               -e $$GITGUI_RELATIVE's|@@GITGUI_LIBDIR@@|$(libdir_SQ)|' \
                $@.sh >$@+ && \
        chmod +x $@+ && \
        mv $@+ $@
@@ -88,6 +95,7 @@ TRACK_VARS = \
        $(subst ','\'',SHELL_PATH='$(SHELL_PATH_SQ)') \
        $(subst ','\'',TCL_PATH='$(TCL_PATH_SQ)') \
        $(subst ','\'',TCLTK_PATH='$(TCLTK_PATH_SQ)') \
+       $(subst ','\'',gitexecdir='$(gitexecdir_SQ)') \
        $(subst ','\'',libdir='$(libdir_SQ)') \
 #end TRACK_VARS
 
index 0a471a5c7d4a2126f1f3322424a643796e1de715..dba585111c111b180b9dc28ef67bda4be2fcb663 100755 (executable)
@@ -25,7 +25,11 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA}
 ## configure our library
 
 set oguilib {@@GITGUI_LIBDIR@@}
-if {[string match @@* $oguilib]} {
+set oguirel {@@GITGUI_RELATIVE@@}
+if {$oguirel eq {1}} {
+       set oguilib [file dirname [file dirname [file normalize $argv0]]]
+       set oguilib [file join $oguilib share git-gui lib]
+} elseif {[string match @@* $oguirel]} {
        set oguilib [file join [file dirname [file normalize $argv0]] lib]
 }
 set idx [file join $oguilib tclIndex]
@@ -55,7 +59,7 @@ if {$idx ne {}} {
 } else {
        set auto_path [concat [list $oguilib] $auto_path]
 }
-unset -nocomplain fd idx
+unset -nocomplain oguilib oguirel idx fd
 
 if {![catch {set _verbose $env(GITGUI_VERBOSE)}]} {
        unset _verbose
@@ -1206,15 +1210,12 @@ foreach class {Button Checkbutton Entry Label
 }
 unset class
 
-if {[is_Windows]} {
-       set M1B Control
-       set M1T Ctrl
-} elseif {[is_MacOSX]} {
+if {[is_MacOSX]} {
        set M1B M1
        set M1T Cmd
 } else {
-       set M1B M1
-       set M1T M1
+       set M1B Control
+       set M1T Ctrl
 }
 
 proc apply_config {} {
index 351676f6d4a39c1ac682296781f4f5c8d1a3053d..ff92aaf3f9826a7c307154657166cd38ad2b6154 100755 (executable)
@@ -329,7 +329,7 @@ f,*)
                then
                        echo "Wonderful."
                        result_commit=$(
-                               echo "$merge_msg" |
+                               printf '%s\n' "$merge_msg" |
                                git-commit-tree $result_tree -p HEAD -p "$1"
                        ) || exit
                        finish "$result_commit" "In-index merge"
@@ -434,7 +434,7 @@ done
 if test '' != "$result_tree"
 then
     parents=$(git-show-branch --independent "$head" "$@" | sed -e 's/^/-p /')
-    result_commit=$(echo "$merge_msg" | git-commit-tree $result_tree $parents) || exit
+    result_commit=$(printf '%s\n' "$merge_msg" | git-commit-tree $result_tree $parents) || exit
     finish "$result_commit" "Merge made by $wt_strategy."
     dropsave
     exit 0
@@ -473,7 +473,7 @@ else
        do
                echo $remote
        done >"$GIT_DIR/MERGE_HEAD"
-       echo "$merge_msg" >"$GIT_DIR/MERGE_MSG"
+       printf '%s\n' "$merge_msg" >"$GIT_DIR/MERGE_MSG"
 fi
 
 if test "$merge_was_ok" = t
index eda9969f501fe1466610dedc0ea667714ba81653..e35006142af766080b3bafe0cdcd39bf2ccf3f04 100755 (executable)
@@ -2472,12 +2472,16 @@ sub close_file {
        my $hash;
        my $path = $self->git_path($fb->{path});
        if (my $fh = $fb->{fh}) {
-               seek($fh, 0, 0) or croak $!;
-               my $md5 = Digest::MD5->new;
-               $md5->addfile($fh);
-               my $got = $md5->hexdigest;
-               die "Checksum mismatch: $path\n",
-                   "expected: $exp\n    got: $got\n" if ($got ne $exp);
+               if (defined $exp) {
+                       seek($fh, 0, 0) or croak $!;
+                       my $md5 = Digest::MD5->new;
+                       $md5->addfile($fh);
+                       my $got = $md5->hexdigest;
+                       if ($got ne $exp) {
+                               die "Checksum mismatch: $path\n",
+                                   "expected: $exp\n    got: $got\n";
+                       }
+               }
                sysseek($fh, 0, 0) or croak $!;
                if ($fb->{mode_b} == 120000) {
                        sysread($fh, my $buf, 5) == 5 or croak $!;
index 4a0a7b660780b7c377ce80ac49dc99cea3e8137d..6f0b7a72192bbeb7ca4693f40f80e2bd20d5eb03 100755 (executable)
@@ -126,7 +126,7 @@ if [ "$annotate" ]; then
           echo "#" ) > "$GIT_DIR"/TAG_EDITMSG
         ${VISUAL:-${EDITOR:-vi}} "$GIT_DIR"/TAG_EDITMSG || exit
     else
-        echo "$message" >"$GIT_DIR"/TAG_EDITMSG
+        printf '%s\n' "$message" >"$GIT_DIR"/TAG_EDITMSG
     fi
 
     grep -v '^#' <"$GIT_DIR"/TAG_EDITMSG |
index d04536bbff7cba22ca67521d45e690dfa5aa8675..c168642c0c0d9479b1ccc8564ce6c80c9055ab00 100644 (file)
@@ -73,12 +73,11 @@ static int verify_packfile(struct packed_git *p,
 }
 
 
-#define MAX_CHAIN 40
+#define MAX_CHAIN 50
 
 static void show_pack_info(struct packed_git *p)
 {
-       uint32_t nr_objects, i, chain_histogram[MAX_CHAIN];
-
+       uint32_t nr_objects, i, chain_histogram[MAX_CHAIN+1];
        nr_objects = p->num_objects;
        memset(chain_histogram, 0, sizeof(chain_histogram));
 
@@ -109,22 +108,22 @@ static void show_pack_info(struct packed_git *p)
                        printf("%-6s %lu %"PRIuMAX" %u %s\n",
                               type, size, (uintmax_t)offset,
                               delta_chain_length, sha1_to_hex(base_sha1));
-                       if (delta_chain_length < MAX_CHAIN)
+                       if (delta_chain_length <= MAX_CHAIN)
                                chain_histogram[delta_chain_length]++;
                        else
                                chain_histogram[0]++;
                }
        }
 
-       for (i = 0; i < MAX_CHAIN; i++) {
+       for (i = 0; i <= MAX_CHAIN; i++) {
                if (!chain_histogram[i])
                        continue;
-               printf("chain length %s %d: %d object%s\n",
-                      i ? "=" : ">=",
-                      i ? i : MAX_CHAIN,
-                      chain_histogram[i],
-                      1 < chain_histogram[i] ? "s" : "");
+               printf("chain length = %d: %d object%s\n", i,
+                      chain_histogram[i], chain_histogram[i] > 1 ? "s" : "");
        }
+       if (chain_histogram[0])
+               printf("chain length > %d: %d object%s\n", MAX_CHAIN,
+                      chain_histogram[0], chain_histogram[0] > 1 ? "s" : "");
 }
 
 int verify_pack(struct packed_git *p, int verbose)
index 6c26fd829d8d9a08cb6cadfa013e0beae9b08dff..a839f4e0744cd9344a3d71a48fe2224a99750729 100755 (executable)
@@ -45,4 +45,40 @@ test_expect_success check '
        test "z$id" = "z$embedded"
 '
 
+# If an expanded ident ever gets into the repository, we want to make sure that
+# it is collapsed before being expanded again on checkout
+test_expect_success expanded_in_repo '
+       {
+               echo "File with expanded keywords"
+               echo "\$Id\$"
+               echo "\$Id:\$"
+               echo "\$Id: 0000000000000000000000000000000000000000 \$"
+               echo "\$Id: NoSpaceAtEnd\$"
+               echo "\$Id:NoSpaceAtFront \$"
+               echo "\$Id:NoSpaceAtEitherEnd\$"
+               echo "\$Id: NoTerminatingSymbol"
+       } > expanded-keywords &&
+
+       {
+               echo "File with expanded keywords"
+               echo "\$Id: 4f21723e7b15065df7de95bd46c8ba6fb1818f4c \$"
+               echo "\$Id: 4f21723e7b15065df7de95bd46c8ba6fb1818f4c \$"
+               echo "\$Id: 4f21723e7b15065df7de95bd46c8ba6fb1818f4c \$"
+               echo "\$Id: 4f21723e7b15065df7de95bd46c8ba6fb1818f4c \$"
+               echo "\$Id: 4f21723e7b15065df7de95bd46c8ba6fb1818f4c \$"
+               echo "\$Id: 4f21723e7b15065df7de95bd46c8ba6fb1818f4c \$"
+               echo "\$Id: NoTerminatingSymbol"
+       } > expected-output &&
+
+       git add expanded-keywords &&
+       git commit -m "File with keywords expanded" &&
+
+       echo "expanded-keywords ident" >> .gitattributes &&
+
+       rm -f expanded-keywords &&
+       git checkout -- expanded-keywords &&
+       cat expanded-keywords &&
+       cmp expanded-keywords expected-output
+'
+
 test_done
index 4795872a776e3ccc7cc904b12c0352aae782f502..df969bb69ce148f26709691fe846def7f960d39d 100755 (executable)
@@ -16,16 +16,16 @@ test_expect_success setup '
 
        for i in 1 2 5 6 A B C 7 8 9 10; do echo "$i"; done >file &&
        git update-index file &&
-       git commit -m "Side change #1" &&
+       git commit -m "Side changes #1" &&
 
        for i in D E F; do echo "$i"; done >>file &&
        git update-index file &&
-       git commit -m "Side change #2" &&
+       git commit -m "Side changes #2" &&
        git tag C2 &&
 
        for i in 5 6 1 2 3 A 4 B C 7 8 9 10 D E F; do echo "$i"; done >file &&
        git update-index file &&
-       git commit -m "Side change #3" &&
+       git commit -m "Side changes #3 with \\n backslash-n in it." &&
 
        git checkout master &&
        git diff-tree -p C2 | git apply --index &&
@@ -66,4 +66,23 @@ test_expect_success "format-patch --ignore-if-in-upstream result applies" '
        test $cnt = 2
 '
 
+test_expect_success 'commit did not screw up the log message' '
+
+       git cat-file commit side | grep "^Side .* with .* backslash-n"
+
+'
+
+test_expect_success 'format-patch did not screw up the log message' '
+
+       grep "^Subject: .*Side changes #3 with .* backslash-n" patch0 &&
+       grep "^Subject: .*Side changes #3 with .* backslash-n" patch1
+
+'
+
+test_expect_success 'replay did not screw up the log message' '
+
+       git cat-file commit rebuild-1 | grep "^Side .* with .* backslash-n"
+
+'
+
 test_done
diff --git a/t/t9112-git-svn-md5less-file.sh b/t/t9112-git-svn-md5less-file.sh
new file mode 100755 (executable)
index 0000000..08313bb
--- /dev/null
@@ -0,0 +1,45 @@
+test_description='test that git handles an svn repository with missing md5sums'
+
+. ./lib-git-svn.sh
+
+# Loading a node from a svn dumpfile without a Text-Content-Length
+# field causes svn to neglect to store or report an md5sum.  (it will
+# calculate one if you had put Text-Content-Length: 0).  This showed
+# up in a repository creted with cvs2svn.
+
+cat > dumpfile.svn <<EOF
+SVN-fs-dump-format-version: 1
+
+Revision-number: 1
+Prop-content-length: 98
+Content-length: 98
+
+K 7
+svn:log
+V 0
+
+K 10
+svn:author
+V 4
+test
+K 8
+svn:date
+V 27
+2007-05-06T12:37:01.153339Z
+PROPS-END
+
+Node-path: md5less-file
+Node-kind: file
+Node-action: add
+Prop-content-length: 10
+Content-length: 10
+
+PROPS-END
+
+EOF
+
+test_expect_success 'load svn dumpfile' "svnadmin load $rawsvnrepo < dumpfile.svn"
+
+test_expect_success 'initialize git-svn' "git-svn init $svnrepo"
+test_expect_success 'fetch revisions from svn' 'git-svn fetch'
+test_done
index 7f9c6e29b233c785f927293268d97c07eac9db5e..e9ef315173f9596212d9104587486315603b2b51 100755 (executable)
@@ -67,6 +67,22 @@ git
 END AUTH REQUEST
 EOF
 
+cat >login-anonymous <<EOF
+BEGIN VERIFICATION REQUEST
+$SERVERDIR
+anonymous
+
+END VERIFICATION REQUEST
+EOF
+
+cat >login-git <<EOF
+BEGIN VERIFICATION REQUEST
+$SERVERDIR
+git
+
+END VERIFICATION REQUEST
+EOF
+
 test_expect_success 'pserver authentication' \
   'cat request-anonymous | git-cvsserver pserver >log 2>&1 &&
    tail -n1 log | grep -q "^I LOVE YOU$"'
@@ -80,6 +96,19 @@ test_expect_success 'pserver authentication failure (non-anonymous user)' \
    fi &&
    tail -n1 log | grep -q "^I HATE YOU$"'
 
+test_expect_success 'pserver authentication (login)' \
+  'cat login-anonymous | git-cvsserver pserver >log 2>&1 &&
+   tail -n1 log | grep -q "^I LOVE YOU$"'
+
+test_expect_success 'pserver authentication failure (login/non-anonymous user)' \
+  'if cat login-git | git-cvsserver pserver >log 2>&1
+   then
+       false
+   else
+       true
+   fi &&
+   tail -n1 log | grep -q "^I HATE YOU$"'
+
 
 #--------------
 # CONFIG TESTS
@@ -250,6 +279,7 @@ test_expect_success 'cvs update (merge)' \
    git commit -q -m "Merge test (merge)" &&
    git push gitcvs.git >/dev/null &&
    cd cvswork &&
+   sleep 1 && touch merge &&
    GIT_CONFIG="$git_config" cvs -Q update &&
    diff -q merge ../expected'
 
@@ -292,6 +322,7 @@ test_expect_success 'cvs update (merge no-op)' \
     git commit -q -m "Merge test (no-op)" &&
     git push gitcvs.git >/dev/null &&
     cd cvswork &&
+    sleep 1 && touch merge &&
     GIT_CONFIG="$git_config" cvs -Q update &&
     diff -q merge ../merge'
 
diff --git a/tag.c b/tag.c
index 330d287924765c95dac428f040b104930c316b81..bbacd59a23f7994980f4bf017324833ca3d4adb3 100644 (file)
--- a/tag.c
+++ b/tag.c
@@ -26,7 +26,7 @@ struct tag *lookup_tag(const unsigned char *sha1)
        if (!obj->type)
                obj->type = OBJ_TAG;
         if (obj->type != OBJ_TAG) {
-                error("Object %s is a %s, not a tree",
+                error("Object %s is a %s, not a tag",
                       sha1_to_hex(sha1), typename(obj->type));
                 return NULL;
         }