author | Junio C Hamano <junkio@cox.net> | |
Tue, 27 Dec 2005 02:45:30 +0000 (18:45 -0800) | ||
committer | Junio C Hamano <junkio@cox.net> | |
Tue, 27 Dec 2005 02:45:30 +0000 (18:45 -0800) |
19 files changed:
Documentation/git-clone.txt | patch | blob | history | |
Documentation/git-rev-parse.txt | patch | blob | history | |
Documentation/tutorial.txt | patch | blob | history | |
Makefile | patch | blob | history | |
cache.h | patch | blob | history | |
connect.c | patch | blob | history | |
debian/changelog | patch | blob | history | |
environment.c | patch | blob | history | |
git-checkout.sh | patch | blob | history | |
git-clone.sh | patch | blob | history | |
git-merge-recursive.py | patch | blob | history | |
git-whatchanged.sh | patch | blob | history | |
init-db.c | patch | blob | history | |
ls-tree.c | patch | blob | history | |
pack-redundant.c | patch | blob | history | |
rev-parse.c | patch | blob | history | |
setup.c | patch | blob | history | |
sha1_file.c | patch | blob | history | |
t/t6022-merge-rename.sh | patch | blob | history |
index 8410a6d3814b0daf463a052275466dfa63a820e9..f943f267da0356d6e129f10117fce16e19aba939 100644 (file)
SYNOPSIS
--------
-'git-clone' [-l [-s]] [-q] [-n] [-u <upload-pack>] <repository> [<directory>]
+'git-clone' [-l [-s]] [-q] [-n] [-o <name>] [-u <upload-pack>] <repository> [<directory>]
DESCRIPTION
-----------
-n::
No checkout of HEAD is performed after the clone is complete.
+-o <name>::
+ Instead of using the branch name 'origin' to keep track
+ of the upstream repository, use <name> instead. Note
+ that the shorthand name stored in `remotes/origin` is
+ not affected, but the local branch name to pull the
+ remote `master` branch into is.
+
--upload-pack <upload-pack>::
-u <upload-pack>::
When given, and the repository to clone from is handled
index 431b8f6e06194e302aac02fdf90522e6f5c04167..d638bfc202ef9ad0386d640cbf70b9cdb2fff665 100644 (file)
Show all refs found in `$GIT_DIR/refs`.
--show-prefix::
- When the command is invoked from a directory show the
+ When the command is invoked from a subdirectory, show the
path of the current directory relative to the top-level
directory.
+--show-cdup::
+ When the command is invoked from a subdirectory, show the
+ path of the top-level directory relative to the current
+ directory (typically a sequence of "../", or an empty string).
+
--since=datestring, --after=datestring::
Parses the date string, and outputs corresponding
--max-age= parameter for git-rev-list command.
index 3a5c56e24edfe7a970e6dcd346f8c0a346cdbfd8..edd91cbbe42bec1ee406dd95d82832575d89d3a6 100644 (file)
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/Makefile b/Makefile
index a5ca5db3129ab21256c8be5b03645f7d032cd5a2..3395a9e102957b02bbc6e1c25c56c8a97b8e5c76 100644 (file)
--- a/Makefile
+++ b/Makefile
# Define USE_STDEV below if you want git to care about the underlying device
# change being considered an inode change from the update-cache perspective.
-GIT_VERSION = 1.0.5
+GIT_VERSION = 1.0.GIT
# CFLAGS and LDFLAGS are for the users to override from the command line.
index cb87becb3aaea75915a65e99565c418d6765174b..a99fb3ce7d3423d51f5a0829a4bd20f0cd5ca0e1 100644 (file)
--- a/cache.h
+++ b/cache.h
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;
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);
diff --git a/connect.c b/connect.c
index 93f6f80d3e8c5f1592353b6feadb9de2c768b649..6b6d6133a0ad943c3b6018541a656a66833b85d2 100644 (file)
--- a/connect.c
+++ b/connect.c
{
char command[1024];
char *host, *path = url;
- char *colon = NULL;
+ char *end;
+ int c;
int pipefd[2][2];
pid_t pid;
enum protocol protocol = PROTO_LOCAL;
*host = '\0';
protocol = get_protocol(url);
host += 3;
- path = strchr(host, '/');
- }
- else {
+ c = '/';
+ } else {
host = url;
- if ((colon = strchr(host, ':'))) {
+ c = ':';
+ }
+
+ if (host[0] == '[') {
+ end = strchr(host + 1, ']');
+ if (end) {
+ *end = 0;
+ end++;
+ host++;
+ } else
+ end = host;
+ } else
+ end = host;
+
+ path = strchr(end, c);
+ if (c == ':') {
+ if (path) {
protocol = PROTO_SSH;
- *colon = '\0';
- path = colon + 1;
- }
+ *path++ = '\0';
+ } else
+ path = host;
}
if (!path || !*path)
diff --git a/debian/changelog b/debian/changelog
index 88e5755f79edaee45687fbacf1b9fb06fb44e5e7..d7f75910798c14e21107c26c97f76292fb3c62a9 100644 (file)
--- a/debian/changelog
+++ b/debian/changelog
+git-core (1.0.GIT-0) unstable; urgency=low
+
+ * Post GIT 1.0 development track.
+
+ -- Junio C Hamano <junkio@cox.net> Wed, 21 Dec 2005 22:28:33 -0800
+
+git-core (1.0.0.GIT-0) unstable; urgency=low
+
+ * Post GIT 1.0.0 development track.
+
+ -- 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.
diff --git a/environment.c b/environment.c
index 0886ad38f94ddb897629d832160333921ac89481..0596fc647be37343371ae5a266906dab35707076 100644 (file)
--- a/environment.c
+++ b/environment.c
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;
diff --git a/git-checkout.sh b/git-checkout.sh
index 36308d22c6a72b9ad53ced60bd3c70a2e17520b6..3bbd1117739b02572aece86030bb9f02f3110d34 100755 (executable)
--- a/git-checkout.sh
+++ b/git-checkout.sh
#!/bin/sh
USAGE='[-f] [-b <new_branch>] [<branch>] [<paths>...]'
+SUBDIRECTORY_OK=Sometimes
. git-sh-setup
old=$(git-rev-parse HEAD)
# from a specific tree-ish; note that this is for
# rescuing paths and is never meant to remove what
# is not in the named tree-ish.
- git-ls-tree -r "$new" "$@" |
+ git-ls-tree --full-name -r "$new" "$@" |
git-update-index --index-info || exit $?
fi
git-checkout-index -f -u -- "$@"
fi
fi
+# We are switching branches and checking out trees, so
+# we *NEED* to be at the toplevel.
+cdup=$(git-rev-parse --show-cdup)
+if test ! -z "$cdup"
+then
+ cd "$cdup"
+fi
+
[ -z "$new" ] && new=$old
# If we don't have an old branch that we're switching to,
diff --git a/git-clone.sh b/git-clone.sh
index 280cc2e81e98c5fe69e8528ca97069dd0b0e59f5..377d59e62cecd305fc7cf69aa927b13225fdb3eb 100755 (executable)
--- a/git-clone.sh
+++ b/git-clone.sh
unset CDPATH
usage() {
- echo >&2 "Usage: $0 [-l [-s]] [-q] [-u <upload-pack>] [-n] <repo> [<dir>]"
+ echo >&2 "Usage: $0 [-l [-s]] [-q] [-u <upload-pack>] [-o <name>] [-n] <repo> [<dir>]"
exit 1
}
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/\(.*\)'` &&
local_shared=no
no_checkout=
upload_pack=
+origin=origin
while
case "$#,$1" in
0,*) break ;;
*,-s|*,--s|*,--sh|*,--sha|*,--shar|*,--share|*,--shared)
local_shared=yes; use_local=yes ;;
*,-q|*,--quiet) quiet=-q ;;
+ 1,-o) usage;;
+ *,-o)
+ git-check-ref-format "$2" || {
+ echo >&2 "'$2' is not suitable for a branch name"
+ exit 1
+ }
+ origin="$2"; shift
+ ;;
1,-u|1,--upload-pack) usage ;;
*,-u|*,--upload-pack)
shift
mkdir -p .git/remotes &&
echo >.git/remotes/origin \
"URL: $repo
-Pull: $head_points_at:origin" &&
- cp ".git/refs/heads/$head_points_at" .git/refs/heads/origin &&
+Pull: $head_points_at:$origin" &&
+ git-update-ref "refs/heads/$origin" $(git-rev-parse HEAD) &&
find .git/refs/heads -type f -print |
while read ref
do
head=`expr "$ref" : '.git/refs/heads/\(.*\)'` &&
test "$head_points_at" = "$head" ||
- test "origin" = "$head" ||
+ test "$origin" = "$head" ||
echo "Pull: ${head}:${head}"
done >>.git/remotes/origin
esac
diff --git a/git-merge-recursive.py b/git-merge-recursive.py
index f1320a69581500f3c70f0eb556e195a7e47e8714..56c3641abbe872bd44ec6c7745e6bc3705874869 100755 (executable)
--- a/git-merge-recursive.py
+++ b/git-merge-recursive.py
def setIndexStages(path,
oSHA1, oMode,
aSHA1, aMode,
- bSHA1, bMode):
+ bSHA1, bMode,
+ clear=True):
+ istring = []
+ if clear:
+ istring.append("0 " + ("0" * 40) + "\t" + path + "\0")
+ if oMode:
+ istring.append("%o %s %d\t%s\0" % (oMode, oSHA1, 1, path))
+ if aMode:
+ istring.append("%o %s %d\t%s\0" % (aMode, aSHA1, 2, path))
+ if bMode:
+ istring.append("%o %s %d\t%s\0" % (bMode, bSHA1, 3, path))
+
runProgram(['git-update-index', '-z', '--index-info'],
- input="0 " + ("0" * 40) + "\t" + path + "\0" + \
- "%o %s %d\t%s\0" % (oMode, oSHA1, 1, path) + \
- "%o %s %d\t%s\0" % (aMode, aSHA1, 2, path) + \
- "%o %s %d\t%s\0" % (bMode, bSHA1, 3, path))
+ input="".join(istring))
def removeFile(clean, path):
updateCache = cacheOnly or clean
continue
ren1.processed = True
- removeFile(True, ren1.srcName)
+
if ren2:
# Renamed in 1 and renamed in 2
assert(ren1.srcName == ren2.srcName)
'adding as', dstName2, 'instead.')
removeFile(False, ren2.dstName)
else:
- dstName2 = ren1.dstName
+ dstName2 = ren2.dstName
+ setIndexStages(dstName1,
+ None, None,
+ ren1.dstSha, ren1.dstMode,
+ None, None)
+ setIndexStages(dstName2,
+ None, None,
+ None, None,
+ ren2.dstSha, ren2.dstMode)
- # NEEDSWORK: place dstNameA at stage 2 and dstNameB at stage 3
- # What about other stages???
- updateFile(False, ren1.dstSha, ren1.dstMode, dstName1)
- updateFile(False, ren2.dstSha, ren2.dstMode, dstName2)
else:
+ removeFile(True, ren1.srcName)
+
[resSha, resMode, clean, merge] = \
mergeFile(ren1.srcName, ren1.srcSha, ren1.srcMode,
ren1.dstName, ren1.dstSha, ren1.dstMode,
updateFile(clean, resSha, resMode, ren1.dstName)
else:
+ removeFile(True, ren1.srcName)
+
# Renamed in 1, maybe changed in 2
if renamesA == renames1:
stage = 3
diff --git a/git-whatchanged.sh b/git-whatchanged.sh
index b170f74a94e42dbf82f2e94b831f1cf6b49a2b4c..80e2500e0ea1769d9d92454c667852dd2056ef04 100755 (executable)
--- a/git-whatchanged.sh
+++ b/git-whatchanged.sh
SUBDIRECTORY_OK='Yes'
. git-sh-setup
+diff_tree_flags=$(git-rev-parse --sq --no-revs --flags "$@")
+test -z "$diff_tree_flags" &&
+ diff_tree_flags=$(git-repo-config --get whatchanged.difftree)
+test -z "$diff_tree_flags" &&
+ diff_tree_flags='-M --abbrev'
+
rev_list_args=$(git-rev-parse --sq --default HEAD --revs-only "$@") &&
-diff_tree_args=$(git-rev-parse --sq --no-revs "$@") &&
+diff_tree_args=$(git-rev-parse --sq --no-revs --no-flags "$@") &&
eval "git-rev-list $rev_list_args" |
-eval "git-diff-tree --stdin --pretty -r $diff_tree_args" |
+eval "git-diff-tree --stdin --pretty -r $diff_tree_flags $diff_tree_args" |
LESS="$LESS -S" ${PAGER:-less}
diff --git a/init-db.c b/init-db.c
index ead37b5ed86e5ae96c18d081fbfffd65ed74dce8..ff294960f29c8763e34e28060dee04b799bd55fd 100644 (file)
--- a/init-db.c
+++ b/init-db.c
#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) {
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)
}
status = copy_fd(fdi, fdo);
close(fdo);
+
+ if (!status && adjust_shared_perm(dst))
+ return -1;
+
return status;
}
* 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;
* 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
}
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.
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);
}
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
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;
}
diff --git a/ls-tree.c b/ls-tree.c
index dae377d99585d4e6a176f85f0101d8ae29668f2f..d585b6fc13f4b980fa237067157de96e8e7ef601 100644 (file)
--- a/ls-tree.c
+++ b/ls-tree.c
#define LS_NAME_ONLY 8
static int ls_options = 0;
const char **pathspec;
+static int chomp_prefix = 0;
+static const char *prefix;
static const char ls_tree_usage[] =
- "git-ls-tree [-d] [-r] [-t] [-z] [--name-only] [--name-status] <tree-ish> [path...]";
+ "git-ls-tree [-d] [-r] [-t] [-z] [--name-only] [--name-status] [--full-name] <tree-ish> [path...]";
static int show_recursive(const char *base, int baselen, const char *pathname)
{
}
}
-static int show_tree(unsigned char *sha1, const char *base, int baselen, const char *pathname, unsigned mode, int stage)
+static int show_tree(unsigned char *sha1, const char *base, int baselen,
+ const char *pathname, unsigned mode, int stage)
{
int retval = 0;
const char *type = "blob";
@@ -65,21 +68,28 @@ static int show_tree(unsigned char *sha1, const char *base, int baselen, const c
else if (ls_options & LS_TREE_ONLY)
return 0;
+ if (chomp_prefix &&
+ (baselen < chomp_prefix || memcmp(prefix, base, chomp_prefix)))
+ return 0;
+
if (!(ls_options & LS_NAME_ONLY))
printf("%06o %s %s\t", mode, type, sha1_to_hex(sha1));
- write_name_quoted(base, baselen, pathname, line_termination, stdout);
+ write_name_quoted(base + chomp_prefix, baselen - chomp_prefix,
+ pathname,
+ line_termination, stdout);
putchar(line_termination);
return retval;
}
int main(int argc, const char **argv)
{
- const char *prefix;
unsigned char sha1[20];
char *buf;
unsigned long size;
prefix = setup_git_directory();
+ if (prefix && *prefix)
+ chomp_prefix = strlen(prefix);
while (1 < argc && argv[1][0] == '-') {
switch (argv[1][1]) {
case 'z':
ls_options |= LS_NAME_ONLY;
break;
}
+ if (!strcmp(argv[1]+2, "full-name")) {
+ chomp_prefix = 0;
+ break;
+ }
/* otherwise fallthru */
default:
usage(ls_tree_usage);
diff --git a/pack-redundant.c b/pack-redundant.c
index 0a43278924edae9d6e3ecdf4bb100bea10faef97..1869b38b726b3760f279076af43006be9f1c5acf 100644 (file)
--- a/pack-redundant.c
+++ b/pack-redundant.c
#include "cache.h"
+#define BLKSIZE 512
+
static const char pack_redundant_usage[] =
"git-pack-redundant [ --verbose ] [ --alt-odb ] < --all | <.pack filename> ...>";
struct pll {
struct pll *next;
struct pack_list *pl;
- size_t pl_size;
};
static struct llist_item *free_nodes = NULL;
+static inline void llist_item_put(struct llist_item *item)
+{
+ item->next = free_nodes;
+ free_nodes = item;
+}
+
static inline struct llist_item *llist_item_get()
{
struct llist_item *new;
if ( free_nodes ) {
new = free_nodes;
free_nodes = free_nodes->next;
- } else
- new = xmalloc(sizeof(struct llist_item));
-
+ } else {
+ int i = 1;
+ new = xmalloc(sizeof(struct llist_item) * BLKSIZE);
+ for(;i < BLKSIZE; i++) {
+ llist_item_put(&new[i]);
+ }
+ }
return new;
}
-static inline void llist_item_put(struct llist_item *item)
-{
- item->next = free_nodes;
- free_nodes = item;
-}
-
static void llist_free(struct llist *list)
{
while((list->back = list->front)) {
}
}
-static void pll_insert(struct pll **pll, struct pll **hint_table)
+void pll_free(struct pll *l)
{
- struct pll *prev;
- int i = (*pll)->pl_size - 1;
-
- if (hint_table[i] == NULL) {
- hint_table[i--] = *pll;
- for (; i >= 0; --i) {
- if (hint_table[i] != NULL)
- break;
+ struct pll *old;
+ struct pack_list *opl;
+
+ while (l) {
+ old = l;
+ while (l->pl) {
+ opl = l->pl;
+ l->pl = opl->next;
+ free(opl);
}
- if (hint_table[i] == NULL) /* no elements in list */
- die("Why did this happen?");
+ l = l->next;
+ free(old);
}
-
- prev = hint_table[i];
- while (prev->next && prev->next->pl_size < (*pll)->pl_size)
- prev = prev->next;
-
- (*pll)->next = prev->next;
- prev->next = *pll;
}
/* all the permutations have to be free()d at the same time,
* since they refer to each other
*/
-static struct pll * get_all_permutations(struct pack_list *list)
+static struct pll * get_permutations(struct pack_list *list, int n)
{
- struct pll *subset, *pll, *new_pll = NULL; /*silence warning*/
- static struct pll **hint = NULL;
- if (hint == NULL)
- hint = xcalloc(pack_list_size(list), sizeof(struct pll *));
-
- if (list == NULL)
+ struct pll *subset, *ret = NULL, *new_pll = NULL, *pll;
+
+ if (list == NULL || pack_list_size(list) < n || n == 0)
return NULL;
- if (list->next == NULL) {
- new_pll = xmalloc(sizeof(struct pll));
- hint[0] = new_pll;
- new_pll->next = NULL;
- new_pll->pl = list;
- new_pll->pl_size = 1;
- return new_pll;
+ if (n == 1) {
+ while (list) {
+ new_pll = xmalloc(sizeof(pll));
+ new_pll->pl = NULL;
+ pack_list_insert(&new_pll->pl, list);
+ new_pll->next = ret;
+ ret = new_pll;
+ list = list->next;
+ }
+ return ret;
}
- pll = subset = get_all_permutations(list->next);
- while (pll) {
- if (pll->pl->pack == list->pack) {
- pll = pll->next;
- continue;
+ while (list->next) {
+ subset = get_permutations(list->next, n - 1);
+ while (subset) {
+ new_pll = xmalloc(sizeof(pll));
+ new_pll->pl = subset->pl;
+ pack_list_insert(&new_pll->pl, list);
+ new_pll->next = ret;
+ ret = new_pll;
+ subset = subset->next;
}
- new_pll = xmalloc(sizeof(struct pll));
-
- new_pll->pl = xmalloc(sizeof(struct pack_list));
- memcpy(new_pll->pl, list, sizeof(struct pack_list));
- new_pll->pl->next = pll->pl;
- new_pll->pl_size = pll->pl_size + 1;
-
- pll_insert(&new_pll, hint);
-
- pll = pll->next;
- }
- /* add ourself */
- new_pll = xmalloc(sizeof(struct pll));
- new_pll->pl = xmalloc(sizeof(struct pack_list));
- memcpy(new_pll->pl, list, sizeof(struct pack_list));
- new_pll->pl->next = NULL;
- new_pll->pl_size = 1;
- pll_insert(&new_pll, hint);
-
- return hint[0];
+ list = list->next;
+ }
+ return ret;
}
static int is_superset(struct pack_list *pl, struct llist *list)
struct pll *perm, *perm_all, *perm_ok = NULL, *new_perm;
struct llist *missing;
size_t min_perm_size = (size_t)-1, perm_size;
+ int n;
pl = local_packs;
while (pl) {
missing = llist_copy(all_objects);
pl = unique;
while (pl) {
- llist_sorted_difference_inplace(missing,
- pl->all_objects);
+ llist_sorted_difference_inplace(missing, pl->all_objects);
pl = pl->next;
}
}
/* find the permutations which contain all missing objects */
- perm_all = perm = get_all_permutations(non_unique);
- while (perm) {
- if (perm_ok && perm->pl_size > perm_ok->pl_size)
- break; /* ignore all larger permutations */
- if (is_superset(perm->pl, missing)) {
- new_perm = xmalloc(sizeof(struct pll));
- memcpy(new_perm, perm, sizeof(struct pll));
- new_perm->next = perm_ok;
- perm_ok = new_perm;
+ for (n = 1; n <= pack_list_size(non_unique) && !perm_ok; n++) {
+ perm_all = perm = get_permutations(non_unique, n);
+ while (perm) {
+ if (is_superset(perm->pl, missing)) {
+ new_perm = xmalloc(sizeof(struct pll));
+ memcpy(new_perm, perm, sizeof(struct pll));
+ new_perm->next = perm_ok;
+ perm_ok = new_perm;
+ }
+ perm = perm->next;
}
- perm = perm->next;
+ if (perm_ok)
+ break;
+ pll_free(perm_all);
}
-
if (perm_ok == NULL)
die("Internal error: No complete sets found!\n");
alt->all_objects);
local = local->next;
}
+ llist_sorted_difference_inplace(all_objects, alt->all_objects);
alt = alt->next;
}
}
diff --git a/rev-parse.c b/rev-parse.c
index bb4949ad70364abdf7c3bbca357e5ebc42880614..0c951af0d49da459fc6c85c32707b016bf581a57 100644 (file)
--- a/rev-parse.c
+++ b/rev-parse.c
puts(prefix);
continue;
}
+ if (!strcmp(arg, "--show-cdup")) {
+ const char *pfx = prefix;
+ while (pfx) {
+ pfx = strchr(pfx, '/');
+ if (pfx) {
+ pfx++;
+ printf("../");
+ }
+ }
+ putchar('\n');
+ continue;
+ }
if (!strcmp(arg, "--git-dir")) {
const char *gitdir = getenv(GIT_DIR_ENVIRONMENT);
static char cwd[PATH_MAX];
index d3556edf121ba78b0b83d20fdbd9cb397e79eb2b..36ede3d87483548bb1ce6c19361d7f6584386147 100644 (file)
--- a/setup.c
+++ b/setup.c
{
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;
}
diff --git a/sha1_file.c b/sha1_file.c
index 6b7577dbc4ed845da1a70b6d727370423b086735..8bebbb255f762fc36f165b87023d8cc37732968a 100644 (file)
--- a/sha1_file.c
+++ b/sha1_file.c
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;
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;
if (dir) {
*dir = 0;
mkdir(filename, 0777);
+ if (adjust_shared_perm(filename))
+ return -2;
*dir = '/';
if (!link(tmpfile, filename))
return 0;
index 153b9e49f26502ce6b9d0ceb9ae83839ecc3becc..1292cafd7f1f7fc30b462d4e07be34383e9d6be9 100755 (executable)
--- a/t/t6022-merge-rename.sh
+++ b/t/t6022-merge-rename.sh
}
'
+test_expect_success 'pull conflicting renames' \
+'
+ git reset --hard
+ git show-branch
+ git pull . blue && {
+ echo "BAD: should have conflicted"
+ exit 1
+ }
+ test "$(git ls-files -u A | wc -l)" -eq 1 || {
+ echo "BAD: should have left a stage"
+ exit 1
+ }
+ test "$(git ls-files -u B | wc -l)" -eq 1 || {
+ echo "BAD: should have left a stage"
+ exit 1
+ }
+ test "$(git ls-files -u C | wc -l)" -eq 1 || {
+ echo "BAD: should have left a stage"
+ exit 1
+ }
+ test "$(git ls-files -s N | wc -l)" -eq 1 || {
+ echo "BAD: should have merged N"
+ exit 1
+ }
+ sed -ne "/^g/{
+ p
+ q
+ }" B | grep red || {
+ echo "BAD: should have listed our change first"
+ exit 1
+ }
+ test "$(git diff white N | wc -l)" -eq 0 || {
+ echo "BAD: should have taken colored branch"
+ exit 1
+ }
+'
+
test_done