]> asedeno.scripts.mit.edu Git - git.git/commitdiff
Merge branch 'dd/cvsserver'
authorJunio C Hamano <gitster@pobox.com>
Wed, 2 Apr 2008 07:22:15 +0000 (00:22 -0700)
committerJunio C Hamano <gitster@pobox.com>
Wed, 2 Apr 2008 07:22:15 +0000 (00:22 -0700)
* dd/cvsserver:
  cvsserver: Use the user part of the email in log and annotate results
  cvsserver: Add test for update -p
  cvsserver: Implement update -p (print to stdout)
  cvsserver: Add a few tests for 'status' command
  cvsserver: Do not include status output for subdirectories if -l is passed
  cvsserver: Only print the file part of the filename in status header
  cvsserver: Respond to the 'editors' and 'watchers' commands

20 files changed:
Documentation/RelNotes-1.5.4.5.txt
Documentation/config.txt
Documentation/git-cvsserver.txt
Documentation/git.txt
GIT-VERSION-GEN
builtin-prune.c
builtin-verify-tag.c
contrib/completion/git-completion.bash
contrib/fast-import/git-p4
diff-lib.c
git-clone.sh
git-cvsserver.perl
git-svn.perl
git.c
help.c
parse-options.c
parse-options.h
t/t2201-add-update-typechange.sh [new file with mode: 0755]
t/t5304-prune.sh
t/t7004-tag.sh

index 56fcd27b5cf76517683775e11b0c7b9f07a18bae..02823413987d5a10364d936327e3a1cfb38cbac2 100644 (file)
@@ -54,9 +54,3 @@ Fixes since v1.5.4.4
    "rebase --continue" impossible.
 
 As usual, it also comes with many documentation fixes and clarifications.
-
---
-exec >/var/tmp/1
-echo O=$(git describe maint)
-O=v1.5.4.4-32-gb88605f
-git shortlog --no-merges $O..maint
index 3017d640cff918e33544272cb2b9f7b9cfd5db4c..04c01c5fdca566b1760e8eed02687607017e89aa 100644 (file)
@@ -661,6 +661,13 @@ gitcvs.dbuser, gitcvs.dbpass::
        'gitcvs.dbuser' supports variable substitution (see
        linkgit:git-cvsserver[1] for details).
 
+gitcvs.dbTableNamePrefix::
+       Database table name prefix.  Prepended to the names of any
+       database tables used, allowing a single database to be used
+       for several repositories.  Supports variable substitution (see
+       linkgit:git-cvsserver[1] for details).  Any non-alphabetic
+       characters will be replaced with underscores.
+
 All gitcvs variables except for 'gitcvs.allbinary' can also be
 specified as 'gitcvs.<access_method>.<varname>' (where 'access_method'
 is one of "ext" and "pserver") to make them apply only for the given
index d3e99931d7d344cdfb04b90133dd926a2aac1c9b..9cec8021b8c66b6bac692e2a9f14204503f7f18a 100644 (file)
@@ -227,6 +227,11 @@ gitcvs.dbpass::
        Database password.  Only useful if setting `dbdriver`, since
        SQLite has no concept of database passwords.
 
+gitcvs.dbTableNamePrefix::
+       Database table name prefix.  Supports variable substitution
+       (see below).  Any non-alphabetic characters will be replaced
+       with underscores.
+
 All variables can also be set per access method, see <<configaccessmethod,above>>.
 
 Variable substitution
index 3ed24d449a1f277c40dbb49654a196e38d1fa3e4..aaf318993670b537d523bd556b2f24072500c08c 100644 (file)
@@ -43,9 +43,10 @@ unreleased) version of git, that is available from 'master'
 branch of the `git.git` repository.
 Documentation for older releases are available here:
 
-* link:v1.5.4.4/git.html[documentation for release 1.5.4.4]
+* link:v1.5.4.5/git.html[documentation for release 1.5.4.5]
 
 * release notes for
+  link:RelNotes-1.5.4.5.txt[1.5.4.5],
   link:RelNotes-1.5.4.4.txt[1.5.4.4],
   link:RelNotes-1.5.4.3.txt[1.5.4.3],
   link:RelNotes-1.5.4.2.txt[1.5.4.2],
index d0b60f40d80017b4638a403ff4b0ec05550014b2..7529af931536d2d2060dbb48aeb0c3fddfb2eb81 100755 (executable)
@@ -1,7 +1,7 @@
 #!/bin/sh
 
 GVF=GIT-VERSION-FILE
-DEF_VER=v1.5.5-rc1.GIT
+DEF_VER=v1.5.5-rc2.GIT
 
 LF='
 '
index bb8ead92cf41c3cbdbc421a1490fb40ce19f11c3..25f9304b829c9074e8a034eba5e34c38794058a4 100644 (file)
@@ -4,8 +4,12 @@
 #include "revision.h"
 #include "builtin.h"
 #include "reachable.h"
+#include "parse-options.h"
 
-static const char prune_usage[] = "git-prune [-n]";
+static const char * const prune_usage[] = {
+       "git-prune [-n] [--expire <time>] [--] [<head>...]",
+       NULL
+};
 static int show_only;
 static unsigned long expire;
 
@@ -123,32 +127,33 @@ static void remove_temporary_files(void)
 
 int cmd_prune(int argc, const char **argv, const char *prefix)
 {
-       int i;
        struct rev_info revs;
-
-       for (i = 1; i < argc; i++) {
-               const char *arg = argv[i];
-               if (!strcmp(arg, "-n")) {
-                       show_only = 1;
-                       continue;
-               }
-               if (!strcmp(arg, "--expire")) {
-                       if (++i < argc) {
-                               expire = approxidate(argv[i]);
-                               continue;
-                       }
-               }
-               else if (!prefixcmp(arg, "--expire=")) {
-                       expire = approxidate(arg + 9);
-                       continue;
-               }
-               usage(prune_usage);
-       }
+       const struct option options[] = {
+               OPT_BOOLEAN('n', NULL, &show_only,
+                           "do not remove, show only"),
+               OPT_DATE(0, "expire", &expire,
+                        "expire objects older than <time>"),
+               OPT_END()
+       };
 
        save_commit_buffer = 0;
        init_revisions(&revs, prefix);
-       mark_reachable_objects(&revs, 1);
 
+       argc = parse_options(argc, argv, options, prune_usage, 0);
+       while (argc--) {
+               unsigned char sha1[20];
+               const char *name = *argv++;
+
+               if (!get_sha1(name, sha1)) {
+                       struct object *object = parse_object(sha1);
+                       if (!object)
+                               die("bad object: %s", name);
+                       add_pending_object(&revs, object, "");
+               }
+               else
+                       die("unrecognized argument: %s", name);
+       }
+       mark_reachable_objects(&revs, 1);
        prune_object_dir(get_object_directory());
 
        sync();
index f3ef11fa2d582682b428d6e165da65f05e2d7511..db81496b464e253341a42e01eb72d6845e87199c 100644 (file)
@@ -46,8 +46,10 @@ static int run_gpg_verify(const char *buf, unsigned long size, int verbose)
        gpg.argv = args_gpg;
        gpg.in = -1;
        args_gpg[2] = path;
-       if (start_command(&gpg))
+       if (start_command(&gpg)) {
+               unlink(path);
                return error("could not run gpg.");
+       }
 
        write_in_full(gpg.in, buf, len);
        close(gpg.in);
index 5046f699349aa87bedbc79a997dfcb9ea54e7618..791e30f6d78b06429f239defc76aaa0d09db4e09 100755 (executable)
@@ -999,7 +999,8 @@ _git_config ()
                gitcvs.enabled
                gitcvs.logfile
                gitcvs.allbinary
-               gitcvs.dbname gitcvs.dbdriver gitcvs.dbuser gitcvs.dvpass
+               gitcvs.dbname gitcvs.dbdriver gitcvs.dbuser gitcvs.dbpass
+               gitcvs.dbtablenameprefix
                gc.packrefs
                gc.reflogexpire
                gc.reflogexpireunreachable
index 3cb0330ec2d89d0637bbbc5a529158f695793638..d8de9f6c255ca7e458eac62e7f14b3d664054587 100755 (executable)
@@ -90,11 +90,11 @@ def getP4OpenedType(file):
     # Returns the perforce file type for the given file.
 
     result = read_pipe("p4 opened %s" % file)
-    match = re.match(".*\((.+)\)$", result)
+    match = re.match(".*\((.+)\)\r?$", result)
     if match:
         return match.group(1)
     else:
-        die("Could not determine file type for %s" % file)
+        die("Could not determine file type for %s (result: '%s')" % (file, result))
 
 def diffTreePattern():
     # This is a simple generator for the diff tree regex pattern. This could be
@@ -513,6 +513,8 @@ class P4Submit(Command):
         template = ""
         inFilesSection = False
         for line in read_pipe_lines("p4 change -o"):
+            if line.endswith("\r\n"):
+                line = line[:-2] + "\n"
             if inFilesSection:
                 if line.startswith("\t"):
                     # path starts and ends with a tab
@@ -619,8 +621,6 @@ class P4Submit(Command):
             setP4ExecBit(f, mode)
 
         logMessage = extractLogMessageFromGitCommit(id)
-        if self.isWindows:
-            logMessage = logMessage.replace("\n", "\r\n")
         logMessage = logMessage.strip()
 
         template = self.prepareSubmitTemplate()
@@ -631,23 +631,25 @@ class P4Submit(Command):
                 del(os.environ["P4DIFF"])
             diff = read_pipe("p4 diff -du ...")
 
+            newdiff = ""
             for newFile in filesToAdd:
-                diff += "==== new file ====\n"
-                diff += "--- /dev/null\n"
-                diff += "+++ %s\n" % newFile
+                newdiff += "==== new file ====\n"
+                newdiff += "--- /dev/null\n"
+                newdiff += "+++ %s\n" % newFile
                 f = open(newFile, "r")
                 for line in f.readlines():
-                    diff += "+" + line
+                    newdiff += "+" + line
                 f.close()
 
-            separatorLine = "######## everything below this line is just the diff #######"
-            if platform.system() == "Windows":
-                separatorLine += "\r"
-            separatorLine += "\n"
+            separatorLine = "######## everything below this line is just the diff #######\n"
 
             [handle, fileName] = tempfile.mkstemp()
             tmpFile = os.fdopen(handle, "w+")
-            tmpFile.write(submitTemplate + separatorLine + diff)
+            if self.isWindows:
+                submitTemplate = submitTemplate.replace("\n", "\r\n")
+                separatorLine = separatorLine.replace("\n", "\r\n")
+                newdiff = newdiff.replace("\n", "\r\n")
+            tmpFile.write(submitTemplate + separatorLine + diff + newdiff)
             tmpFile.close()
             defaultEditor = "vi"
             if platform.system() == "Windows":
index 52dbac34a40b2ca7bcbb7c2343a0487e5cb90ccf..069e4507ae7caa70f79d5369bc61dfefd0f174e2 100644 (file)
@@ -10,6 +10,7 @@
 #include "cache-tree.h"
 #include "path-list.h"
 #include "unpack-trees.h"
+#include "refs.h"
 
 /*
  * diff-files
@@ -333,6 +334,26 @@ int run_diff_files_cmd(struct rev_info *revs, int argc, const char **argv)
        }
        return run_diff_files(revs, options);
 }
+/*
+ * See if work tree has an entity that can be staged.  Return 0 if so,
+ * return 1 if not and return -1 if error.
+ */
+static int check_work_tree_entity(const struct cache_entry *ce, struct stat *st, char *symcache)
+{
+       if (lstat(ce->name, st) < 0) {
+               if (errno != ENOENT && errno != ENOTDIR)
+                       return -1;
+               return 1;
+       }
+       if (has_symlink_leading_path(ce->name, symcache))
+               return 1;
+       if (S_ISDIR(st->st_mode)) {
+               unsigned char sub[20];
+               if (resolve_gitlink_ref(ce->name, "HEAD", sub))
+                       return 1;
+       }
+       return 0;
+}
 
 int run_diff_files(struct rev_info *revs, unsigned int option)
 {
@@ -341,10 +362,12 @@ int run_diff_files(struct rev_info *revs, unsigned int option)
        int silent_on_removed = option & DIFF_SILENT_ON_REMOVED;
        unsigned ce_option = ((option & DIFF_RACY_IS_MODIFIED)
                              ? CE_MATCH_RACY_IS_DIRTY : 0);
+       char symcache[PATH_MAX];
 
        if (diff_unmerged_stage < 0)
                diff_unmerged_stage = 2;
        entries = active_nr;
+       symcache[0] = '\0';
        for (i = 0; i < entries; i++) {
                struct stat st;
                unsigned int oldmode, newmode;
@@ -376,16 +399,17 @@ int run_diff_files(struct rev_info *revs, unsigned int option)
                        memset(&(dpath->parent[0]), 0,
                               sizeof(struct combine_diff_parent)*5);
 
-                       if (lstat(ce->name, &st) < 0) {
-                               if (errno != ENOENT && errno != ENOTDIR) {
+                       changed = check_work_tree_entity(ce, &st, symcache);
+                       if (!changed)
+                               dpath->mode = ce_mode_from_stat(ce, st.st_mode);
+                       else {
+                               if (changed < 0) {
                                        perror(ce->name);
                                        continue;
                                }
                                if (silent_on_removed)
                                        continue;
                        }
-                       else
-                               dpath->mode = ce_mode_from_stat(ce, st.st_mode);
 
                        while (i < entries) {
                                struct cache_entry *nce = active_cache[i];
@@ -438,8 +462,10 @@ int run_diff_files(struct rev_info *revs, unsigned int option)
 
                if (ce_uptodate(ce))
                        continue;
-               if (lstat(ce->name, &st) < 0) {
-                       if (errno != ENOENT && errno != ENOTDIR) {
+
+               changed = check_work_tree_entity(ce, &st, symcache);
+               if (changed) {
+                       if (changed < 0) {
                                perror(ce->name);
                                continue;
                        }
@@ -468,6 +494,11 @@ int run_diff_files(struct rev_info *revs, unsigned int option)
  * diff-index
  */
 
+struct oneway_unpack_data {
+       struct rev_info *revs;
+       char symcache[PATH_MAX];
+};
+
 /* A file entry went away or appeared */
 static void diff_index_show_file(struct rev_info *revs,
                                 const char *prefix,
@@ -481,7 +512,8 @@ static void diff_index_show_file(struct rev_info *revs,
 static int get_stat_data(struct cache_entry *ce,
                         const unsigned char **sha1p,
                         unsigned int *modep,
-                        int cached, int match_missing)
+                        int cached, int match_missing,
+                        struct oneway_unpack_data *cbdata)
 {
        const unsigned char *sha1 = ce->sha1;
        unsigned int mode = ce->ce_mode;
@@ -489,8 +521,11 @@ static int get_stat_data(struct cache_entry *ce,
        if (!cached) {
                int changed;
                struct stat st;
-               if (lstat(ce->name, &st) < 0) {
-                       if (errno == ENOENT && match_missing) {
+               changed = check_work_tree_entity(ce, &st, cbdata->symcache);
+               if (changed < 0)
+                       return -1;
+               else if (changed) {
+                       if (match_missing) {
                                *sha1p = sha1;
                                *modep = mode;
                                return 0;
@@ -509,23 +544,25 @@ static int get_stat_data(struct cache_entry *ce,
        return 0;
 }
 
-static void show_new_file(struct rev_info *revs,
+static void show_new_file(struct oneway_unpack_data *cbdata,
                          struct cache_entry *new,
                          int cached, int match_missing)
 {
        const unsigned char *sha1;
        unsigned int mode;
+       struct rev_info *revs = cbdata->revs;
 
-       /* New file in the index: it might actually be different in
+       /*
+        * New file in the index: it might actually be different in
         * the working copy.
         */
-       if (get_stat_data(new, &sha1, &mode, cached, match_missing) < 0)
+       if (get_stat_data(new, &sha1, &mode, cached, match_missing, cbdata) < 0)
                return;
 
        diff_index_show_file(revs, "+", new, sha1, mode);
 }
 
-static int show_modified(struct rev_info *revs,
+static int show_modified(struct oneway_unpack_data *cbdata,
                         struct cache_entry *old,
                         struct cache_entry *new,
                         int report_missing,
@@ -533,8 +570,9 @@ static int show_modified(struct rev_info *revs,
 {
        unsigned int mode, oldmode;
        const unsigned char *sha1;
+       struct rev_info *revs = cbdata->revs;
 
-       if (get_stat_data(new, &sha1, &mode, cached, match_missing) < 0) {
+       if (get_stat_data(new, &sha1, &mode, cached, match_missing, cbdata) < 0) {
                if (report_missing)
                        diff_index_show_file(revs, "-", old,
                                             old->sha1, old->ce_mode);
@@ -602,7 +640,8 @@ static void do_oneway_diff(struct unpack_trees_options *o,
        struct cache_entry *idx,
        struct cache_entry *tree)
 {
-       struct rev_info *revs = o->unpack_data;
+       struct oneway_unpack_data *cbdata = o->unpack_data;
+       struct rev_info *revs = cbdata->revs;
        int match_missing, cached;
 
        /*
@@ -625,7 +664,7 @@ static void do_oneway_diff(struct unpack_trees_options *o,
         * Something added to the tree?
         */
        if (!tree) {
-               show_new_file(revs, idx, cached, match_missing);
+               show_new_file(cbdata, idx, cached, match_missing);
                return;
        }
 
@@ -638,7 +677,7 @@ static void do_oneway_diff(struct unpack_trees_options *o,
        }
 
        /* Show difference between old and new */
-       show_modified(revs, tree, idx, 1, cached, match_missing);
+       show_modified(cbdata, tree, idx, 1, cached, match_missing);
 }
 
 static inline void skip_same_name(struct cache_entry *ce, struct unpack_trees_options *o)
@@ -675,7 +714,8 @@ static int oneway_diff(struct cache_entry **src, struct unpack_trees_options *o)
 {
        struct cache_entry *idx = src[0];
        struct cache_entry *tree = src[1];
-       struct rev_info *revs = o->unpack_data;
+       struct oneway_unpack_data *cbdata = o->unpack_data;
+       struct rev_info *revs = cbdata->revs;
 
        if (idx && ce_stage(idx))
                skip_same_name(idx, o);
@@ -702,6 +742,7 @@ int run_diff_index(struct rev_info *revs, int cached)
        const char *tree_name;
        struct unpack_trees_options opts;
        struct tree_desc t;
+       struct oneway_unpack_data unpack_cb;
 
        mark_merge_entries();
 
@@ -711,12 +752,14 @@ int run_diff_index(struct rev_info *revs, int cached)
        if (!tree)
                return error("bad tree object %s", tree_name);
 
+       unpack_cb.revs = revs;
+       unpack_cb.symcache[0] = '\0';
        memset(&opts, 0, sizeof(opts));
        opts.head_idx = 1;
        opts.index_only = cached;
        opts.merge = 1;
        opts.fn = oneway_diff;
-       opts.unpack_data = revs;
+       opts.unpack_data = &unpack_cb;
        opts.src_index = &the_index;
        opts.dst_index = NULL;
 
@@ -738,6 +781,7 @@ int do_diff_cache(const unsigned char *tree_sha1, struct diff_options *opt)
        struct cache_entry *last = NULL;
        struct unpack_trees_options opts;
        struct tree_desc t;
+       struct oneway_unpack_data unpack_cb;
 
        /*
         * This is used by git-blame to run diff-cache internally;
@@ -766,12 +810,14 @@ int do_diff_cache(const unsigned char *tree_sha1, struct diff_options *opt)
        if (!tree)
                die("bad tree object %s", sha1_to_hex(tree_sha1));
 
+       unpack_cb.revs = &revs;
+       unpack_cb.symcache[0] = '\0';
        memset(&opts, 0, sizeof(opts));
        opts.head_idx = 1;
        opts.index_only = 1;
        opts.merge = 1;
        opts.fn = oneway_diff;
-       opts.unpack_data = &revs;
+       opts.unpack_data = &unpack_cb;
        opts.src_index = &the_index;
        opts.dst_index = &the_index;
 
index e98112277839349a47c26e69ce30982604d12d2c..2636159aaa7a6278d9b8fc64b853b319ac8da123 100755 (executable)
@@ -310,6 +310,9 @@ yes)
                mkdir -p "$GIT_DIR/objects/info"
                echo "$repo/objects" >>"$GIT_DIR/objects/info/alternates"
        else
+               cpio_quiet_flag=""
+               cpio --help 2>&1 | grep -- --quiet >/dev/null && \
+                       cpio_quiet_flag=--quiet
                l= &&
                if test "$use_local_hardlink" = yes
                then
@@ -330,7 +333,8 @@ yes)
                        fi
                fi &&
                cd "$repo" &&
-               find objects -depth -print | cpio -pumd$l "$GIT_DIR/" || exit 1
+               find objects -depth -print | cpio $cpio_quiet_flag -pumd$l "$GIT_DIR/" || \
+                       exit 1
        fi
        git-ls-remote "$repo" >"$GIT_DIR/CLONE_HEAD" || exit 1
        ;;
index dcca4e7173eae6ff1781b169e7d07be441ac541b..64c255740b54ab3ba6532a2c49efd5841b2bccd1 100755 (executable)
@@ -2351,6 +2351,14 @@ sub new
 
     bless $self, $class;
 
+    $self->{valid_tables} = {'revision' => 1,
+                             'revision_ix1' => 1,
+                             'revision_ix2' => 1,
+                             'head' => 1,
+                             'head_ix1' => 1,
+                             'properties' => 1,
+                             'commitmsgs' => 1};
+
     $self->{module} = $module;
     $self->{git_path} = $config . "/";
 
@@ -2366,6 +2374,8 @@ sub new
         $cfg->{gitcvs}{dbuser} || "";
     $self->{dbpass} = $cfg->{gitcvs}{$state->{method}}{dbpass} ||
         $cfg->{gitcvs}{dbpass} || "";
+    $self->{dbtablenameprefix} = $cfg->{gitcvs}{$state->{method}}{dbtablenameprefix} ||
+        $cfg->{gitcvs}{dbtablenameprefix} || "";
     my %mapping = ( m => $module,
                     a => $state->{method},
                     u => getlogin || getpwuid($<) || $<,
@@ -2374,6 +2384,8 @@ sub new
                     );
     $self->{dbname} =~ s/%([mauGg])/$mapping{$1}/eg;
     $self->{dbuser} =~ s/%([mauGg])/$mapping{$1}/eg;
+    $self->{dbtablenameprefix} =~ s/%([mauGg])/$mapping{$1}/eg;
+    $self->{dbtablenameprefix} = mangle_tablename($self->{dbtablenameprefix});
 
     die "Invalid char ':' in dbdriver" if $self->{dbdriver} =~ /:/;
     die "Invalid char ';' in dbname" if $self->{dbname} =~ /;/;
@@ -2389,10 +2401,13 @@ sub new
     }
 
     # Construct the revision table if required
-    unless ( $self->{tables}{revision} )
+    unless ( $self->{tables}{$self->tablename("revision")} )
     {
+        my $tablename = $self->tablename("revision");
+        my $ix1name = $self->tablename("revision_ix1");
+        my $ix2name = $self->tablename("revision_ix2");
         $self->{dbh}->do("
-            CREATE TABLE revision (
+            CREATE TABLE $tablename (
                 name       TEXT NOT NULL,
                 revision   INTEGER NOT NULL,
                 filehash   TEXT NOT NULL,
@@ -2403,20 +2418,22 @@ sub new
             )
         ");
         $self->{dbh}->do("
-            CREATE INDEX revision_ix1
-            ON revision (name,revision)
+            CREATE INDEX $ix1name
+            ON $tablename (name,revision)
         ");
         $self->{dbh}->do("
-            CREATE INDEX revision_ix2
-            ON revision (name,commithash)
+            CREATE INDEX $ix2name
+            ON $tablename (name,commithash)
         ");
     }
 
     # Construct the head table if required
-    unless ( $self->{tables}{head} )
+    unless ( $self->{tables}{$self->tablename("head")} )
     {
+        my $tablename = $self->tablename("head");
+        my $ix1name = $self->tablename("head_ix1");
         $self->{dbh}->do("
-            CREATE TABLE head (
+            CREATE TABLE $tablename (
                 name       TEXT NOT NULL,
                 revision   INTEGER NOT NULL,
                 filehash   TEXT NOT NULL,
@@ -2427,16 +2444,17 @@ sub new
             )
         ");
         $self->{dbh}->do("
-            CREATE INDEX head_ix1
-            ON head (name)
+            CREATE INDEX $ix1name
+            ON $tablename (name)
         ");
     }
 
     # Construct the properties table if required
-    unless ( $self->{tables}{properties} )
+    unless ( $self->{tables}{$self->tablename("properties")} )
     {
+        my $tablename = $self->tablename("properties");
         $self->{dbh}->do("
-            CREATE TABLE properties (
+            CREATE TABLE $tablename (
                 key        TEXT NOT NULL PRIMARY KEY,
                 value      TEXT
             )
@@ -2444,10 +2462,11 @@ sub new
     }
 
     # Construct the commitmsgs table if required
-    unless ( $self->{tables}{commitmsgs} )
+    unless ( $self->{tables}{$self->tablename("commitmsgs")} )
     {
+        my $tablename = $self->tablename("commitmsgs");
         $self->{dbh}->do("
-            CREATE TABLE commitmsgs (
+            CREATE TABLE $tablename (
                 key        TEXT NOT NULL PRIMARY KEY,
                 value      TEXT
             )
@@ -2457,6 +2476,21 @@ sub new
     return $self;
 }
 
+=head2 tablename
+
+=cut
+sub tablename
+{
+    my $self = shift;
+    my $name = shift;
+
+    if (exists $self->{valid_tables}{$name}) {
+        return $self->{dbtablenameprefix} . $name;
+    } else {
+        return undef;
+    }
+}
+
 =head2 update
 
 =cut
@@ -2822,8 +2856,9 @@ sub insert_rev
     my $modified = shift;
     my $author = shift;
     my $mode = shift;
+    my $tablename = $self->tablename("revision");
 
-    my $insert_rev = $self->{dbh}->prepare_cached("INSERT INTO revision (name, revision, filehash, commithash, modified, author, mode) VALUES (?,?,?,?,?,?,?)",{},1);
+    my $insert_rev = $self->{dbh}->prepare_cached("INSERT INTO $tablename (name, revision, filehash, commithash, modified, author, mode) VALUES (?,?,?,?,?,?,?)",{},1);
     $insert_rev->execute($name, $revision, $filehash, $commithash, $modified, $author, $mode);
 }
 
@@ -2832,16 +2867,18 @@ sub insert_mergelog
     my $self = shift;
     my $key = shift;
     my $value = shift;
+    my $tablename = $self->tablename("commitmsgs");
 
-    my $insert_mergelog = $self->{dbh}->prepare_cached("INSERT INTO commitmsgs (key, value) VALUES (?,?)",{},1);
+    my $insert_mergelog = $self->{dbh}->prepare_cached("INSERT INTO $tablename (key, value) VALUES (?,?)",{},1);
     $insert_mergelog->execute($key, $value);
 }
 
 sub delete_head
 {
     my $self = shift;
+    my $tablename = $self->tablename("head");
 
-    my $delete_head = $self->{dbh}->prepare_cached("DELETE FROM head",{},1);
+    my $delete_head = $self->{dbh}->prepare_cached("DELETE FROM $tablename",{},1);
     $delete_head->execute();
 }
 
@@ -2855,8 +2892,9 @@ sub insert_head
     my $modified = shift;
     my $author = shift;
     my $mode = shift;
+    my $tablename = $self->tablename("head");
 
-    my $insert_head = $self->{dbh}->prepare_cached("INSERT INTO head (name, revision, filehash, commithash, modified, author, mode) VALUES (?,?,?,?,?,?,?)",{},1);
+    my $insert_head = $self->{dbh}->prepare_cached("INSERT INTO $tablename (name, revision, filehash, commithash, modified, author, mode) VALUES (?,?,?,?,?,?,?)",{},1);
     $insert_head->execute($name, $revision, $filehash, $commithash, $modified, $author, $mode);
 }
 
@@ -2864,8 +2902,9 @@ sub _headrev
 {
     my $self = shift;
     my $filename = shift;
+    my $tablename = $self->tablename("head");
 
-    my $db_query = $self->{dbh}->prepare_cached("SELECT filehash, revision, mode FROM head WHERE name=?",{},1);
+    my $db_query = $self->{dbh}->prepare_cached("SELECT filehash, revision, mode FROM $tablename WHERE name=?",{},1);
     $db_query->execute($filename);
     my ( $hash, $revision, $mode ) = $db_query->fetchrow_array;
 
@@ -2876,8 +2915,9 @@ sub _get_prop
 {
     my $self = shift;
     my $key = shift;
+    my $tablename = $self->tablename("properties");
 
-    my $db_query = $self->{dbh}->prepare_cached("SELECT value FROM properties WHERE key=?",{},1);
+    my $db_query = $self->{dbh}->prepare_cached("SELECT value FROM $tablename WHERE key=?",{},1);
     $db_query->execute($key);
     my ( $value ) = $db_query->fetchrow_array;
 
@@ -2889,13 +2929,14 @@ sub _set_prop
     my $self = shift;
     my $key = shift;
     my $value = shift;
+    my $tablename = $self->tablename("properties");
 
-    my $db_query = $self->{dbh}->prepare_cached("UPDATE properties SET value=? WHERE key=?",{},1);
+    my $db_query = $self->{dbh}->prepare_cached("UPDATE $tablename SET value=? WHERE key=?",{},1);
     $db_query->execute($value, $key);
 
     unless ( $db_query->rows )
     {
-        $db_query = $self->{dbh}->prepare_cached("INSERT INTO properties (key, value) VALUES (?,?)",{},1);
+        $db_query = $self->{dbh}->prepare_cached("INSERT INTO $tablename (key, value) VALUES (?,?)",{},1);
         $db_query->execute($key, $value);
     }
 
@@ -2909,10 +2950,11 @@ sub _set_prop
 sub gethead
 {
     my $self = shift;
+    my $tablename = $self->tablename("head");
 
     return $self->{gethead_cache} if ( defined ( $self->{gethead_cache} ) );
 
-    my $db_query = $self->{dbh}->prepare_cached("SELECT name, filehash, mode, revision, modified, commithash, author FROM head ORDER BY name ASC",{},1);
+    my $db_query = $self->{dbh}->prepare_cached("SELECT name, filehash, mode, revision, modified, commithash, author FROM $tablename ORDER BY name ASC",{},1);
     $db_query->execute();
 
     my $tree = [];
@@ -2934,8 +2976,9 @@ sub getlog
 {
     my $self = shift;
     my $filename = shift;
+    my $tablename = $self->tablename("revision");
 
-    my $db_query = $self->{dbh}->prepare_cached("SELECT name, filehash, author, mode, revision, modified, commithash FROM revision WHERE name=? ORDER BY revision DESC",{},1);
+    my $db_query = $self->{dbh}->prepare_cached("SELECT name, filehash, author, mode, revision, modified, commithash FROM $tablename WHERE name=? ORDER BY revision DESC",{},1);
     $db_query->execute($filename);
 
     my $tree = [];
@@ -2959,19 +3002,21 @@ sub getmeta
     my $self = shift;
     my $filename = shift;
     my $revision = shift;
+    my $tablename_rev = $self->tablename("revision");
+    my $tablename_head = $self->tablename("head");
 
     my $db_query;
     if ( defined($revision) and $revision =~ /^\d+$/ )
     {
-        $db_query = $self->{dbh}->prepare_cached("SELECT * FROM revision WHERE name=? AND revision=?",{},1);
+        $db_query = $self->{dbh}->prepare_cached("SELECT * FROM $tablename_rev WHERE name=? AND revision=?",{},1);
         $db_query->execute($filename, $revision);
     }
     elsif ( defined($revision) and $revision =~ /^[a-zA-Z0-9]{40}$/ )
     {
-        $db_query = $self->{dbh}->prepare_cached("SELECT * FROM revision WHERE name=? AND commithash=?",{},1);
+        $db_query = $self->{dbh}->prepare_cached("SELECT * FROM $tablename_rev WHERE name=? AND commithash=?",{},1);
         $db_query->execute($filename, $revision);
     } else {
-        $db_query = $self->{dbh}->prepare_cached("SELECT * FROM head WHERE name=?",{},1);
+        $db_query = $self->{dbh}->prepare_cached("SELECT * FROM $tablename_head WHERE name=?",{},1);
         $db_query->execute($filename);
     }
 
@@ -2987,11 +3032,12 @@ sub commitmessage
 {
     my $self = shift;
     my $commithash = shift;
+    my $tablename = $self->tablename("commitmsgs");
 
     die("Need commithash") unless ( defined($commithash) and $commithash =~ /^[a-zA-Z0-9]{40}$/ );
 
     my $db_query;
-    $db_query = $self->{dbh}->prepare_cached("SELECT value FROM commitmsgs WHERE key=?",{},1);
+    $db_query = $self->{dbh}->prepare_cached("SELECT value FROM $tablename WHERE key=?",{},1);
     $db_query->execute($commithash);
 
     my ( $message ) = $db_query->fetchrow_array;
@@ -3019,9 +3065,10 @@ sub gethistory
 {
     my $self = shift;
     my $filename = shift;
+    my $tablename = $self->tablename("revision");
 
     my $db_query;
-    $db_query = $self->{dbh}->prepare_cached("SELECT revision, filehash, commithash FROM revision WHERE name=? ORDER BY revision DESC",{},1);
+    $db_query = $self->{dbh}->prepare_cached("SELECT revision, filehash, commithash FROM $tablename WHERE name=? ORDER BY revision DESC",{},1);
     $db_query->execute($filename);
 
     return $db_query->fetchall_arrayref;
@@ -3041,9 +3088,10 @@ sub gethistorydense
 {
     my $self = shift;
     my $filename = shift;
+    my $tablename = $self->tablename("revision");
 
     my $db_query;
-    $db_query = $self->{dbh}->prepare_cached("SELECT revision, filehash, commithash FROM revision WHERE name=? AND filehash!='deleted' ORDER BY revision DESC",{},1);
+    $db_query = $self->{dbh}->prepare_cached("SELECT revision, filehash, commithash FROM $tablename WHERE name=? AND filehash!='deleted' ORDER BY revision DESC",{},1);
     $db_query->execute($filename);
 
     return $db_query->fetchall_arrayref;
@@ -3101,4 +3149,19 @@ sub mangle_dirname {
     return $dirname;
 }
 
+=head2 mangle_tablename
+
+create a string from a that is suitable to use as part of an SQL table
+name, mainly by converting all chars except \w to _
+
+=cut
+sub mangle_tablename {
+    my $tablename = shift;
+    return unless defined $tablename;
+
+    $tablename =~ s/[^\w_]/_/g;
+
+    return $tablename;
+}
+
 1;
index 0c2b791eab3de64a8b642460b4b2b959936cca96..1b44cbe10682401b9296d19f7a3595819e60702b 100755 (executable)
@@ -1900,7 +1900,7 @@ sub prop_walk {
 
        foreach (sort keys %$dirent) {
                next if $dirent->{$_}->{kind} != $SVN::Node::dir;
-               $self->prop_walk($path . '/' . $_, $rev, $sub);
+               $self->prop_walk($p . $_, $rev, $sub);
        }
 }
 
diff --git a/git.c b/git.c
index b7729d72cf8dcec32215e968d39dcf675302e216..c4e4644b30e184e6496fb5a4877f3141488f8f44 100644 (file)
--- a/git.c
+++ b/git.c
@@ -148,8 +148,9 @@ static int handle_alias(int *argcp, const char ***argv)
        const char** new_argv;
        const char *alias_command;
        char *alias_string;
+       int unused_nongit;
 
-       subdir = setup_git_directory_gently(NULL);
+       subdir = setup_git_directory_gently(&unused_nongit);
 
        alias_command = (*argv)[0];
        alias_string = alias_lookup(alias_command);
diff --git a/help.c b/help.c
index ecaca770d398e8068ec18e9f4c5058044001d4ea..10298fb0a197f18008783214de11e424fbadb77d 100644 (file)
--- a/help.c
+++ b/help.c
@@ -30,6 +30,7 @@ static struct option builtin_help_options[] = {
                        HELP_FORMAT_WEB),
        OPT_SET_INT('i', "info", &help_format, "show info page",
                        HELP_FORMAT_INFO),
+       OPT_END(),
 };
 
 static const char * const builtin_help_usage[] = {
index 8e64316fe002fe90c58de61e4d6558ee4ad87157..e87cafbe4199acb39fd9113e4b5096de19a3a61c 100644 (file)
@@ -409,3 +409,10 @@ int parse_opt_abbrev_cb(const struct option *opt, const char *arg, int unset)
        *(int *)(opt->value) = v;
        return 0;
 }
+
+int parse_opt_approxidate_cb(const struct option *opt, const char *arg,
+                            int unset)
+{
+       *(unsigned long *)(opt->value) = approxidate(arg);
+       return 0;
+}
index 1af62b0485f2760607b7d3bc3e0ebdca09a53ea4..4ee443dafe146f05d1fe2a46e7e39ca6fdd608f9 100644 (file)
@@ -94,6 +94,9 @@ struct option {
 #define OPT_SET_PTR(s, l, v, h, p)  { OPTION_SET_PTR, (s), (l), (v), NULL, (h), 0, NULL, (p) }
 #define OPT_INTEGER(s, l, v, h)     { OPTION_INTEGER, (s), (l), (v), NULL, (h) }
 #define OPT_STRING(s, l, v, a, h)   { OPTION_STRING,  (s), (l), (v), (a), (h) }
+#define OPT_DATE(s, l, v, h) \
+       { OPTION_CALLBACK, (s), (l), (v), "time",(h), 0, \
+         parse_opt_approxidate_cb }
 #define OPT_CALLBACK(s, l, v, a, h, f) \
        { OPTION_CALLBACK, (s), (l), (v), (a), (h), 0, (f) }
 
@@ -110,6 +113,7 @@ extern NORETURN void usage_with_options(const char * const *usagestr,
 
 /*----- some often used options -----*/
 extern int parse_opt_abbrev_cb(const struct option *, const char *, int);
+extern int parse_opt_approxidate_cb(const struct option *, const char *, int);
 
 #define OPT__VERBOSE(var)  OPT_BOOLEAN('v', "verbose", (var), "be verbose")
 #define OPT__QUIET(var)    OPT_BOOLEAN('q', "quiet",   (var), "be quiet")
diff --git a/t/t2201-add-update-typechange.sh b/t/t2201-add-update-typechange.sh
new file mode 100755 (executable)
index 0000000..e15e3eb
--- /dev/null
@@ -0,0 +1,140 @@
+#!/bin/sh
+
+test_description='more git add -u'
+
+. ./test-lib.sh
+
+_z40=0000000000000000000000000000000000000000
+
+test_expect_success setup '
+       >xyzzy &&
+       _empty=$(git hash-object --stdin <xyzzy) &&
+       >yomin &&
+       >caskly &&
+       ln -s frotz nitfol &&
+       mkdir rezrov &&
+       >rezrov/bozbar &&
+       git add caskly xyzzy yomin nitfol rezrov/bozbar &&
+
+       test_tick &&
+       git commit -m initial
+
+'
+
+test_expect_success modify '
+       rm -f xyzzy yomin nitfol caskly &&
+       # caskly disappears (not a submodule)
+       mkdir caskly &&
+       # nitfol changes from symlink to regular
+       >nitfol &&
+       # rezrov/bozbar disappears
+       rm -fr rezrov &&
+       ln -s xyzzy rezrov &&
+       # xyzzy disappears (not a submodule)
+       mkdir xyzzy &&
+       echo gnusto >xyzzy/bozbar &&
+       # yomin gets replaced with a submodule
+       mkdir yomin &&
+       >yomin/yomin &&
+       (
+               cd yomin &&
+               git init &&
+               git add yomin &&
+               git commit -m "sub initial"
+       ) &&
+       yomin=$(GIT_DIR=yomin/.git git rev-parse HEAD) &&
+       # yonk is added and then turned into a submodule
+       # this should appear as T in diff-files and as A in diff-index
+       >yonk &&
+       git add yonk &&
+       rm -f yonk &&
+       mkdir yonk &&
+       >yonk/yonk &&
+       (
+               cd yonk &&
+               git init &&
+               git add yonk &&
+               git commit -m "sub initial"
+       ) &&
+       yonk=$(GIT_DIR=yonk/.git git rev-parse HEAD) &&
+       # zifmia is added and then removed
+       # this should appear in diff-files but not in diff-index.
+       >zifmia &&
+       git add zifmia &&
+       rm -f zifmia &&
+       mkdir zifmia &&
+       {
+               git ls-tree -r HEAD |
+               sed -e "s/^/:/" -e "
+                       /       caskly/{
+                               s/      caskly/ $_z40 D&/
+                               s/blob/000000/
+                       }
+                       /       nitfol/{
+                               s/      nitfol/ $_z40 T&/
+                               s/blob/100644/
+                       }
+                       /       rezrov.bozbar/{
+                               s/      rezrov.bozbar/ $_z40 D&/
+                               s/blob/000000/
+                       }
+                       /       xyzzy/{
+                               s/      xyzzy/ $_z40 D&/
+                               s/blob/000000/
+                       }
+                       /       yomin/{
+                           s/  yomin/ $_z40 T&/
+                               s/blob/160000/
+                       }
+               "
+       } >expect &&
+       {
+               cat expect
+               echo ":100644 160000 $_empty $_z40 T    yonk"
+               echo ":100644 000000 $_empty $_z40 D    zifmia"
+       } >expect-files &&
+       {
+               cat expect
+               echo ":000000 160000 $_z40 $_z40 A      yonk"
+       } >expect-index &&
+       {
+               echo "100644 $_empty 0  nitfol"
+               echo "160000 $yomin 0   yomin"
+               echo "160000 $yonk 0    yonk"
+       } >expect-final
+'
+
+test_expect_success diff-files '
+       git diff-files --raw >actual &&
+       diff -u expect-files actual
+'
+
+test_expect_success diff-index '
+       git diff-index --raw HEAD -- >actual &&
+       diff -u expect-index actual
+'
+
+test_expect_success 'add -u' '
+       rm -f ".git/saved-index" &&
+       cp -p ".git/index" ".git/saved-index" &&
+       git add -u &&
+       git ls-files -s >actual &&
+       diff -u expect-final actual
+'
+
+test_expect_success 'commit -a' '
+       if test -f ".git/saved-index"
+       then
+               rm -f ".git/index" &&
+               mv ".git/saved-index" ".git/index"
+       fi &&
+       git commit -m "second" -a &&
+       git ls-files -s >actual &&
+       diff -u expect-final actual &&
+       rm -f .git/index &&
+       git read-tree HEAD &&
+       git ls-files -s >actual &&
+       diff -u expect-final actual
+'
+
+test_done
index 47090c4cf528016bf864116232baf29aeb1e4bfe..9fd9d0700033027921c90290cedc0a31d71c7733 100644 (file)
@@ -78,4 +78,38 @@ test_expect_success 'gc: start with ok gc.pruneExpire' '
 
 '
 
+test_expect_success 'prune: prune nonsense parameters' '
+
+       test_must_fail git prune garbage &&
+       test_must_fail git prune --- &&
+       test_must_fail git prune --no-such-option
+
+'
+
+test_expect_success 'prune: prune unreachable heads' '
+
+       git config core.logAllRefUpdates false &&
+       mv .git/logs .git/logs.old &&
+       : > file2 &&
+       git add file2 &&
+       git commit -m temporary &&
+       tmp_head=$(git rev-list -1 HEAD) &&
+       git reset HEAD^ &&
+       git prune &&
+       test_must_fail git reset $tmp_head --
+
+'
+
+test_expect_success 'prune: do not prune heads listed as an argument' '
+
+       : > file2 &&
+       git add file2 &&
+       git commit -m temporary &&
+       tmp_head=$(git rev-list -1 HEAD) &&
+       git reset HEAD^ &&
+       git prune -- $tmp_head &&
+       git reset $tmp_head --
+
+'
+
 test_done
index 75cd33bde8e5906ad68ecdcc904248745d79975c..1a7141ecd7ad1ffcd5081181548920b6a199ab2c 100755 (executable)
@@ -578,6 +578,14 @@ test_expect_success \
        git diff expect actual
 '
 
+# subsequent tests require gpg; check if it is available
+gpg --version >/dev/null
+if [ $? -eq 127 ]; then
+       echo "gpg not found - skipping tag signing and verification tests"
+       test_done
+       exit
+fi
+
 # trying to verify annotated non-signed tags:
 
 test_expect_success \
@@ -600,13 +608,6 @@ test_expect_success \
 
 # creating and verifying signed tags:
 
-gpg --version >/dev/null
-if [ $? -eq 127 ]; then
-       echo "Skipping signed tags tests, because gpg was not found"
-       test_done
-       exit
-fi
-
 # As said here: http://www.gnupg.org/documentation/faqs.html#q6.19
 # the gpg version 1.0.6 didn't parse trust packets correctly, so for
 # that version, creation of signed tags using the generated key fails.