git/update-index.c

759 строки
18 KiB
C
Исходник Обычный вид История

/*
* GIT - The information manager from hell
*
* Copyright (C) Linus Torvalds, 2005
*/
#include "cache.h"
#include "strbuf.h"
#include "quote.h"
#include "tree-walk.h"
/*
* Default to not allowing changes to the list of files. The
* tool doesn't actually care, but this makes it harder to add
* files to the revision control by mistake by doing something
* like "git-update-index *" and suddenly having all the object
* files be revision controlled.
*/
static int allow_add;
static int allow_remove;
static int allow_replace;
static int allow_unmerged; /* --refresh needing merge is not error */
static int not_new; /* --refresh not having working tree files is not error */
static int quiet; /* --refresh needing update is not error */
static int info_only;
static int force_remove;
static int verbose;
"Assume unchanged" git This adds "assume unchanged" logic, started by this message in the list discussion recently: <Pine.LNX.4.64.0601311807470.7301@g5.osdl.org> This is a workaround for filesystems that do not have lstat() that is quick enough for the index mechanism to take advantage of. On the paths marked as "assumed to be unchanged", the user needs to explicitly use update-index to register the object name to be in the next commit. You can use two new options to update-index to set and reset the CE_VALID bit: git-update-index --assume-unchanged path... git-update-index --no-assume-unchanged path... These forms manipulate only the CE_VALID bit; it does not change the object name recorded in the index file. Nor they add a new entry to the index. When the configuration variable "core.ignorestat = true" is set, the index entries are marked with CE_VALID bit automatically after: - update-index to explicitly register the current object name to the index file. - when update-index --refresh finds the path to be up-to-date. - when tools like read-tree -u and apply --index update the working tree file and register the current object name to the index file. The flag is dropped upon read-tree that does not check out the index entry. This happens regardless of the core.ignorestat settings. Index entries marked with CE_VALID bit are assumed to be unchanged most of the time. However, there are cases that CE_VALID bit is ignored for the sake of safety and usability: - while "git-read-tree -m" or git-apply need to make sure that the paths involved in the merge do not have local modifications. This sacrifices performance for safety. - when git-checkout-index -f -q -u -a tries to see if it needs to checkout the paths. Otherwise you can never check anything out ;-). - when git-update-index --really-refresh (a new flag) tries to see if the index entry is up to date. You can start with everything marked as CE_VALID and run this once to drop CE_VALID bit for paths that are modified. Most notably, "update-index --refresh" honours CE_VALID and does not actively stat, so after you modified a file in the working tree, update-index --refresh would not notice until you tell the index about it with "git-update-index path" or "git-update-index --no-assume-unchanged path". This version is not expected to be perfect. I think diff between index and/or tree and working files may need some adjustment, and there probably needs other cases we should automatically unmark paths that are marked to be CE_VALID. But the basics seem to work, and ready to be tested by people who asked for this feature. Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-02-09 08:15:24 +03:00
static int mark_valid_only = 0;
#define MARK_VALID 1
#define UNMARK_VALID 2
/* Three functions to allow overloaded pointer return; see linux/err.h */
static inline void *ERR_PTR(long error)
{
return (void *) error;
}
static inline long PTR_ERR(const void *ptr)
{
return (long) ptr;
}
static inline long IS_ERR(const void *ptr)
{
return (unsigned long)ptr > (unsigned long)-1000L;
}
static void report(const char *fmt, ...)
{
va_list vp;
if (!verbose)
return;
va_start(vp, fmt);
vprintf(fmt, vp);
putchar('\n');
va_end(vp);
}
"Assume unchanged" git This adds "assume unchanged" logic, started by this message in the list discussion recently: <Pine.LNX.4.64.0601311807470.7301@g5.osdl.org> This is a workaround for filesystems that do not have lstat() that is quick enough for the index mechanism to take advantage of. On the paths marked as "assumed to be unchanged", the user needs to explicitly use update-index to register the object name to be in the next commit. You can use two new options to update-index to set and reset the CE_VALID bit: git-update-index --assume-unchanged path... git-update-index --no-assume-unchanged path... These forms manipulate only the CE_VALID bit; it does not change the object name recorded in the index file. Nor they add a new entry to the index. When the configuration variable "core.ignorestat = true" is set, the index entries are marked with CE_VALID bit automatically after: - update-index to explicitly register the current object name to the index file. - when update-index --refresh finds the path to be up-to-date. - when tools like read-tree -u and apply --index update the working tree file and register the current object name to the index file. The flag is dropped upon read-tree that does not check out the index entry. This happens regardless of the core.ignorestat settings. Index entries marked with CE_VALID bit are assumed to be unchanged most of the time. However, there are cases that CE_VALID bit is ignored for the sake of safety and usability: - while "git-read-tree -m" or git-apply need to make sure that the paths involved in the merge do not have local modifications. This sacrifices performance for safety. - when git-checkout-index -f -q -u -a tries to see if it needs to checkout the paths. Otherwise you can never check anything out ;-). - when git-update-index --really-refresh (a new flag) tries to see if the index entry is up to date. You can start with everything marked as CE_VALID and run this once to drop CE_VALID bit for paths that are modified. Most notably, "update-index --refresh" honours CE_VALID and does not actively stat, so after you modified a file in the working tree, update-index --refresh would not notice until you tell the index about it with "git-update-index path" or "git-update-index --no-assume-unchanged path". This version is not expected to be perfect. I think diff between index and/or tree and working files may need some adjustment, and there probably needs other cases we should automatically unmark paths that are marked to be CE_VALID. But the basics seem to work, and ready to be tested by people who asked for this feature. Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-02-09 08:15:24 +03:00
static int mark_valid(const char *path)
{
int namelen = strlen(path);
int pos = cache_name_pos(path, namelen);
if (0 <= pos) {
switch (mark_valid_only) {
case MARK_VALID:
active_cache[pos]->ce_flags |= htons(CE_VALID);
break;
case UNMARK_VALID:
active_cache[pos]->ce_flags &= ~htons(CE_VALID);
break;
}
active_cache_changed = 1;
return 0;
}
return -1;
}
static int add_file_to_cache(const char *path)
{
int size, namelen, option, status;
struct cache_entry *ce;
struct stat st;
status = lstat(path, &st);
if (status < 0 || S_ISDIR(st.st_mode)) {
/* When we used to have "path" and now we want to add
* "path/file", we need a way to remove "path" before
* being able to add "path/file". However,
* "git-update-index --remove path" would not work.
* --force-remove can be used but this is more user
* friendly, especially since we can do the opposite
* case just fine without --force-remove.
*/
if (status == 0 || (errno == ENOENT || errno == ENOTDIR)) {
if (allow_remove) {
if (remove_file_from_cache(path))
return error("%s: cannot remove from the index",
path);
else
return 0;
} else if (status < 0) {
return error("%s: does not exist and --remove not passed",
path);
}
}
if (0 == status)
return error("%s: is a directory - add files inside instead",
path);
else
return error("lstat(\"%s\"): %s", path,
strerror(errno));
}
namelen = strlen(path);
size = cache_entry_size(namelen);
ce = xcalloc(1, size);
memcpy(ce->name, path, namelen);
"Assume unchanged" git This adds "assume unchanged" logic, started by this message in the list discussion recently: <Pine.LNX.4.64.0601311807470.7301@g5.osdl.org> This is a workaround for filesystems that do not have lstat() that is quick enough for the index mechanism to take advantage of. On the paths marked as "assumed to be unchanged", the user needs to explicitly use update-index to register the object name to be in the next commit. You can use two new options to update-index to set and reset the CE_VALID bit: git-update-index --assume-unchanged path... git-update-index --no-assume-unchanged path... These forms manipulate only the CE_VALID bit; it does not change the object name recorded in the index file. Nor they add a new entry to the index. When the configuration variable "core.ignorestat = true" is set, the index entries are marked with CE_VALID bit automatically after: - update-index to explicitly register the current object name to the index file. - when update-index --refresh finds the path to be up-to-date. - when tools like read-tree -u and apply --index update the working tree file and register the current object name to the index file. The flag is dropped upon read-tree that does not check out the index entry. This happens regardless of the core.ignorestat settings. Index entries marked with CE_VALID bit are assumed to be unchanged most of the time. However, there are cases that CE_VALID bit is ignored for the sake of safety and usability: - while "git-read-tree -m" or git-apply need to make sure that the paths involved in the merge do not have local modifications. This sacrifices performance for safety. - when git-checkout-index -f -q -u -a tries to see if it needs to checkout the paths. Otherwise you can never check anything out ;-). - when git-update-index --really-refresh (a new flag) tries to see if the index entry is up to date. You can start with everything marked as CE_VALID and run this once to drop CE_VALID bit for paths that are modified. Most notably, "update-index --refresh" honours CE_VALID and does not actively stat, so after you modified a file in the working tree, update-index --refresh would not notice until you tell the index about it with "git-update-index path" or "git-update-index --no-assume-unchanged path". This version is not expected to be perfect. I think diff between index and/or tree and working files may need some adjustment, and there probably needs other cases we should automatically unmark paths that are marked to be CE_VALID. But the basics seem to work, and ready to be tested by people who asked for this feature. Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-02-09 08:15:24 +03:00
ce->ce_flags = htons(namelen);
fill_stat_cache_info(ce, &st);
ce->ce_mode = create_ce_mode(st.st_mode);
if (!trust_executable_bit) {
/* If there is an existing entry, pick the mode bits
* from it.
*/
int pos = cache_name_pos(path, namelen);
if (0 <= pos)
ce->ce_mode = active_cache[pos]->ce_mode;
}
if (index_path(ce->sha1, path, &st, !info_only))
return -1;
option = allow_add ? ADD_CACHE_OK_TO_ADD : 0;
option |= allow_replace ? ADD_CACHE_OK_TO_REPLACE : 0;
if (add_cache_entry(ce, option))
return error("%s: cannot add to the index - missing --add option?",
path);
return 0;
}
/*
* "refresh" does not calculate a new sha1 file or bring the
* cache up-to-date for mode/content changes. But what it
* _does_ do is to "re-match" the stat information of a file
* with the cache, so that you can refresh the cache for a
* file that hasn't been changed but where the stat entry is
* out of date.
*
* For example, you'd want to do this after doing a "git-read-tree",
* to link up the stat cache details with the proper files.
*/
"Assume unchanged" git This adds "assume unchanged" logic, started by this message in the list discussion recently: <Pine.LNX.4.64.0601311807470.7301@g5.osdl.org> This is a workaround for filesystems that do not have lstat() that is quick enough for the index mechanism to take advantage of. On the paths marked as "assumed to be unchanged", the user needs to explicitly use update-index to register the object name to be in the next commit. You can use two new options to update-index to set and reset the CE_VALID bit: git-update-index --assume-unchanged path... git-update-index --no-assume-unchanged path... These forms manipulate only the CE_VALID bit; it does not change the object name recorded in the index file. Nor they add a new entry to the index. When the configuration variable "core.ignorestat = true" is set, the index entries are marked with CE_VALID bit automatically after: - update-index to explicitly register the current object name to the index file. - when update-index --refresh finds the path to be up-to-date. - when tools like read-tree -u and apply --index update the working tree file and register the current object name to the index file. The flag is dropped upon read-tree that does not check out the index entry. This happens regardless of the core.ignorestat settings. Index entries marked with CE_VALID bit are assumed to be unchanged most of the time. However, there are cases that CE_VALID bit is ignored for the sake of safety and usability: - while "git-read-tree -m" or git-apply need to make sure that the paths involved in the merge do not have local modifications. This sacrifices performance for safety. - when git-checkout-index -f -q -u -a tries to see if it needs to checkout the paths. Otherwise you can never check anything out ;-). - when git-update-index --really-refresh (a new flag) tries to see if the index entry is up to date. You can start with everything marked as CE_VALID and run this once to drop CE_VALID bit for paths that are modified. Most notably, "update-index --refresh" honours CE_VALID and does not actively stat, so after you modified a file in the working tree, update-index --refresh would not notice until you tell the index about it with "git-update-index path" or "git-update-index --no-assume-unchanged path". This version is not expected to be perfect. I think diff between index and/or tree and working files may need some adjustment, and there probably needs other cases we should automatically unmark paths that are marked to be CE_VALID. But the basics seem to work, and ready to be tested by people who asked for this feature. Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-02-09 08:15:24 +03:00
static struct cache_entry *refresh_entry(struct cache_entry *ce, int really)
{
struct stat st;
struct cache_entry *updated;
int changed, size;
if (lstat(ce->name, &st) < 0)
return ERR_PTR(-errno);
"Assume unchanged" git This adds "assume unchanged" logic, started by this message in the list discussion recently: <Pine.LNX.4.64.0601311807470.7301@g5.osdl.org> This is a workaround for filesystems that do not have lstat() that is quick enough for the index mechanism to take advantage of. On the paths marked as "assumed to be unchanged", the user needs to explicitly use update-index to register the object name to be in the next commit. You can use two new options to update-index to set and reset the CE_VALID bit: git-update-index --assume-unchanged path... git-update-index --no-assume-unchanged path... These forms manipulate only the CE_VALID bit; it does not change the object name recorded in the index file. Nor they add a new entry to the index. When the configuration variable "core.ignorestat = true" is set, the index entries are marked with CE_VALID bit automatically after: - update-index to explicitly register the current object name to the index file. - when update-index --refresh finds the path to be up-to-date. - when tools like read-tree -u and apply --index update the working tree file and register the current object name to the index file. The flag is dropped upon read-tree that does not check out the index entry. This happens regardless of the core.ignorestat settings. Index entries marked with CE_VALID bit are assumed to be unchanged most of the time. However, there are cases that CE_VALID bit is ignored for the sake of safety and usability: - while "git-read-tree -m" or git-apply need to make sure that the paths involved in the merge do not have local modifications. This sacrifices performance for safety. - when git-checkout-index -f -q -u -a tries to see if it needs to checkout the paths. Otherwise you can never check anything out ;-). - when git-update-index --really-refresh (a new flag) tries to see if the index entry is up to date. You can start with everything marked as CE_VALID and run this once to drop CE_VALID bit for paths that are modified. Most notably, "update-index --refresh" honours CE_VALID and does not actively stat, so after you modified a file in the working tree, update-index --refresh would not notice until you tell the index about it with "git-update-index path" or "git-update-index --no-assume-unchanged path". This version is not expected to be perfect. I think diff between index and/or tree and working files may need some adjustment, and there probably needs other cases we should automatically unmark paths that are marked to be CE_VALID. But the basics seem to work, and ready to be tested by people who asked for this feature. Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-02-09 08:15:24 +03:00
changed = ce_match_stat(ce, &st, really);
if (!changed) {
if (really && assume_unchanged &&
!(ce->ce_flags & htons(CE_VALID)))
; /* mark this one VALID again */
else
return NULL;
}
"Assume unchanged" git This adds "assume unchanged" logic, started by this message in the list discussion recently: <Pine.LNX.4.64.0601311807470.7301@g5.osdl.org> This is a workaround for filesystems that do not have lstat() that is quick enough for the index mechanism to take advantage of. On the paths marked as "assumed to be unchanged", the user needs to explicitly use update-index to register the object name to be in the next commit. You can use two new options to update-index to set and reset the CE_VALID bit: git-update-index --assume-unchanged path... git-update-index --no-assume-unchanged path... These forms manipulate only the CE_VALID bit; it does not change the object name recorded in the index file. Nor they add a new entry to the index. When the configuration variable "core.ignorestat = true" is set, the index entries are marked with CE_VALID bit automatically after: - update-index to explicitly register the current object name to the index file. - when update-index --refresh finds the path to be up-to-date. - when tools like read-tree -u and apply --index update the working tree file and register the current object name to the index file. The flag is dropped upon read-tree that does not check out the index entry. This happens regardless of the core.ignorestat settings. Index entries marked with CE_VALID bit are assumed to be unchanged most of the time. However, there are cases that CE_VALID bit is ignored for the sake of safety and usability: - while "git-read-tree -m" or git-apply need to make sure that the paths involved in the merge do not have local modifications. This sacrifices performance for safety. - when git-checkout-index -f -q -u -a tries to see if it needs to checkout the paths. Otherwise you can never check anything out ;-). - when git-update-index --really-refresh (a new flag) tries to see if the index entry is up to date. You can start with everything marked as CE_VALID and run this once to drop CE_VALID bit for paths that are modified. Most notably, "update-index --refresh" honours CE_VALID and does not actively stat, so after you modified a file in the working tree, update-index --refresh would not notice until you tell the index about it with "git-update-index path" or "git-update-index --no-assume-unchanged path". This version is not expected to be perfect. I think diff between index and/or tree and working files may need some adjustment, and there probably needs other cases we should automatically unmark paths that are marked to be CE_VALID. But the basics seem to work, and ready to be tested by people who asked for this feature. Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-02-09 08:15:24 +03:00
if (ce_modified(ce, &st, really))
return ERR_PTR(-EINVAL);
size = ce_size(ce);
updated = xmalloc(size);
memcpy(updated, ce, size);
fill_stat_cache_info(updated, &st);
"Assume unchanged" git This adds "assume unchanged" logic, started by this message in the list discussion recently: <Pine.LNX.4.64.0601311807470.7301@g5.osdl.org> This is a workaround for filesystems that do not have lstat() that is quick enough for the index mechanism to take advantage of. On the paths marked as "assumed to be unchanged", the user needs to explicitly use update-index to register the object name to be in the next commit. You can use two new options to update-index to set and reset the CE_VALID bit: git-update-index --assume-unchanged path... git-update-index --no-assume-unchanged path... These forms manipulate only the CE_VALID bit; it does not change the object name recorded in the index file. Nor they add a new entry to the index. When the configuration variable "core.ignorestat = true" is set, the index entries are marked with CE_VALID bit automatically after: - update-index to explicitly register the current object name to the index file. - when update-index --refresh finds the path to be up-to-date. - when tools like read-tree -u and apply --index update the working tree file and register the current object name to the index file. The flag is dropped upon read-tree that does not check out the index entry. This happens regardless of the core.ignorestat settings. Index entries marked with CE_VALID bit are assumed to be unchanged most of the time. However, there are cases that CE_VALID bit is ignored for the sake of safety and usability: - while "git-read-tree -m" or git-apply need to make sure that the paths involved in the merge do not have local modifications. This sacrifices performance for safety. - when git-checkout-index -f -q -u -a tries to see if it needs to checkout the paths. Otherwise you can never check anything out ;-). - when git-update-index --really-refresh (a new flag) tries to see if the index entry is up to date. You can start with everything marked as CE_VALID and run this once to drop CE_VALID bit for paths that are modified. Most notably, "update-index --refresh" honours CE_VALID and does not actively stat, so after you modified a file in the working tree, update-index --refresh would not notice until you tell the index about it with "git-update-index path" or "git-update-index --no-assume-unchanged path". This version is not expected to be perfect. I think diff between index and/or tree and working files may need some adjustment, and there probably needs other cases we should automatically unmark paths that are marked to be CE_VALID. But the basics seem to work, and ready to be tested by people who asked for this feature. Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-02-09 08:15:24 +03:00
/* In this case, if really is not set, we should leave
* CE_VALID bit alone. Otherwise, paths marked with
* --no-assume-unchanged (i.e. things to be edited) will
* reacquire CE_VALID bit automatically, which is not
* really what we want.
*/
if (!really && assume_unchanged && !(ce->ce_flags & htons(CE_VALID)))
updated->ce_flags &= ~htons(CE_VALID);
return updated;
}
"Assume unchanged" git This adds "assume unchanged" logic, started by this message in the list discussion recently: <Pine.LNX.4.64.0601311807470.7301@g5.osdl.org> This is a workaround for filesystems that do not have lstat() that is quick enough for the index mechanism to take advantage of. On the paths marked as "assumed to be unchanged", the user needs to explicitly use update-index to register the object name to be in the next commit. You can use two new options to update-index to set and reset the CE_VALID bit: git-update-index --assume-unchanged path... git-update-index --no-assume-unchanged path... These forms manipulate only the CE_VALID bit; it does not change the object name recorded in the index file. Nor they add a new entry to the index. When the configuration variable "core.ignorestat = true" is set, the index entries are marked with CE_VALID bit automatically after: - update-index to explicitly register the current object name to the index file. - when update-index --refresh finds the path to be up-to-date. - when tools like read-tree -u and apply --index update the working tree file and register the current object name to the index file. The flag is dropped upon read-tree that does not check out the index entry. This happens regardless of the core.ignorestat settings. Index entries marked with CE_VALID bit are assumed to be unchanged most of the time. However, there are cases that CE_VALID bit is ignored for the sake of safety and usability: - while "git-read-tree -m" or git-apply need to make sure that the paths involved in the merge do not have local modifications. This sacrifices performance for safety. - when git-checkout-index -f -q -u -a tries to see if it needs to checkout the paths. Otherwise you can never check anything out ;-). - when git-update-index --really-refresh (a new flag) tries to see if the index entry is up to date. You can start with everything marked as CE_VALID and run this once to drop CE_VALID bit for paths that are modified. Most notably, "update-index --refresh" honours CE_VALID and does not actively stat, so after you modified a file in the working tree, update-index --refresh would not notice until you tell the index about it with "git-update-index path" or "git-update-index --no-assume-unchanged path". This version is not expected to be perfect. I think diff between index and/or tree and working files may need some adjustment, and there probably needs other cases we should automatically unmark paths that are marked to be CE_VALID. But the basics seem to work, and ready to be tested by people who asked for this feature. Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-02-09 08:15:24 +03:00
static int refresh_cache(int really)
{
int i;
int has_errors = 0;
for (i = 0; i < active_nr; i++) {
struct cache_entry *ce, *new;
ce = active_cache[i];
if (ce_stage(ce)) {
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;
}
"Assume unchanged" git This adds "assume unchanged" logic, started by this message in the list discussion recently: <Pine.LNX.4.64.0601311807470.7301@g5.osdl.org> This is a workaround for filesystems that do not have lstat() that is quick enough for the index mechanism to take advantage of. On the paths marked as "assumed to be unchanged", the user needs to explicitly use update-index to register the object name to be in the next commit. You can use two new options to update-index to set and reset the CE_VALID bit: git-update-index --assume-unchanged path... git-update-index --no-assume-unchanged path... These forms manipulate only the CE_VALID bit; it does not change the object name recorded in the index file. Nor they add a new entry to the index. When the configuration variable "core.ignorestat = true" is set, the index entries are marked with CE_VALID bit automatically after: - update-index to explicitly register the current object name to the index file. - when update-index --refresh finds the path to be up-to-date. - when tools like read-tree -u and apply --index update the working tree file and register the current object name to the index file. The flag is dropped upon read-tree that does not check out the index entry. This happens regardless of the core.ignorestat settings. Index entries marked with CE_VALID bit are assumed to be unchanged most of the time. However, there are cases that CE_VALID bit is ignored for the sake of safety and usability: - while "git-read-tree -m" or git-apply need to make sure that the paths involved in the merge do not have local modifications. This sacrifices performance for safety. - when git-checkout-index -f -q -u -a tries to see if it needs to checkout the paths. Otherwise you can never check anything out ;-). - when git-update-index --really-refresh (a new flag) tries to see if the index entry is up to date. You can start with everything marked as CE_VALID and run this once to drop CE_VALID bit for paths that are modified. Most notably, "update-index --refresh" honours CE_VALID and does not actively stat, so after you modified a file in the working tree, update-index --refresh would not notice until you tell the index about it with "git-update-index path" or "git-update-index --no-assume-unchanged path". This version is not expected to be perfect. I think diff between index and/or tree and working files may need some adjustment, and there probably needs other cases we should automatically unmark paths that are marked to be CE_VALID. But the basics seem to work, and ready to be tested by people who asked for this feature. Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-02-09 08:15:24 +03:00
new = refresh_entry(ce, really);
if (!new)
continue;
if (IS_ERR(new)) {
if (not_new && PTR_ERR(new) == -ENOENT)
continue;
"Assume unchanged" git This adds "assume unchanged" logic, started by this message in the list discussion recently: <Pine.LNX.4.64.0601311807470.7301@g5.osdl.org> This is a workaround for filesystems that do not have lstat() that is quick enough for the index mechanism to take advantage of. On the paths marked as "assumed to be unchanged", the user needs to explicitly use update-index to register the object name to be in the next commit. You can use two new options to update-index to set and reset the CE_VALID bit: git-update-index --assume-unchanged path... git-update-index --no-assume-unchanged path... These forms manipulate only the CE_VALID bit; it does not change the object name recorded in the index file. Nor they add a new entry to the index. When the configuration variable "core.ignorestat = true" is set, the index entries are marked with CE_VALID bit automatically after: - update-index to explicitly register the current object name to the index file. - when update-index --refresh finds the path to be up-to-date. - when tools like read-tree -u and apply --index update the working tree file and register the current object name to the index file. The flag is dropped upon read-tree that does not check out the index entry. This happens regardless of the core.ignorestat settings. Index entries marked with CE_VALID bit are assumed to be unchanged most of the time. However, there are cases that CE_VALID bit is ignored for the sake of safety and usability: - while "git-read-tree -m" or git-apply need to make sure that the paths involved in the merge do not have local modifications. This sacrifices performance for safety. - when git-checkout-index -f -q -u -a tries to see if it needs to checkout the paths. Otherwise you can never check anything out ;-). - when git-update-index --really-refresh (a new flag) tries to see if the index entry is up to date. You can start with everything marked as CE_VALID and run this once to drop CE_VALID bit for paths that are modified. Most notably, "update-index --refresh" honours CE_VALID and does not actively stat, so after you modified a file in the working tree, update-index --refresh would not notice until you tell the index about it with "git-update-index path" or "git-update-index --no-assume-unchanged path". This version is not expected to be perfect. I think diff between index and/or tree and working files may need some adjustment, and there probably needs other cases we should automatically unmark paths that are marked to be CE_VALID. But the basics seem to work, and ready to be tested by people who asked for this feature. Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-02-09 08:15:24 +03:00
if (really && PTR_ERR(new) == -EINVAL) {
/* If we are doing --really-refresh that
* means the index is not valid anymore.
*/
ce->ce_flags &= ~htons(CE_VALID);
active_cache_changed = 1;
}
if (quiet)
continue;
printf("%s: needs update\n", ce->name);
has_errors = 1;
continue;
}
active_cache_changed = 1;
/* You can NOT just free active_cache[i] here, since it
* might not be necessarily malloc()ed but can also come
* from mmap(). */
active_cache[i] = new;
}
return has_errors;
}
/*
* We fundamentally don't like some paths: we don't want
* dot or dot-dot anywhere, and for obvious reasons don't
* want to recurse into ".git" either.
*
* Also, we don't want double slashes or slashes at the
* end that can make pathnames ambiguous.
*/
static int verify_dotfile(const char *rest)
{
/*
* The first character was '.', but that
* has already been discarded, we now test
* the rest.
*/
switch (*rest) {
/* "." is not allowed */
case '\0': case '/':
return 0;
/*
* ".git" followed by NUL or slash is bad. This
* shares the path end test with the ".." case.
*/
case 'g':
if (rest[1] != 'i')
break;
if (rest[2] != 't')
break;
rest += 2;
/* fallthrough */
case '.':
if (rest[1] == '\0' || rest[1] == '/')
return 0;
}
return 1;
}
static int verify_path(const char *path)
{
char c;
goto inside;
for (;;) {
if (!c)
return 1;
if (c == '/') {
inside:
c = *path++;
switch (c) {
default:
continue;
case '/': case '\0':
break;
case '.':
if (verify_dotfile(path))
continue;
}
return 0;
}
c = *path++;
}
}
update-index: allow --index-info to add higher stages. The new merge world order tells the merge strategies to leave the cache unmerged and store the automerge result in the working tree if automerge is not clean. This was done for the resolve strategy and recursive strategy when no rename is involved, but recording a conflicting merge in the rename case could not easily be done by the recursive strategy. This commit adds a new input format, in addition to the exsting two, to "update-index --index-info". (1) mode SP sha1 TAB path The first format is what "git-apply --index-info" reports, and used to reconstruct a partial tree that is used for phony merge base tree when falling back on 3-way merge. (2) mode SP type SP sha1 TAB path The second format is to stuff git-ls-tree output into the index file. (3) mode SP sha1 SP stage TAB path This format is to put higher order stages into the index file and matches git-ls-files --stage output. To place a higher stage entry to the index, the path should first be removed by feeding a mode=0 entry for the path, and then feeding necessary input lines in the (3) format. For example, starting with this index: $ git ls-files -s 100644 8a1218a1024a212bb3db30becd860315f9f3ac52 0 frotz $ git update-index --index-info ;# interactive session -- input follows... 0 0000000000000000000000000000000000000000 frotz 100644 8a1218a1024a212bb3db30becd860315f9f3ac52 1 frotz 100755 8a1218a1024a212bb3db30becd860315f9f3ac52 2 frotz The first line of the input feeds 0 as the mode to remove the path; the SHA1 does not matter as long as it is well formatted. Then the second and third line feeds stage 1 and stage 2 entries for that path. After the above, we would end up with this: $ git ls-files -s 100644 8a1218a1024a212bb3db30becd860315f9f3ac52 1 frotz 100755 8a1218a1024a212bb3db30becd860315f9f3ac52 2 frotz This completes the groundwork for the new merge world order. Signed-off-by: Junio C Hamano <junkio@cox.net>
2005-12-07 12:45:38 +03:00
static int add_cacheinfo(unsigned int mode, const unsigned char *sha1,
const char *path, int stage)
{
int size, len, option;
struct cache_entry *ce;
update-index: allow --index-info to add higher stages. The new merge world order tells the merge strategies to leave the cache unmerged and store the automerge result in the working tree if automerge is not clean. This was done for the resolve strategy and recursive strategy when no rename is involved, but recording a conflicting merge in the rename case could not easily be done by the recursive strategy. This commit adds a new input format, in addition to the exsting two, to "update-index --index-info". (1) mode SP sha1 TAB path The first format is what "git-apply --index-info" reports, and used to reconstruct a partial tree that is used for phony merge base tree when falling back on 3-way merge. (2) mode SP type SP sha1 TAB path The second format is to stuff git-ls-tree output into the index file. (3) mode SP sha1 SP stage TAB path This format is to put higher order stages into the index file and matches git-ls-files --stage output. To place a higher stage entry to the index, the path should first be removed by feeding a mode=0 entry for the path, and then feeding necessary input lines in the (3) format. For example, starting with this index: $ git ls-files -s 100644 8a1218a1024a212bb3db30becd860315f9f3ac52 0 frotz $ git update-index --index-info ;# interactive session -- input follows... 0 0000000000000000000000000000000000000000 frotz 100644 8a1218a1024a212bb3db30becd860315f9f3ac52 1 frotz 100755 8a1218a1024a212bb3db30becd860315f9f3ac52 2 frotz The first line of the input feeds 0 as the mode to remove the path; the SHA1 does not matter as long as it is well formatted. Then the second and third line feeds stage 1 and stage 2 entries for that path. After the above, we would end up with this: $ git ls-files -s 100644 8a1218a1024a212bb3db30becd860315f9f3ac52 1 frotz 100755 8a1218a1024a212bb3db30becd860315f9f3ac52 2 frotz This completes the groundwork for the new merge world order. Signed-off-by: Junio C Hamano <junkio@cox.net>
2005-12-07 12:45:38 +03:00
if (!verify_path(path))
return -1;
update-index: allow --index-info to add higher stages. The new merge world order tells the merge strategies to leave the cache unmerged and store the automerge result in the working tree if automerge is not clean. This was done for the resolve strategy and recursive strategy when no rename is involved, but recording a conflicting merge in the rename case could not easily be done by the recursive strategy. This commit adds a new input format, in addition to the exsting two, to "update-index --index-info". (1) mode SP sha1 TAB path The first format is what "git-apply --index-info" reports, and used to reconstruct a partial tree that is used for phony merge base tree when falling back on 3-way merge. (2) mode SP type SP sha1 TAB path The second format is to stuff git-ls-tree output into the index file. (3) mode SP sha1 SP stage TAB path This format is to put higher order stages into the index file and matches git-ls-files --stage output. To place a higher stage entry to the index, the path should first be removed by feeding a mode=0 entry for the path, and then feeding necessary input lines in the (3) format. For example, starting with this index: $ git ls-files -s 100644 8a1218a1024a212bb3db30becd860315f9f3ac52 0 frotz $ git update-index --index-info ;# interactive session -- input follows... 0 0000000000000000000000000000000000000000 frotz 100644 8a1218a1024a212bb3db30becd860315f9f3ac52 1 frotz 100755 8a1218a1024a212bb3db30becd860315f9f3ac52 2 frotz The first line of the input feeds 0 as the mode to remove the path; the SHA1 does not matter as long as it is well formatted. Then the second and third line feeds stage 1 and stage 2 entries for that path. After the above, we would end up with this: $ git ls-files -s 100644 8a1218a1024a212bb3db30becd860315f9f3ac52 1 frotz 100755 8a1218a1024a212bb3db30becd860315f9f3ac52 2 frotz This completes the groundwork for the new merge world order. Signed-off-by: Junio C Hamano <junkio@cox.net>
2005-12-07 12:45:38 +03:00
len = strlen(path);
size = cache_entry_size(len);
ce = xcalloc(1, size);
memcpy(ce->sha1, sha1, 20);
update-index: allow --index-info to add higher stages. The new merge world order tells the merge strategies to leave the cache unmerged and store the automerge result in the working tree if automerge is not clean. This was done for the resolve strategy and recursive strategy when no rename is involved, but recording a conflicting merge in the rename case could not easily be done by the recursive strategy. This commit adds a new input format, in addition to the exsting two, to "update-index --index-info". (1) mode SP sha1 TAB path The first format is what "git-apply --index-info" reports, and used to reconstruct a partial tree that is used for phony merge base tree when falling back on 3-way merge. (2) mode SP type SP sha1 TAB path The second format is to stuff git-ls-tree output into the index file. (3) mode SP sha1 SP stage TAB path This format is to put higher order stages into the index file and matches git-ls-files --stage output. To place a higher stage entry to the index, the path should first be removed by feeding a mode=0 entry for the path, and then feeding necessary input lines in the (3) format. For example, starting with this index: $ git ls-files -s 100644 8a1218a1024a212bb3db30becd860315f9f3ac52 0 frotz $ git update-index --index-info ;# interactive session -- input follows... 0 0000000000000000000000000000000000000000 frotz 100644 8a1218a1024a212bb3db30becd860315f9f3ac52 1 frotz 100755 8a1218a1024a212bb3db30becd860315f9f3ac52 2 frotz The first line of the input feeds 0 as the mode to remove the path; the SHA1 does not matter as long as it is well formatted. Then the second and third line feeds stage 1 and stage 2 entries for that path. After the above, we would end up with this: $ git ls-files -s 100644 8a1218a1024a212bb3db30becd860315f9f3ac52 1 frotz 100755 8a1218a1024a212bb3db30becd860315f9f3ac52 2 frotz This completes the groundwork for the new merge world order. Signed-off-by: Junio C Hamano <junkio@cox.net>
2005-12-07 12:45:38 +03:00
memcpy(ce->name, path, len);
ce->ce_flags = create_ce_flags(len, stage);
ce->ce_mode = create_ce_mode(mode);
"Assume unchanged" git This adds "assume unchanged" logic, started by this message in the list discussion recently: <Pine.LNX.4.64.0601311807470.7301@g5.osdl.org> This is a workaround for filesystems that do not have lstat() that is quick enough for the index mechanism to take advantage of. On the paths marked as "assumed to be unchanged", the user needs to explicitly use update-index to register the object name to be in the next commit. You can use two new options to update-index to set and reset the CE_VALID bit: git-update-index --assume-unchanged path... git-update-index --no-assume-unchanged path... These forms manipulate only the CE_VALID bit; it does not change the object name recorded in the index file. Nor they add a new entry to the index. When the configuration variable "core.ignorestat = true" is set, the index entries are marked with CE_VALID bit automatically after: - update-index to explicitly register the current object name to the index file. - when update-index --refresh finds the path to be up-to-date. - when tools like read-tree -u and apply --index update the working tree file and register the current object name to the index file. The flag is dropped upon read-tree that does not check out the index entry. This happens regardless of the core.ignorestat settings. Index entries marked with CE_VALID bit are assumed to be unchanged most of the time. However, there are cases that CE_VALID bit is ignored for the sake of safety and usability: - while "git-read-tree -m" or git-apply need to make sure that the paths involved in the merge do not have local modifications. This sacrifices performance for safety. - when git-checkout-index -f -q -u -a tries to see if it needs to checkout the paths. Otherwise you can never check anything out ;-). - when git-update-index --really-refresh (a new flag) tries to see if the index entry is up to date. You can start with everything marked as CE_VALID and run this once to drop CE_VALID bit for paths that are modified. Most notably, "update-index --refresh" honours CE_VALID and does not actively stat, so after you modified a file in the working tree, update-index --refresh would not notice until you tell the index about it with "git-update-index path" or "git-update-index --no-assume-unchanged path". This version is not expected to be perfect. I think diff between index and/or tree and working files may need some adjustment, and there probably needs other cases we should automatically unmark paths that are marked to be CE_VALID. But the basics seem to work, and ready to be tested by people who asked for this feature. Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-02-09 08:15:24 +03:00
if (assume_unchanged)
ce->ce_flags |= htons(CE_VALID);
option = allow_add ? ADD_CACHE_OK_TO_ADD : 0;
option |= allow_replace ? ADD_CACHE_OK_TO_REPLACE : 0;
if (add_cache_entry(ce, option))
return error("%s: cannot add to the index - missing --add option?",
update-index: allow --index-info to add higher stages. The new merge world order tells the merge strategies to leave the cache unmerged and store the automerge result in the working tree if automerge is not clean. This was done for the resolve strategy and recursive strategy when no rename is involved, but recording a conflicting merge in the rename case could not easily be done by the recursive strategy. This commit adds a new input format, in addition to the exsting two, to "update-index --index-info". (1) mode SP sha1 TAB path The first format is what "git-apply --index-info" reports, and used to reconstruct a partial tree that is used for phony merge base tree when falling back on 3-way merge. (2) mode SP type SP sha1 TAB path The second format is to stuff git-ls-tree output into the index file. (3) mode SP sha1 SP stage TAB path This format is to put higher order stages into the index file and matches git-ls-files --stage output. To place a higher stage entry to the index, the path should first be removed by feeding a mode=0 entry for the path, and then feeding necessary input lines in the (3) format. For example, starting with this index: $ git ls-files -s 100644 8a1218a1024a212bb3db30becd860315f9f3ac52 0 frotz $ git update-index --index-info ;# interactive session -- input follows... 0 0000000000000000000000000000000000000000 frotz 100644 8a1218a1024a212bb3db30becd860315f9f3ac52 1 frotz 100755 8a1218a1024a212bb3db30becd860315f9f3ac52 2 frotz The first line of the input feeds 0 as the mode to remove the path; the SHA1 does not matter as long as it is well formatted. Then the second and third line feeds stage 1 and stage 2 entries for that path. After the above, we would end up with this: $ git ls-files -s 100644 8a1218a1024a212bb3db30becd860315f9f3ac52 1 frotz 100755 8a1218a1024a212bb3db30becd860315f9f3ac52 2 frotz This completes the groundwork for the new merge world order. Signed-off-by: Junio C Hamano <junkio@cox.net>
2005-12-07 12:45:38 +03:00
path);
report("add '%s'", path);
return 0;
}
static void chmod_path(int flip, const char *path)
{
int pos;
struct cache_entry *ce;
unsigned int mode;
pos = cache_name_pos(path, strlen(path));
if (pos < 0)
goto fail;
ce = active_cache[pos];
mode = ntohl(ce->ce_mode);
if (!S_ISREG(mode))
goto fail;
switch (flip) {
case '+':
ce->ce_mode |= htonl(0111); break;
case '-':
ce->ce_mode &= htonl(~0111); break;
default:
goto fail;
}
active_cache_changed = 1;
report("chmod %cx '%s'", flip, path);
return;
fail:
die("git-update-index: cannot chmod %cx '%s'", flip, path);
}
static struct cache_file cache_file;
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;
}
"Assume unchanged" git This adds "assume unchanged" logic, started by this message in the list discussion recently: <Pine.LNX.4.64.0601311807470.7301@g5.osdl.org> This is a workaround for filesystems that do not have lstat() that is quick enough for the index mechanism to take advantage of. On the paths marked as "assumed to be unchanged", the user needs to explicitly use update-index to register the object name to be in the next commit. You can use two new options to update-index to set and reset the CE_VALID bit: git-update-index --assume-unchanged path... git-update-index --no-assume-unchanged path... These forms manipulate only the CE_VALID bit; it does not change the object name recorded in the index file. Nor they add a new entry to the index. When the configuration variable "core.ignorestat = true" is set, the index entries are marked with CE_VALID bit automatically after: - update-index to explicitly register the current object name to the index file. - when update-index --refresh finds the path to be up-to-date. - when tools like read-tree -u and apply --index update the working tree file and register the current object name to the index file. The flag is dropped upon read-tree that does not check out the index entry. This happens regardless of the core.ignorestat settings. Index entries marked with CE_VALID bit are assumed to be unchanged most of the time. However, there are cases that CE_VALID bit is ignored for the sake of safety and usability: - while "git-read-tree -m" or git-apply need to make sure that the paths involved in the merge do not have local modifications. This sacrifices performance for safety. - when git-checkout-index -f -q -u -a tries to see if it needs to checkout the paths. Otherwise you can never check anything out ;-). - when git-update-index --really-refresh (a new flag) tries to see if the index entry is up to date. You can start with everything marked as CE_VALID and run this once to drop CE_VALID bit for paths that are modified. Most notably, "update-index --refresh" honours CE_VALID and does not actively stat, so after you modified a file in the working tree, update-index --refresh would not notice until you tell the index about it with "git-update-index path" or "git-update-index --no-assume-unchanged path". This version is not expected to be perfect. I think diff between index and/or tree and working files may need some adjustment, and there probably needs other cases we should automatically unmark paths that are marked to be CE_VALID. But the basics seem to work, and ready to be tested by people who asked for this feature. Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-02-09 08:15:24 +03:00
if (mark_valid_only) {
if (mark_valid(p))
die("Unable to mark file %s", path);
return;
}
if (force_remove) {
if (remove_file_from_cache(p))
die("git-update-index: unable to remove %s", path);
report("remove '%s'", path);
return;
}
if (add_file_to_cache(p))
die("Unable to process file %s", path);
report("add '%s'", path);
}
static void read_index_info(int line_termination)
{
struct strbuf buf;
strbuf_init(&buf);
while (1) {
char *ptr, *tab;
char *path_name;
unsigned char sha1[20];
unsigned int mode;
update-index: allow --index-info to add higher stages. The new merge world order tells the merge strategies to leave the cache unmerged and store the automerge result in the working tree if automerge is not clean. This was done for the resolve strategy and recursive strategy when no rename is involved, but recording a conflicting merge in the rename case could not easily be done by the recursive strategy. This commit adds a new input format, in addition to the exsting two, to "update-index --index-info". (1) mode SP sha1 TAB path The first format is what "git-apply --index-info" reports, and used to reconstruct a partial tree that is used for phony merge base tree when falling back on 3-way merge. (2) mode SP type SP sha1 TAB path The second format is to stuff git-ls-tree output into the index file. (3) mode SP sha1 SP stage TAB path This format is to put higher order stages into the index file and matches git-ls-files --stage output. To place a higher stage entry to the index, the path should first be removed by feeding a mode=0 entry for the path, and then feeding necessary input lines in the (3) format. For example, starting with this index: $ git ls-files -s 100644 8a1218a1024a212bb3db30becd860315f9f3ac52 0 frotz $ git update-index --index-info ;# interactive session -- input follows... 0 0000000000000000000000000000000000000000 frotz 100644 8a1218a1024a212bb3db30becd860315f9f3ac52 1 frotz 100755 8a1218a1024a212bb3db30becd860315f9f3ac52 2 frotz The first line of the input feeds 0 as the mode to remove the path; the SHA1 does not matter as long as it is well formatted. Then the second and third line feeds stage 1 and stage 2 entries for that path. After the above, we would end up with this: $ git ls-files -s 100644 8a1218a1024a212bb3db30becd860315f9f3ac52 1 frotz 100755 8a1218a1024a212bb3db30becd860315f9f3ac52 2 frotz This completes the groundwork for the new merge world order. Signed-off-by: Junio C Hamano <junkio@cox.net>
2005-12-07 12:45:38 +03:00
int stage;
/* This reads lines formatted in one of three formats:
*
* (1) mode SP sha1 TAB path
* The first format is what "git-apply --index-info"
* reports, and used to reconstruct a partial tree
* that is used for phony merge base tree when falling
* back on 3-way merge.
*
* (2) mode SP type SP sha1 TAB path
* The second format is to stuff git-ls-tree output
* into the index file.
*
* (3) mode SP sha1 SP stage TAB path
* This format is to put higher order stages into the
* index file and matches git-ls-files --stage output.
*/
read_line(&buf, stdin, line_termination);
if (buf.eof)
break;
mode = strtoul(buf.buf, &ptr, 8);
if (ptr == buf.buf || *ptr != ' ')
goto bad_line;
tab = strchr(ptr, '\t');
if (!tab || tab - ptr < 41)
goto bad_line;
update-index: allow --index-info to add higher stages. The new merge world order tells the merge strategies to leave the cache unmerged and store the automerge result in the working tree if automerge is not clean. This was done for the resolve strategy and recursive strategy when no rename is involved, but recording a conflicting merge in the rename case could not easily be done by the recursive strategy. This commit adds a new input format, in addition to the exsting two, to "update-index --index-info". (1) mode SP sha1 TAB path The first format is what "git-apply --index-info" reports, and used to reconstruct a partial tree that is used for phony merge base tree when falling back on 3-way merge. (2) mode SP type SP sha1 TAB path The second format is to stuff git-ls-tree output into the index file. (3) mode SP sha1 SP stage TAB path This format is to put higher order stages into the index file and matches git-ls-files --stage output. To place a higher stage entry to the index, the path should first be removed by feeding a mode=0 entry for the path, and then feeding necessary input lines in the (3) format. For example, starting with this index: $ git ls-files -s 100644 8a1218a1024a212bb3db30becd860315f9f3ac52 0 frotz $ git update-index --index-info ;# interactive session -- input follows... 0 0000000000000000000000000000000000000000 frotz 100644 8a1218a1024a212bb3db30becd860315f9f3ac52 1 frotz 100755 8a1218a1024a212bb3db30becd860315f9f3ac52 2 frotz The first line of the input feeds 0 as the mode to remove the path; the SHA1 does not matter as long as it is well formatted. Then the second and third line feeds stage 1 and stage 2 entries for that path. After the above, we would end up with this: $ git ls-files -s 100644 8a1218a1024a212bb3db30becd860315f9f3ac52 1 frotz 100755 8a1218a1024a212bb3db30becd860315f9f3ac52 2 frotz This completes the groundwork for the new merge world order. Signed-off-by: Junio C Hamano <junkio@cox.net>
2005-12-07 12:45:38 +03:00
if (tab[-2] == ' ' && '0' <= tab[-1] && tab[-1] <= '3') {
update-index: allow --index-info to add higher stages. The new merge world order tells the merge strategies to leave the cache unmerged and store the automerge result in the working tree if automerge is not clean. This was done for the resolve strategy and recursive strategy when no rename is involved, but recording a conflicting merge in the rename case could not easily be done by the recursive strategy. This commit adds a new input format, in addition to the exsting two, to "update-index --index-info". (1) mode SP sha1 TAB path The first format is what "git-apply --index-info" reports, and used to reconstruct a partial tree that is used for phony merge base tree when falling back on 3-way merge. (2) mode SP type SP sha1 TAB path The second format is to stuff git-ls-tree output into the index file. (3) mode SP sha1 SP stage TAB path This format is to put higher order stages into the index file and matches git-ls-files --stage output. To place a higher stage entry to the index, the path should first be removed by feeding a mode=0 entry for the path, and then feeding necessary input lines in the (3) format. For example, starting with this index: $ git ls-files -s 100644 8a1218a1024a212bb3db30becd860315f9f3ac52 0 frotz $ git update-index --index-info ;# interactive session -- input follows... 0 0000000000000000000000000000000000000000 frotz 100644 8a1218a1024a212bb3db30becd860315f9f3ac52 1 frotz 100755 8a1218a1024a212bb3db30becd860315f9f3ac52 2 frotz The first line of the input feeds 0 as the mode to remove the path; the SHA1 does not matter as long as it is well formatted. Then the second and third line feeds stage 1 and stage 2 entries for that path. After the above, we would end up with this: $ git ls-files -s 100644 8a1218a1024a212bb3db30becd860315f9f3ac52 1 frotz 100755 8a1218a1024a212bb3db30becd860315f9f3ac52 2 frotz This completes the groundwork for the new merge world order. Signed-off-by: Junio C Hamano <junkio@cox.net>
2005-12-07 12:45:38 +03:00
stage = tab[-1] - '0';
ptr = tab + 1; /* point at the head of path */
tab = tab - 2; /* point at tail of sha1 */
}
else {
stage = 0;
ptr = tab + 1; /* point at the head of path */
}
if (get_sha1_hex(tab - 40, sha1) || tab[-41] != ' ')
goto bad_line;
if (line_termination && ptr[0] == '"')
path_name = unquote_c_style(ptr, NULL);
else
path_name = ptr;
if (!verify_path(path_name)) {
fprintf(stderr, "Ignoring path %s\n", path_name);
if (path_name != ptr)
free(path_name);
continue;
}
if (!mode) {
/* mode == 0 means there is no such path -- remove */
if (remove_file_from_cache(path_name))
die("git-update-index: unable to remove %s",
ptr);
}
else {
/* mode ' ' sha1 '\t' name
* ptr[-1] points at tab,
* ptr[-41] is at the beginning of sha1
*/
ptr[-42] = ptr[-1] = 0;
update-index: allow --index-info to add higher stages. The new merge world order tells the merge strategies to leave the cache unmerged and store the automerge result in the working tree if automerge is not clean. This was done for the resolve strategy and recursive strategy when no rename is involved, but recording a conflicting merge in the rename case could not easily be done by the recursive strategy. This commit adds a new input format, in addition to the exsting two, to "update-index --index-info". (1) mode SP sha1 TAB path The first format is what "git-apply --index-info" reports, and used to reconstruct a partial tree that is used for phony merge base tree when falling back on 3-way merge. (2) mode SP type SP sha1 TAB path The second format is to stuff git-ls-tree output into the index file. (3) mode SP sha1 SP stage TAB path This format is to put higher order stages into the index file and matches git-ls-files --stage output. To place a higher stage entry to the index, the path should first be removed by feeding a mode=0 entry for the path, and then feeding necessary input lines in the (3) format. For example, starting with this index: $ git ls-files -s 100644 8a1218a1024a212bb3db30becd860315f9f3ac52 0 frotz $ git update-index --index-info ;# interactive session -- input follows... 0 0000000000000000000000000000000000000000 frotz 100644 8a1218a1024a212bb3db30becd860315f9f3ac52 1 frotz 100755 8a1218a1024a212bb3db30becd860315f9f3ac52 2 frotz The first line of the input feeds 0 as the mode to remove the path; the SHA1 does not matter as long as it is well formatted. Then the second and third line feeds stage 1 and stage 2 entries for that path. After the above, we would end up with this: $ git ls-files -s 100644 8a1218a1024a212bb3db30becd860315f9f3ac52 1 frotz 100755 8a1218a1024a212bb3db30becd860315f9f3ac52 2 frotz This completes the groundwork for the new merge world order. Signed-off-by: Junio C Hamano <junkio@cox.net>
2005-12-07 12:45:38 +03:00
if (add_cacheinfo(mode, sha1, path_name, stage))
die("git-update-index: unable to update %s",
path_name);
}
if (path_name != ptr)
free(path_name);
continue;
bad_line:
die("malformed index info %s", buf.buf);
}
}
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';
int allow_options = 1;
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);
newfd = hold_index_file_for_update(&cache_file, get_index_file());
if (newfd < 0)
die("unable to create new cachefile");
entries = read_cache();
if (entries < 0)
die("cache corrupted");
for (i = 1 ; i < argc; i++) {
const char *path = argv[i];
if (allow_options && *path == '-') {
if (!strcmp(path, "--")) {
allow_options = 0;
continue;
}
if (!strcmp(path, "-q")) {
quiet = 1;
continue;
}
if (!strcmp(path, "--add")) {
allow_add = 1;
continue;
}
if (!strcmp(path, "--replace")) {
allow_replace = 1;
continue;
}
if (!strcmp(path, "--remove")) {
allow_remove = 1;
continue;
}
if (!strcmp(path, "--unmerged")) {
allow_unmerged = 1;
continue;
}
if (!strcmp(path, "--refresh")) {
"Assume unchanged" git This adds "assume unchanged" logic, started by this message in the list discussion recently: <Pine.LNX.4.64.0601311807470.7301@g5.osdl.org> This is a workaround for filesystems that do not have lstat() that is quick enough for the index mechanism to take advantage of. On the paths marked as "assumed to be unchanged", the user needs to explicitly use update-index to register the object name to be in the next commit. You can use two new options to update-index to set and reset the CE_VALID bit: git-update-index --assume-unchanged path... git-update-index --no-assume-unchanged path... These forms manipulate only the CE_VALID bit; it does not change the object name recorded in the index file. Nor they add a new entry to the index. When the configuration variable "core.ignorestat = true" is set, the index entries are marked with CE_VALID bit automatically after: - update-index to explicitly register the current object name to the index file. - when update-index --refresh finds the path to be up-to-date. - when tools like read-tree -u and apply --index update the working tree file and register the current object name to the index file. The flag is dropped upon read-tree that does not check out the index entry. This happens regardless of the core.ignorestat settings. Index entries marked with CE_VALID bit are assumed to be unchanged most of the time. However, there are cases that CE_VALID bit is ignored for the sake of safety and usability: - while "git-read-tree -m" or git-apply need to make sure that the paths involved in the merge do not have local modifications. This sacrifices performance for safety. - when git-checkout-index -f -q -u -a tries to see if it needs to checkout the paths. Otherwise you can never check anything out ;-). - when git-update-index --really-refresh (a new flag) tries to see if the index entry is up to date. You can start with everything marked as CE_VALID and run this once to drop CE_VALID bit for paths that are modified. Most notably, "update-index --refresh" honours CE_VALID and does not actively stat, so after you modified a file in the working tree, update-index --refresh would not notice until you tell the index about it with "git-update-index path" or "git-update-index --no-assume-unchanged path". This version is not expected to be perfect. I think diff between index and/or tree and working files may need some adjustment, and there probably needs other cases we should automatically unmark paths that are marked to be CE_VALID. But the basics seem to work, and ready to be tested by people who asked for this feature. Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-02-09 08:15:24 +03:00
has_errors |= refresh_cache(0);
continue;
}
if (!strcmp(path, "--really-refresh")) {
has_errors |= refresh_cache(1);
continue;
}
if (!strcmp(path, "--cacheinfo")) {
update-index: allow --index-info to add higher stages. The new merge world order tells the merge strategies to leave the cache unmerged and store the automerge result in the working tree if automerge is not clean. This was done for the resolve strategy and recursive strategy when no rename is involved, but recording a conflicting merge in the rename case could not easily be done by the recursive strategy. This commit adds a new input format, in addition to the exsting two, to "update-index --index-info". (1) mode SP sha1 TAB path The first format is what "git-apply --index-info" reports, and used to reconstruct a partial tree that is used for phony merge base tree when falling back on 3-way merge. (2) mode SP type SP sha1 TAB path The second format is to stuff git-ls-tree output into the index file. (3) mode SP sha1 SP stage TAB path This format is to put higher order stages into the index file and matches git-ls-files --stage output. To place a higher stage entry to the index, the path should first be removed by feeding a mode=0 entry for the path, and then feeding necessary input lines in the (3) format. For example, starting with this index: $ git ls-files -s 100644 8a1218a1024a212bb3db30becd860315f9f3ac52 0 frotz $ git update-index --index-info ;# interactive session -- input follows... 0 0000000000000000000000000000000000000000 frotz 100644 8a1218a1024a212bb3db30becd860315f9f3ac52 1 frotz 100755 8a1218a1024a212bb3db30becd860315f9f3ac52 2 frotz The first line of the input feeds 0 as the mode to remove the path; the SHA1 does not matter as long as it is well formatted. Then the second and third line feeds stage 1 and stage 2 entries for that path. After the above, we would end up with this: $ git ls-files -s 100644 8a1218a1024a212bb3db30becd860315f9f3ac52 1 frotz 100755 8a1218a1024a212bb3db30becd860315f9f3ac52 2 frotz This completes the groundwork for the new merge world order. Signed-off-by: Junio C Hamano <junkio@cox.net>
2005-12-07 12:45:38 +03:00
unsigned char sha1[20];
unsigned int mode;
if (i+3 >= argc)
die("git-update-index: --cacheinfo <mode> <sha1> <path>");
update-index: allow --index-info to add higher stages. The new merge world order tells the merge strategies to leave the cache unmerged and store the automerge result in the working tree if automerge is not clean. This was done for the resolve strategy and recursive strategy when no rename is involved, but recording a conflicting merge in the rename case could not easily be done by the recursive strategy. This commit adds a new input format, in addition to the exsting two, to "update-index --index-info". (1) mode SP sha1 TAB path The first format is what "git-apply --index-info" reports, and used to reconstruct a partial tree that is used for phony merge base tree when falling back on 3-way merge. (2) mode SP type SP sha1 TAB path The second format is to stuff git-ls-tree output into the index file. (3) mode SP sha1 SP stage TAB path This format is to put higher order stages into the index file and matches git-ls-files --stage output. To place a higher stage entry to the index, the path should first be removed by feeding a mode=0 entry for the path, and then feeding necessary input lines in the (3) format. For example, starting with this index: $ git ls-files -s 100644 8a1218a1024a212bb3db30becd860315f9f3ac52 0 frotz $ git update-index --index-info ;# interactive session -- input follows... 0 0000000000000000000000000000000000000000 frotz 100644 8a1218a1024a212bb3db30becd860315f9f3ac52 1 frotz 100755 8a1218a1024a212bb3db30becd860315f9f3ac52 2 frotz The first line of the input feeds 0 as the mode to remove the path; the SHA1 does not matter as long as it is well formatted. Then the second and third line feeds stage 1 and stage 2 entries for that path. After the above, we would end up with this: $ git ls-files -s 100644 8a1218a1024a212bb3db30becd860315f9f3ac52 1 frotz 100755 8a1218a1024a212bb3db30becd860315f9f3ac52 2 frotz This completes the groundwork for the new merge world order. Signed-off-by: Junio C Hamano <junkio@cox.net>
2005-12-07 12:45:38 +03:00
if ((sscanf(argv[i+1], "%o", &mode) != 1) ||
get_sha1_hex(argv[i+2], sha1) ||
add_cacheinfo(mode, sha1, argv[i+3], 0))
die("git-update-index: --cacheinfo"
" cannot add %s", argv[i+3]);
i += 3;
continue;
}
if (!strcmp(path, "--chmod=-x") ||
!strcmp(path, "--chmod=+x")) {
if (argc <= i+1)
die("git-update-index: %s <path>", path);
set_executable_bit = path[8];
continue;
}
"Assume unchanged" git This adds "assume unchanged" logic, started by this message in the list discussion recently: <Pine.LNX.4.64.0601311807470.7301@g5.osdl.org> This is a workaround for filesystems that do not have lstat() that is quick enough for the index mechanism to take advantage of. On the paths marked as "assumed to be unchanged", the user needs to explicitly use update-index to register the object name to be in the next commit. You can use two new options to update-index to set and reset the CE_VALID bit: git-update-index --assume-unchanged path... git-update-index --no-assume-unchanged path... These forms manipulate only the CE_VALID bit; it does not change the object name recorded in the index file. Nor they add a new entry to the index. When the configuration variable "core.ignorestat = true" is set, the index entries are marked with CE_VALID bit automatically after: - update-index to explicitly register the current object name to the index file. - when update-index --refresh finds the path to be up-to-date. - when tools like read-tree -u and apply --index update the working tree file and register the current object name to the index file. The flag is dropped upon read-tree that does not check out the index entry. This happens regardless of the core.ignorestat settings. Index entries marked with CE_VALID bit are assumed to be unchanged most of the time. However, there are cases that CE_VALID bit is ignored for the sake of safety and usability: - while "git-read-tree -m" or git-apply need to make sure that the paths involved in the merge do not have local modifications. This sacrifices performance for safety. - when git-checkout-index -f -q -u -a tries to see if it needs to checkout the paths. Otherwise you can never check anything out ;-). - when git-update-index --really-refresh (a new flag) tries to see if the index entry is up to date. You can start with everything marked as CE_VALID and run this once to drop CE_VALID bit for paths that are modified. Most notably, "update-index --refresh" honours CE_VALID and does not actively stat, so after you modified a file in the working tree, update-index --refresh would not notice until you tell the index about it with "git-update-index path" or "git-update-index --no-assume-unchanged path". This version is not expected to be perfect. I think diff between index and/or tree and working files may need some adjustment, and there probably needs other cases we should automatically unmark paths that are marked to be CE_VALID. But the basics seem to work, and ready to be tested by people who asked for this feature. Signed-off-by: Junio C Hamano <junkio@cox.net>
2006-02-09 08:15:24 +03:00
if (!strcmp(path, "--assume-unchanged")) {
mark_valid_only = MARK_VALID;
continue;
}
if (!strcmp(path, "--no-assume-unchanged")) {
mark_valid_only = UNMARK_VALID;
continue;
}
if (!strcmp(path, "--info-only")) {
info_only = 1;
continue;
}
if (!strcmp(path, "--force-remove")) {
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, "--index-info")) {
if (i != argc - 1)
die("--index-info must be at the end");
allow_add = allow_replace = allow_remove = 1;
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;
}
if (!strcmp(path, "--verbose")) {
verbose = 1;
continue;
}
if (!strcmp(path, "-h") || !strcmp(path, "--help"))
usage(update_index_usage);
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;
strbuf_init(&buf);
while (1) {
char *path_name;
read_line(&buf, stdin, line_termination);
if (buf.eof)
break;
if (line_termination && buf.buf[0] == '"')
path_name = unquote_c_style(buf.buf, NULL);
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))
die("Unable to write new cachefile");
}
return has_errors ? 1 : 0;
}