Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.kernel.org/pub/scm/git/git.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJunio C Hamano <junkio@cox.net>2006-04-26 14:29:09 +0400
committerJunio C Hamano <junkio@cox.net>2006-04-26 14:29:09 +0400
commitb8ed7f0f40743dae6111c8950ba55051933298ca (patch)
treeff4ebce0cdaf2c9c493eb38fd22f8e9d8d705bc0 /update-index.c
parent0f8820528e4c2e4b3e1306cfe79998e7124c8d49 (diff)
parent3496277a561307c3d31d2085347af8eb4c667c36 (diff)
Merge branch 'master' into jc/cache-tree
* master: commit-tree: allow generic object name for the tree as well. Makefile: remove and create xdiff library from scratch. t0000-basic: Add ls-tree recursive test back. Libified diff-index: backward compatibility fix. Libify diff-index. Libify diff-files. Makefile: remove and create libgit.a from scratch. Document the configuration file Document git-var -l listing also configuration variables rev-parse: better error message for ambiguous arguments make update-index --chmod work with multiple files and --stdin socksetup: don't return on set_reuse_addr() error Fix "git show --stat" git-update-index --unresolve Add git-unresolve <paths>... Add colordiff for git to contrib/colordiff. gitk: Let git-rev-list do the argument list parsing
Diffstat (limited to 'update-index.c')
-rw-r--r--update-index.c150
1 files changed, 143 insertions, 7 deletions
diff --git a/update-index.c b/update-index.c
index d6d3295e32..258a88cbea 100644
--- a/update-index.c
+++ b/update-index.c
@@ -7,6 +7,7 @@
#include "strbuf.h"
#include "quote.h"
#include "cache-tree.h"
+#include "tree-walk.h"
/*
* Default to not allowing changes to the list of files. The
@@ -337,7 +338,7 @@ static int add_cacheinfo(unsigned int mode, const unsigned char *sha1,
return 0;
}
-static int chmod_path(int flip, const char *path)
+static void chmod_path(int flip, const char *path)
{
int pos;
struct cache_entry *ce;
@@ -345,22 +346,25 @@ static int chmod_path(int flip, const char *path)
pos = cache_name_pos(path, strlen(path));
if (pos < 0)
- return -1;
+ goto fail;
ce = active_cache[pos];
mode = ntohl(ce->ce_mode);
if (!S_ISREG(mode))
- return -1;
+ goto fail;
switch (flip) {
case '+':
ce->ce_mode |= htonl(0111); break;
case '-':
ce->ce_mode &= htonl(~0111); break;
default:
- return -1;
+ goto fail;
}
cache_tree_invalidate_path(active_cache_tree, path);
active_cache_changed = 1;
- return 0;
+ report("chmod %cx '%s'", flip, path);
+ return;
+ fail:
+ die("git-update-index: cannot chmod %cx '%s'", flip, path);
}
static struct cache_file cache_file;
@@ -483,6 +487,124 @@ static void read_index_info(int line_termination)
static const char update_index_usage[] =
"git-update-index [-q] [--add] [--replace] [--remove] [--unmerged] [--refresh] [--cacheinfo] [--chmod=(+|-)x] [--info-only] [--force-remove] [--stdin] [--index-info] [--ignore-missing] [-z] [--verbose] [--] <file>...";
+static unsigned char head_sha1[20];
+static unsigned char merge_head_sha1[20];
+
+static struct cache_entry *read_one_ent(const char *which,
+ unsigned char *ent, const char *path,
+ int namelen, int stage)
+{
+ unsigned mode;
+ unsigned char sha1[20];
+ int size;
+ struct cache_entry *ce;
+
+ if (get_tree_entry(ent, path, sha1, &mode)) {
+ error("%s: not in %s branch.", path, which);
+ return NULL;
+ }
+ if (mode == S_IFDIR) {
+ error("%s: not a blob in %s branch.", path, which);
+ return NULL;
+ }
+ size = cache_entry_size(namelen);
+ ce = xcalloc(1, size);
+
+ memcpy(ce->sha1, sha1, 20);
+ memcpy(ce->name, path, namelen);
+ ce->ce_flags = create_ce_flags(namelen, stage);
+ ce->ce_mode = create_ce_mode(mode);
+ return ce;
+}
+
+static int unresolve_one(const char *path)
+{
+ int namelen = strlen(path);
+ int pos;
+ int ret = 0;
+ struct cache_entry *ce_2 = NULL, *ce_3 = NULL;
+
+ /* See if there is such entry in the index. */
+ pos = cache_name_pos(path, namelen);
+ if (pos < 0) {
+ /* If there isn't, either it is unmerged, or
+ * resolved as "removed" by mistake. We do not
+ * want to do anything in the former case.
+ */
+ pos = -pos-1;
+ if (pos < active_nr) {
+ struct cache_entry *ce = active_cache[pos];
+ if (ce_namelen(ce) == namelen &&
+ !memcmp(ce->name, path, namelen)) {
+ fprintf(stderr,
+ "%s: skipping still unmerged path.\n",
+ path);
+ goto free_return;
+ }
+ }
+ }
+
+ /* Grab blobs from given path from HEAD and MERGE_HEAD,
+ * stuff HEAD version in stage #2,
+ * stuff MERGE_HEAD version in stage #3.
+ */
+ ce_2 = read_one_ent("our", head_sha1, path, namelen, 2);
+ ce_3 = read_one_ent("their", merge_head_sha1, path, namelen, 3);
+
+ if (!ce_2 || !ce_3) {
+ ret = -1;
+ goto free_return;
+ }
+ if (!memcmp(ce_2->sha1, ce_3->sha1, 20) &&
+ ce_2->ce_mode == ce_3->ce_mode) {
+ fprintf(stderr, "%s: identical in both, skipping.\n",
+ path);
+ goto free_return;
+ }
+
+ remove_file_from_cache(path);
+ if (add_cache_entry(ce_2, ADD_CACHE_OK_TO_ADD)) {
+ error("%s: cannot add our version to the index.", path);
+ ret = -1;
+ goto free_return;
+ }
+ if (!add_cache_entry(ce_3, ADD_CACHE_OK_TO_ADD))
+ return 0;
+ error("%s: cannot add their version to the index.", path);
+ ret = -1;
+ free_return:
+ free(ce_2);
+ free(ce_3);
+ return ret;
+}
+
+static void read_head_pointers(void)
+{
+ if (read_ref(git_path("HEAD"), head_sha1))
+ die("No HEAD -- no initial commit yet?\n");
+ if (read_ref(git_path("MERGE_HEAD"), merge_head_sha1)) {
+ fprintf(stderr, "Not in the middle of a merge.\n");
+ exit(0);
+ }
+}
+
+static int do_unresolve(int ac, const char **av)
+{
+ int i;
+ int err = 0;
+
+ /* Read HEAD and MERGE_HEAD; if MERGE_HEAD does not exist, we
+ * are not doing a merge, so exit with success status.
+ */
+ read_head_pointers();
+
+ for (i = 1; i < ac; i++) {
+ const char *arg = av[i];
+ err |= unresolve_one(arg);
+ }
+ return err;
+}
+
int main(int argc, const char **argv)
{
int i, newfd, entries, has_errors = 0, line_termination = '\n';
@@ -490,6 +612,7 @@ int main(int argc, const char **argv)
int read_from_stdin = 0;
const char *prefix = setup_git_directory();
int prefix_length = prefix ? strlen(prefix) : 0;
+ char set_executable_bit = 0;
git_config(git_default_config);
@@ -556,8 +679,7 @@ int main(int argc, const char **argv)
!strcmp(path, "--chmod=+x")) {
if (argc <= i+1)
die("git-update-index: %s <path>", path);
- if (chmod_path(path[8], argv[++i]))
- die("git-update-index: %s cannot chmod %s", path, argv[i]);
+ set_executable_bit = path[8];
continue;
}
if (!strcmp(path, "--assume-unchanged")) {
@@ -593,6 +715,12 @@ int main(int argc, const char **argv)
read_index_info(line_termination);
break;
}
+ if (!strcmp(path, "--unresolve")) {
+ has_errors = do_unresolve(argc - i, argv + i);
+ if (has_errors)
+ active_cache_changed = 0;
+ goto finish;
+ }
if (!strcmp(path, "--ignore-missing")) {
not_new = 1;
continue;
@@ -606,6 +734,8 @@ int main(int argc, const char **argv)
die("unknown option %s", path);
}
update_one(path, prefix, prefix_length);
+ if (set_executable_bit)
+ chmod_path(set_executable_bit, path);
}
if (read_from_stdin) {
struct strbuf buf;
@@ -620,10 +750,16 @@ int main(int argc, const char **argv)
else
path_name = buf.buf;
update_one(path_name, prefix, prefix_length);
+ if (set_executable_bit) {
+ const char *p = prefix_path(prefix, prefix_length, path_name);
+ chmod_path(set_executable_bit, p);
+ }
if (path_name != buf.buf)
free(path_name);
}
}
+
+ finish:
if (active_cache_changed) {
if (write_cache(newfd, active_cache, active_nr) ||
commit_index_file(&cache_file))