* Copyright (C) Linus Torvalds, 2005
*/
#include "cache.h"
+#include "strbuf.h"
/*
* Default to not allowing changes to the list of files. The
* like "git-update-index *" and suddenly having all the object
* files be revision controlled.
*/
-static int allow_add = 0, allow_remove = 0, allow_replace = 0, not_new = 0, quiet = 0, info_only = 0;
+static int allow_add = 0, allow_remove = 0, allow_replace = 0, allow_unmerged = 0, not_new = 0, quiet = 0, info_only = 0;
static int force_remove;
/* Three functions to allow overloaded pointer return; see linux/err.h */
return (unsigned long)ptr > (unsigned long)-1000L;
}
-static int add_file_to_cache(char *path)
+static int add_file_to_cache(const char *path)
{
int size, namelen, option, status;
struct cache_entry *ce;
return 0;
}
-static int compare_data(struct cache_entry *ce, struct stat *st)
-{
- int match = -1;
- int fd = open(ce->name, O_RDONLY);
-
- if (fd >= 0) {
- unsigned char sha1[20];
- if (!index_fd(sha1, fd, st, 0, NULL))
- match = memcmp(sha1, ce->sha1, 20);
- close(fd);
- }
- return match;
-}
-
-static int compare_link(struct cache_entry *ce, unsigned long expected_size)
-{
- int match = -1;
- char *target;
- void *buffer;
- unsigned long size;
- char type[10];
- int len;
-
- target = xmalloc(expected_size);
- len = readlink(ce->name, target, expected_size);
- if (len != expected_size) {
- free(target);
- return -1;
- }
- buffer = read_sha1_file(ce->sha1, type, &size);
- if (!buffer) {
- free(target);
- return -1;
- }
- if (size == expected_size)
- match = memcmp(buffer, target, size);
- free(buffer);
- free(target);
- return match;
-}
-
/*
* "refresh" does not calculate a new sha1 file or bring the
* cache up-to-date for mode/content changes. But what it
changed = ce_match_stat(ce, &st);
if (!changed)
- return ce;
-
- /*
- * If the mode or type has changed, there's no point in trying
- * to refresh the entry - it's not going to match
- */
- if (changed & (MODE_CHANGED | TYPE_CHANGED))
- return ERR_PTR(-EINVAL);
+ return NULL;
- switch (st.st_mode & S_IFMT) {
- case S_IFREG:
- if (compare_data(ce, &st))
- return ERR_PTR(-EINVAL);
- break;
- case S_IFLNK:
- if (compare_link(ce, st.st_size))
- return ERR_PTR(-EINVAL);
- break;
- default:
+ if (ce_modified(ce, &st))
return ERR_PTR(-EINVAL);
- }
size = ce_size(ce);
updated = xmalloc(size);
struct cache_entry *ce, *new;
ce = active_cache[i];
if (ce_stage(ce)) {
- printf("%s: needs merge\n", ce->name);
- has_errors = 1;
while ((i < active_nr) &&
! strcmp(active_cache[i]->name, ce->name))
i++;
i--;
+ if (allow_unmerged)
+ continue;
+ printf("%s: needs merge\n", ce->name);
+ has_errors = 1;
continue;
}
new = refresh_entry(ce);
+ if (!new)
+ continue;
if (IS_ERR(new)) {
if (not_new && PTR_ERR(new) == -ENOENT)
continue;
return 1;
}
-static int verify_path(char *path)
+static int verify_path(const char *path)
{
char c;
}
}
-static int add_cacheinfo(char *arg1, char *arg2, char *arg3)
+static int add_cacheinfo(const char *arg1, const char *arg2, const char *arg3)
{
int size, len, option;
unsigned int mode;
static struct cache_file cache_file;
-int main(int argc, char **argv)
+
+static void update_one(const char *path, const char *prefix, int prefix_length)
+{
+ const char *p = prefix_path(prefix, prefix_length, path);
+ if (!verify_path(p)) {
+ fprintf(stderr, "Ignoring path %s\n", path);
+ return;
+ }
+ if (force_remove) {
+ if (remove_file_from_cache(p))
+ die("git-update-index: unable to remove %s", path);
+ return;
+ }
+ if (add_file_to_cache(p))
+ die("Unable to process file %s", path);
+}
+
+int main(int argc, const char **argv)
{
- int i, newfd, entries, has_errors = 0;
+ int i, newfd, entries, has_errors = 0, line_termination = '\n';
int allow_options = 1;
+ int read_from_stdin = 0;
const char *prefix = setup_git_directory();
+ int prefix_length = prefix ? strlen(prefix) : 0;
newfd = hold_index_file_for_update(&cache_file, get_index_file());
if (newfd < 0)
die("cache corrupted");
for (i = 1 ; i < argc; i++) {
- char *path = argv[i];
+ const char *path = argv[i];
if (allow_options && *path == '-') {
if (!strcmp(path, "--")) {
allow_remove = 1;
continue;
}
+ if (!strcmp(path, "--unmerged")) {
+ allow_unmerged = 1;
+ continue;
+ }
if (!strcmp(path, "--refresh")) {
has_errors |= refresh_cache();
continue;
force_remove = 1;
continue;
}
-
+ if (!strcmp(path, "-z")) {
+ line_termination = 0;
+ continue;
+ }
+ if (!strcmp(path, "--stdin")) {
+ if (i != argc - 1)
+ die("--stdin must be at the end");
+ read_from_stdin = 1;
+ break;
+ }
if (!strcmp(path, "--ignore-missing")) {
not_new = 1;
continue;
}
die("unknown option %s", path);
}
- path = prefix_path(prefix, prefix ? strlen(prefix) : 0, path);
- if (!verify_path(path)) {
- fprintf(stderr, "Ignoring path %s\n", argv[i]);
- continue;
- }
- if (force_remove) {
- if (remove_file_from_cache(path))
- die("git-update-index: unable to remove %s", path);
- continue;
+ update_one(path, prefix, prefix_length);
+ }
+ if (read_from_stdin) {
+ struct strbuf buf;
+ strbuf_init(&buf);
+ while (1) {
+ read_line(&buf, stdin, line_termination);
+ if (buf.eof)
+ break;
+ update_one(buf.buf, prefix, prefix_length);
}
- if (add_file_to_cache(path))
- die("Unable to process file %s", path);
}
- if (write_cache(newfd, active_cache, active_nr) ||
- commit_index_file(&cache_file))
- die("Unable to write new cachefile");
+ if (active_cache_changed) {
+ if (write_cache(newfd, active_cache, active_nr) ||
+ commit_index_file(&cache_file))
+ die("Unable to write new cachefile");
+ }
return has_errors ? 1 : 0;
}