mirror of
https://github.com/git/git
synced 2024-08-24 18:26:02 +00:00
![Linus Torvalds](/assets/img/avatar_default.png)
After git-write-tree finishes computing the tree, it updates the index so that later operations can take advantage of fully populated cache tree. However, anybody writing the index file has to mark the entries that are racily clean. For each entry whose cached lstat(3) data in the index exactly matches what is obtained from the filesystem, if the timestamp on the index file was the same or older than the modification timestamp of the file, the blob contents and the work tree file, after convert_to_git(), need to be compared, and if they are different, its index entry needs to be marked not to match the lstat(3) data from the filesystem. In order for this to work, convert_to_git() needs to work correctly, which in turn means you need to read the config file to get the settings of core.crlf and friends. Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>
95 lines
2.2 KiB
C
95 lines
2.2 KiB
C
/*
|
|
* GIT - The information manager from hell
|
|
*
|
|
* Copyright (C) Linus Torvalds, 2005
|
|
*/
|
|
#include "builtin.h"
|
|
#include "cache.h"
|
|
#include "tree.h"
|
|
#include "cache-tree.h"
|
|
|
|
static const char write_tree_usage[] =
|
|
"git-write-tree [--missing-ok] [--prefix=<prefix>/]";
|
|
|
|
int write_tree(unsigned char *sha1, int missing_ok, const char *prefix)
|
|
{
|
|
int entries, was_valid, newfd;
|
|
|
|
/* We can't free this memory, it becomes part of a linked list parsed atexit() */
|
|
struct lock_file *lock_file = xcalloc(1, sizeof(struct lock_file));
|
|
|
|
newfd = hold_locked_index(lock_file, 1);
|
|
|
|
entries = read_cache();
|
|
if (entries < 0)
|
|
die("git-write-tree: error reading cache");
|
|
|
|
if (!active_cache_tree)
|
|
active_cache_tree = cache_tree();
|
|
|
|
was_valid = cache_tree_fully_valid(active_cache_tree);
|
|
|
|
if (!was_valid) {
|
|
if (cache_tree_update(active_cache_tree,
|
|
active_cache, active_nr,
|
|
missing_ok, 0) < 0)
|
|
die("git-write-tree: error building trees");
|
|
if (0 <= newfd) {
|
|
if (!write_cache(newfd, active_cache, active_nr)
|
|
&& !close(newfd)) {
|
|
commit_lock_file(lock_file);
|
|
newfd = -1;
|
|
}
|
|
}
|
|
/* Not being able to write is fine -- we are only interested
|
|
* in updating the cache-tree part, and if the next caller
|
|
* ends up using the old index with unupdated cache-tree part
|
|
* it misses the work we did here, but that is just a
|
|
* performance penalty and not a big deal.
|
|
*/
|
|
}
|
|
|
|
if (prefix) {
|
|
struct cache_tree *subtree =
|
|
cache_tree_find(active_cache_tree, prefix);
|
|
if (!subtree)
|
|
die("git-write-tree: prefix %s not found", prefix);
|
|
hashcpy(sha1, subtree->sha1);
|
|
}
|
|
else
|
|
hashcpy(sha1, active_cache_tree->sha1);
|
|
|
|
if (0 <= newfd)
|
|
close(newfd);
|
|
rollback_lock_file(lock_file);
|
|
|
|
return 0;
|
|
}
|
|
|
|
int cmd_write_tree(int argc, const char **argv, const char *unused_prefix)
|
|
{
|
|
int missing_ok = 0, ret;
|
|
const char *prefix = NULL;
|
|
unsigned char sha1[20];
|
|
|
|
git_config(git_default_config);
|
|
while (1 < argc) {
|
|
const char *arg = argv[1];
|
|
if (!strcmp(arg, "--missing-ok"))
|
|
missing_ok = 1;
|
|
else if (!prefixcmp(arg, "--prefix="))
|
|
prefix = arg + 9;
|
|
else
|
|
usage(write_tree_usage);
|
|
argc--; argv++;
|
|
}
|
|
|
|
if (argc > 2)
|
|
die("too many options");
|
|
|
|
ret = write_tree(sha1, missing_ok, prefix);
|
|
printf("%s\n", sha1_to_hex(sha1));
|
|
|
|
return ret;
|
|
}
|