Merge branch 'jc/checkout'
authorJunio C Hamano <junkio@cox.net>
Mon, 26 Dec 2005 07:30:15 +0000 (23:30 -0800)
committerJunio C Hamano <junkio@cox.net>
Mon, 26 Dec 2005 07:30:15 +0000 (23:30 -0800)
13 files changed:
Documentation/git-ls-files.txt
Documentation/tutorial.txt
cache.h
debian/changelog
environment.c
git-clone.sh
git-merge.sh
init-db.c
ls-files.c
mailinfo.c
setup.c
sha1_file.c
show-branch.c

index 2f308ec..186f3bb 100644 (file)
@@ -13,7 +13,8 @@ SYNOPSIS
                (-[c|d|o|i|s|u|k|m])\*
                [-x <pattern>|--exclude=<pattern>]
                [-X <file>|--exclude-from=<file>]
-               [--exclude-per-directory=<file>] [--] [<file>]\*
+               [--exclude-per-directory=<file>] 
+               [--full-name] [--] [<file>]\*
 
 DESCRIPTION
 -----------
@@ -77,6 +78,12 @@ OPTIONS
        K::     to be killed
        ?       other
 
+--full-name::
+       When run from a subdirectory, the command usually
+       outputs paths relative to the current directory.  This
+       option forces paths to be output relative to the project
+       top directory.
+
 --::
        Do not interpret any more arguments as options.
 
index 3a5c56e..edd91cb 100644 (file)
@@ -1695,6 +1695,24 @@ You still need to create UNIX user accounts for each developer,
 and put them in the same group.  Make sure that the repository
 shared among these developers is writable by that group.
 
+. Initializing the shared repository with `git-init-db --shared`
+helps somewhat.
+
+. Run the following in the shared repository:
++
+------------
+$ chgrp -R $group repo.git
+$ find repo.git -type d -print | xargs chmod ug+rwx,g+s
+$ GIT_DIR=repo.git git repo-config core.sharedrepository true
+------------
+
+The above measures make sure that directories lazily created in
+`$GIT_DIR` are writable by group members.  You, as the
+repository administrator, are still responsible to make sure
+your developers belong to that shared repository group and set
+their umask to a value no stricter than 027 (i.e. at least allow
+reading and searching by group members).
+
 You can implement finer grained branch policies using update
 hooks.  There is a document ("control access to branches") in
 Documentation/howto by Carl Baldwin and JC outlining how to (1)
diff --git a/cache.h b/cache.h
index cb87bec..a99fb3c 100644 (file)
--- a/cache.h
+++ b/cache.h
@@ -159,6 +159,7 @@ extern void rollback_index_file(struct cache_file *);
 extern int trust_executable_bit;
 extern int only_use_symrefs;
 extern int diff_rename_limit_default;
+extern int shared_repository;
 
 #define GIT_REPO_VERSION 0
 extern int repository_format_version;
@@ -183,6 +184,7 @@ extern const unsigned char null_sha1[20];
 
 int git_mkstemp(char *path, size_t n, const char *template);
 
+int adjust_shared_perm(const char *path);
 int safe_create_leading_directories(char *path);
 char *safe_strncpy(char *, const char *, size_t);
 char *enter_repo(char *path, int strict);
index 8d6c066..d7f7591 100644 (file)
@@ -10,6 +10,12 @@ git-core (1.0.0.GIT-0) unstable; urgency=low
 
  -- Junio C Hamano <junkio@cox.net>  Wed, 21 Dec 2005 12:12:05 -0800
 
+git-core (1.0.4-0) unstable; urgency=low
+
+  * GIT 1.0.4.
+
+ -- Junio C Hamano <junkio@cox.net>  Sat, 24 Dec 2005 00:01:20 -0800
+
 git-core (1.0.3-0) unstable; urgency=low
 
   * GIT 1.0.3 maintenance release.
index 0886ad3..0596fc6 100644 (file)
@@ -15,6 +15,7 @@ int trust_executable_bit = 1;
 int only_use_symrefs = 0;
 int repository_format_version = 0;
 char git_commit_encoding[MAX_ENCODING_LENGTH] = "utf-8";
+int shared_repository = 0;
 
 static char *git_dir, *git_object_dir, *git_index_file, *git_refs_dir,
        *git_graft_file;
index bfc6c2d..377d59e 100755 (executable)
@@ -31,25 +31,11 @@ clone_dumb_http () {
        cd "$2" &&
        clone_tmp='.git/clone-tmp' &&
        mkdir -p "$clone_tmp" || exit 1
-       http_fetch "$1/info/refs" "$clone_tmp/refs" &&
-       http_fetch "$1/objects/info/packs" "$clone_tmp/packs" || {
+       http_fetch "$1/info/refs" "$clone_tmp/refs" || {
                echo >&2 "Cannot get remote repository information.
 Perhaps git-update-server-info needs to be run there?"
                exit 1;
        }
-       while read type name
-       do
-               case "$type" in
-               P) ;;
-               *) continue ;;
-               esac &&
-
-               idx=`expr "$name" : '\(.*\)\.pack'`.idx
-               http_fetch "$1/objects/pack/$name" ".git/objects/pack/$name" &&
-               http_fetch "$1/objects/pack/$idx" ".git/objects/pack/$idx" &&
-               git-verify-pack ".git/objects/pack/$idx" || exit 1
-       done <"$clone_tmp/packs"
-
        while read sha1 refname
        do
                name=`expr "$refname" : 'refs/\(.*\)'` &&
index e50fbb1..0a158ef 100755 (executable)
@@ -209,6 +209,7 @@ case "$use_strategies" in
 esac
 
 result_tree= best_cnt=-1 best_strategy= wt_strategy=
+merge_was_ok=
 for strategy in $use_strategies
 do
     test "$wt_strategy" = '' || {
@@ -228,6 +229,7 @@ do
     exit=$?
     if test "$no_commit" = t && test "$exit" = 0
     then
+        merge_was_ok=t
        exit=1 ;# pretend it left conflicts.
     fi
 
@@ -293,4 +295,11 @@ do
 done >"$GIT_DIR/MERGE_HEAD"
 echo $merge_msg >"$GIT_DIR/MERGE_MSG"
 
-die "Automatic merge failed/prevented; fix up by hand"
+if test "$merge_was_ok" = t
+then
+       echo >&2 \
+       "Automatic merge went well; stopped before committing as requested"
+       exit 0
+else
+       die "Automatic merge failed; fix up by hand"
+fi
index ead37b5..ff29496 100644 (file)
--- a/init-db.c
+++ b/init-db.c
@@ -9,7 +9,7 @@
 #define DEFAULT_GIT_TEMPLATE_DIR "/usr/share/git-core/templates/"
 #endif
 
-static void safe_create_dir(const char *dir)
+static void safe_create_dir(const char *dir, int share)
 {
        if (mkdir(dir, 0777) < 0) {
                if (errno != EEXIST) {
@@ -17,6 +17,8 @@ static void safe_create_dir(const char *dir)
                        exit(1);
                }
        }
+       else if (share && adjust_shared_perm(dir))
+               die("Could not make %s writable by group\n", dir);
 }
 
 static int copy_file(const char *dst, const char *src, int mode)
@@ -32,6 +34,10 @@ static int copy_file(const char *dst, const char *src, int mode)
        }
        status = copy_fd(fdi, fdo);
        close(fdo);
+
+       if (!status && adjust_shared_perm(dst))
+               return -1;
+
        return status;
 }
 
@@ -48,7 +54,7 @@ static void copy_templates_1(char *path, int baselen,
         * with the way the namespace under .git/ is organized, should
         * be really carefully chosen.
         */
-       safe_create_dir(path);
+       safe_create_dir(path, 1);
        while ((de = readdir(dir)) != NULL) {
                struct stat st_git, st_template;
                int namelen;
@@ -176,11 +182,11 @@ static void create_default_files(const char *git_dir, char *template_path)
         * Create .git/refs/{heads,tags}
         */
        strcpy(path + len, "refs");
-       safe_create_dir(path);
+       safe_create_dir(path, 1);
        strcpy(path + len, "refs/heads");
-       safe_create_dir(path);
+       safe_create_dir(path, 1);
        strcpy(path + len, "refs/tags");
-       safe_create_dir(path);
+       safe_create_dir(path, 1);
 
        /* First copy the templates -- we might have the default
         * config file there, in which case we would want to read
@@ -220,7 +226,7 @@ static void create_default_files(const char *git_dir, char *template_path)
 }
 
 static const char init_db_usage[] =
-"git-init-db [--template=<template-directory>]";
+"git-init-db [--template=<template-directory>] [--shared]";
 
 /*
  * If you want to, you can share the DB area with any number of branches.
@@ -239,6 +245,8 @@ int main(int argc, char **argv)
                char *arg = argv[1];
                if (!strncmp(arg, "--template=", 11))
                        template_dir = arg+11;
+               else if (!strcmp(arg, "--shared"))
+                       shared_repository = 1;
                else
                        die(init_db_usage);
        }
@@ -251,7 +259,7 @@ int main(int argc, char **argv)
                git_dir = DEFAULT_GIT_DIR_ENVIRONMENT;
                fprintf(stderr, "defaulting to local storage area\n");
        }
-       safe_create_dir(git_dir);
+       safe_create_dir(git_dir, 0);
 
        /* Check to see if the repository version is right.
         * Note that a newly created repository does not have
@@ -270,10 +278,14 @@ int main(int argc, char **argv)
        path = xmalloc(len + 40);
        memcpy(path, sha1_dir, len);
 
-       safe_create_dir(sha1_dir);
+       safe_create_dir(sha1_dir, 1);
        strcpy(path+len, "/pack");
-       safe_create_dir(path);
+       safe_create_dir(path, 1);
        strcpy(path+len, "/info");
-       safe_create_dir(path);
+       safe_create_dir(path, 1);
+
+       if (shared_repository)
+               git_config_set("core.sharedRepository", "true");
+
        return 0;
 }
index f3f1a6a..5e9ac71 100644 (file)
@@ -562,7 +562,7 @@ static void verify_pathspec(void)
 static const char ls_files_usage[] =
        "git-ls-files [-z] [-t] (--[cached|deleted|others|stage|unmerged|killed|modified])* "
        "[ --ignored ] [--exclude=<pattern>] [--exclude-from=<file>] "
-       "[ --exclude-per-directory=<filename> ] [--] [<file>]*";
+       "[ --exclude-per-directory=<filename> ] [--full-name] [--] [<file>]*";
 
 int main(int argc, const char **argv)
 {
index 9f95f37..0265a29 100644 (file)
@@ -472,7 +472,7 @@ static void convert_to_utf8(char *line, char *charset)
        char *in, *out;
        size_t insize, outsize, nrc;
        char outbuf[4096]; /* cheat */
-       static char latin_one[] = "latin-1";
+       static char latin_one[] = "latin1";
        char *input_charset = *charset ? charset : latin_one;
        iconv_t conv = iconv_open(metainfo_charset, input_charset);
 
diff --git a/setup.c b/setup.c
index d3556ed..36ede3d 100644 (file)
--- a/setup.c
+++ b/setup.c
@@ -180,6 +180,8 @@ int check_repository_format_version(const char *var, const char *value)
 {
        if (strcmp(var, "core.repositoryformatversion") == 0)
                repository_format_version = git_config_int(var, value);
+       else if (strcmp(var, "core.sharedrepository") == 0)
+               shared_repository = git_config_bool(var, value);
        return 0;
 }
 
index 6b7577d..8bebbb2 100644 (file)
@@ -48,6 +48,29 @@ int get_sha1_hex(const char *hex, unsigned char *sha1)
        return 0;
 }
 
+int adjust_shared_perm(const char *path)
+{
+       struct stat st;
+       int mode;
+
+       if (!shared_repository)
+               return 0;
+       if (lstat(path, &st) < 0)
+               return -1;
+       mode = st.st_mode;
+       if (mode & S_IRUSR)
+               mode |= S_IRGRP;
+       if (mode & S_IWUSR)
+               mode |= S_IWGRP;
+       if (mode & S_IXUSR)
+               mode |= S_IXGRP;
+       if (S_ISDIR(mode))
+               mode |= S_ISGID;
+       if (chmod(path, mode) < 0)
+               return -2;
+       return 0;
+}
+
 int safe_create_leading_directories(char *path)
 {
        char *pos = path;
@@ -59,11 +82,16 @@ int safe_create_leading_directories(char *path)
                if (!pos)
                        break;
                *pos = 0;
-               if (mkdir(path, 0777) < 0)
+               if (mkdir(path, 0777) < 0) {
                        if (errno != EEXIST) {
                                *pos = '/';
                                return -1;
                        }
+               }
+               else if (adjust_shared_perm(path)) {
+                       *pos = '/';
+                       return -2;
+               }
                *pos++ = '/';
        }
        return 0;
@@ -1255,6 +1283,8 @@ static int link_temp_to_file(const char *tmpfile, char *filename)
                if (dir) {
                        *dir = 0;
                        mkdir(filename, 0777);
+                       if (adjust_shared_perm(filename))
+                               return -2;
                        *dir = '/';
                        if (!link(tmpfile, filename))
                                return 0;
index 3fe62b7..15b1968 100644 (file)
@@ -284,10 +284,54 @@ static void show_one_commit(struct commit *commit, int no_name)
 static char *ref_name[MAX_REVS + 1];
 static int ref_name_cnt;
 
+static const char *find_digit_prefix(const char *s, int *v)
+{
+       const char *p;
+       int ver;
+       char ch;
+
+       for (p = s, ver = 0;
+            '0' <= (ch = *p) && ch <= '9';
+            p++)
+               ver = ver * 10 + ch - '0';
+       *v = ver;
+       return p;
+}
+
+
+static int version_cmp(const char *a, const char *b)
+{
+       while (1) {
+               int va, vb;
+
+               a = find_digit_prefix(a, &va);
+               b = find_digit_prefix(b, &vb);
+               if (va != vb)
+                       return va - vb;
+
+               while (1) {
+                       int ca = *a;
+                       int cb = *b;
+                       if ('0' <= ca && ca <= '9')
+                               ca = 0;
+                       if ('0' <= cb && cb <= '9')
+                               cb = 0;
+                       if (ca != cb)
+                               return ca - cb;
+                       if (!ca)
+                               break;
+                       a++;
+                       b++;
+               }
+               if (!*a && !*b)
+                       return 0;
+       }
+}
+
 static int compare_ref_name(const void *a_, const void *b_)
 {
        const char * const*a = a_, * const*b = b_;
-       return strcmp(*a, *b);
+       return version_cmp(*a, *b);
 }
 
 static void sort_ref_range(int bottom, int top)
@@ -299,8 +343,15 @@ static void sort_ref_range(int bottom, int top)
 static int append_ref(const char *refname, const unsigned char *sha1)
 {
        struct commit *commit = lookup_commit_reference_gently(sha1, 1);
+       int i;
+
        if (!commit)
                return 0;
+       /* Avoid adding the same thing twice */
+       for (i = 0; i < ref_name_cnt; i++)
+               if (!strcmp(refname, ref_name[i]))
+                       return 0;
+
        if (MAX_REVS <= ref_name_cnt) {
                fprintf(stderr, "warning: ignoring %s; "
                        "cannot handle more than %d refs\n",
@@ -512,19 +563,17 @@ int main(int ac, char **av)
        if (1 < independent + merge_base + (extra != 0))
                usage(show_branch_usage);
 
+       /* If nothing is specified, show all branches by default */
+       if (ac + all_heads + all_tags == 0)
+               all_heads = 1;
+
        if (all_heads + all_tags)
                snarf_refs(all_heads, all_tags);
-
-       if (ac) {
-               while (0 < ac) {
-                       append_one_rev(*av);
-                       ac--; av++;
-               }
-       }
-       else {
-               /* If no revs given, then add heads */
-               snarf_refs(1, 0);
+       while (0 < ac) {
+               append_one_rev(*av);
+               ac--; av++;
        }
+
        if (!ref_name_cnt) {
                fprintf(stderr, "No revs to be shown.\n");
                exit(0);