diff options
| -rw-r--r-- | src/git/common.h | 3 | ||||
| -rw-r--r-- | src/git/index.h | 39 | ||||
| -rw-r--r-- | src/index.c | 131 | ||||
| -rw-r--r-- | src/index.h | 3 | ||||
| -rw-r--r-- | src/repository.c | 4 | ||||
| -rw-r--r-- | tests/t0601-read.c | 10 | ||||
| -rw-r--r-- | tests/t0602-write.c | 2 | ||||
| -rw-r--r-- | tests/t0603-sort.c | 4 | 
8 files changed, 139 insertions, 57 deletions
diff --git a/src/git/common.h b/src/git/common.h index 82f08ac5d..cbc77e991 100644 --- a/src/git/common.h +++ b/src/git/common.h @@ -105,6 +105,9 @@  /** The queried object is currently busy */  #define GIT_EBUSY (GIT_ERROR - 13) +/** The index file is not backed up by an existing repository */ +#define GIT_EBAREINDEX (GIT_ERROR -14) +  GIT_BEGIN_DECL diff --git a/src/git/index.h b/src/git/index.h index 8220e6290..6cf270baa 100644 --- a/src/git/index.h +++ b/src/git/index.h @@ -47,21 +47,28 @@ typedef struct git_index_entry {  /**   * Create a new Git index object as a memory representation - * of the Git index file in 'index_path'. + * of the Git index file in 'index_path', without a repository + * to back it.   * - * The argument 'working_dir' is the root path of the indexed - * files in the index and is used to calculate the relative path - * when inserting new entries from existing files on disk. - * - * If 'working _dir' is NULL (e.g for bare repositories), the - * methods working on on-disk files will fail. + * Since there is no ODB behind this index, any Index methods + * which rely on the ODB (e.g. index_add) will fail with the + * GIT_EBAREINDEX error code.   *   * @param index the pointer for the new index   * @param index_path the path to the index file in disk - * @param working_dir working dir for the git repository   * @return 0 on success; error code otherwise   */ -GIT_EXTERN(int) git_index_open(git_index **index, const char *index_path, const char *working_dir); +GIT_EXTERN(int) git_index_open_bare(git_index **index, const char *index_path); + +/** + * Open the Index inside the git repository pointed + * by 'repo'. + * + * @param repo the git repo which owns the index + * @param index_path the path to the index file in disk + * @return 0 on success; error code otherwise + */ +GIT_EXTERN(int) git_index_open_inrepo(git_index **index, git_repository *repo);  /**   * Clear the contents (all the entries) of an index object. @@ -108,14 +115,14 @@ GIT_EXTERN(int) git_index_write(git_index *index);  GIT_EXTERN(int) git_index_find(git_index *index, const char *path);  /** - * Add a new empty entry to the index with a given path. + * Add or update an index entry from a file in disk.   *   * @param index an existing index object - * @param path filename pointed to by the entry + * @param path filename to add   * @param stage stage for the entry   * @return 0 on success, otherwise an error code   */ -GIT_EXTERN(int) git_index_add_bypath(git_index *index, const char *path, int stage); +GIT_EXTERN(int) git_index_add(git_index *index, const char *path, int stage);  /**   * Remove an entry from the index  @@ -127,13 +134,17 @@ GIT_EXTERN(int) git_index_add_bypath(git_index *index, const char *path, int sta  GIT_EXTERN(int) git_index_remove(git_index *index, int position);  /** - * Add a new entry to the index  + * Insert an entry into the index. + * A full copy (including the 'path' string) of the given + * 'source_entry' will be inserted on the index; if the index + * already contains an entry for the same path, the entry + * will be updated.   *   * @param index an existing index object   * @param source_entry new entry object   * @return 0 on success, otherwise an error code   */ -GIT_EXTERN(int) git_index_add(git_index *index, const git_index_entry *source_entry); +GIT_EXTERN(int) git_index_insert(git_index *index, const git_index_entry *source_entry);  /**   * Get a pointer to one of the entries in the index diff --git a/src/index.c b/src/index.c index ed85f912d..accb244b2 100644 --- a/src/index.c +++ b/src/index.c @@ -26,9 +26,11 @@  #include <stddef.h>  #include "common.h" +#include "repository.h"  #include "index.h"  #include "hash.h"  #include "git/odb.h" +#include "git/blob.h"  #define entry_padding(type, len) (8 - ((offsetof(type, path) + (len)) & 0x7))  #define short_entry_padding(len) entry_padding(struct entry_short, len) @@ -97,7 +99,7 @@ static int read_tree(git_index *index, const char *buffer, size_t buffer_size);  static git_index_tree *read_tree_internal(const char **, const char *, git_index_tree *); -int git_index_open(git_index **index_out, const char *index_path, const char *work_dir) +static int index_initialize(git_index **index_out, git_repository *owner, const char *index_path)  {  	git_index *index; @@ -115,8 +117,7 @@ int git_index_open(git_index **index_out, const char *index_path, const char *wo  		return GIT_ENOMEM;  	} -	if (work_dir != NULL) -		index->working_path = git__strdup(work_dir); +	index->repository = owner;  	/* Check if index file is stored on disk already */  	if (gitfo_exists(index->index_file_path) == 0) @@ -126,6 +127,16 @@ int git_index_open(git_index **index_out, const char *index_path, const char *wo  	return GIT_SUCCESS;  } +int git_index_open_bare(git_index **index_out, const char *index_path) +{ +	return index_initialize(index_out, NULL, index_path); +} + +int git_index_open_inrepo(git_index **index_out, git_repository *repo) +{ +	return index_initialize(index_out, repo, repo->path_index); +} +  void git_index_clear(git_index *index)  {  	unsigned int i; @@ -233,28 +244,49 @@ git_index_entry *git_index_get(git_index *index, int n)  	return (n >= 0 && (unsigned int)n < index->entry_count) ? &index->entries[n] : NULL;  } -int git_index_add_bypath(git_index *index, const char *filename, int stage) +int git_index_add(git_index *index, const char *rel_path, int stage)  {  	git_index_entry entry; -	size_t path_length; +	char full_path[GIT_PATH_MAX]; +	struct stat st; +	int error; -	memset(&entry, 0x0, sizeof(git_index_entry)); +	if (index->repository == NULL) +		return GIT_EBAREINDEX; -	path_length = strlen(filename); +	strcpy(full_path, index->repository->path_workdir); +	strcat(full_path, rel_path); -	if (path_length < GIT_IDXENTRY_NAMEMASK) -		entry.flags |= path_length; -	else -		entry.flags |= GIT_IDXENTRY_NAMEMASK;; +	if (gitfo_exists(full_path) < 0) +		return GIT_ENOTFOUND; + +	if (gitfo_stat(full_path, &st) < 0) +		return GIT_EOSERR;  	if (stage < 0 || stage > 3)  		return GIT_ERROR; -	entry.flags |= (stage << GIT_IDXENTRY_STAGESHIFT); +	memset(&entry, 0x0, sizeof(git_index_entry)); -	entry.path = git__strdup(filename); +	entry.ctime.seconds = st.st_ctime; +	entry.mtime.seconds = st.st_mtime; +	/* entry.mtime.nanoseconds = st.st_mtimensec; */ +	/* entry.ctime.nanoseconds = st.st_ctimensec; */ +	entry.dev= st.st_rdev; +	entry.ino = st.st_ino; +	entry.mode = st.st_mode; +	entry.uid = st.st_uid; +	entry.gid = st.st_gid; +	entry.file_size = st.st_size; + +	/* write the blob to disk and get the oid */ +	if ((error = git_blob_writefile(&entry.oid, index->repository, full_path)) < 0) +		return error; -	return git_index_add(index, &entry); +	entry.flags |= (stage << GIT_IDXENTRY_STAGESHIFT); +	entry.path = (char *)rel_path; /* do not duplicate; index_insert already does this */ + +	return git_index_insert(index, &entry);  }  void git_index__sort(git_index *index) @@ -281,31 +313,66 @@ void git_index__sort(git_index *index)  	index->sorted = 1;  } -int git_index_add(git_index *index, const git_index_entry *source_entry) +int git_index_insert(git_index *index, const git_index_entry *source_entry)  {  	git_index_entry *offset; +	size_t path_length; +	int position; -	/* Resize the entries array */ -	if (index->entry_count + 1 > index->entries_size) { -		git_index_entry *new_entries; -		size_t new_size; +	assert(index && source_entry); -		new_size = (unsigned int)(index->entries_size * 1.5f); -		if ((new_entries = git__malloc(new_size * sizeof(git_index_entry))) == NULL) -			return GIT_ENOMEM; +	if (source_entry->path == NULL) +		return GIT_EMISSINGOBJDATA; -		memcpy(new_entries, index->entries, index->entry_count * sizeof(git_index_entry)); -		free(index->entries); +	position = git_index_find(index, source_entry->path); -		index->entries_size = new_size; -		index->entries = new_entries; -	} +	if (position == GIT_ENOTFOUND) { + +		/* Resize the entries array */ +		if (index->entry_count + 1 > index->entries_size) { +			git_index_entry *new_entries; +			size_t new_size; + +			new_size = (unsigned int)(index->entries_size * 1.5f); +			if ((new_entries = git__malloc(new_size * sizeof(git_index_entry))) == NULL) +				return GIT_ENOMEM; + +			memcpy(new_entries, index->entries, index->entry_count * sizeof(git_index_entry)); +			free(index->entries); + +			index->entries_size = new_size; +			index->entries = new_entries; +		} -	offset = &index->entries[index->entry_count]; -	index->entry_count++; +		offset = &index->entries[index->entry_count]; +		index->entry_count++; +		index->sorted = 0; +	 +	} else { +		offset = &index->entries[position]; +		free(offset->path); +	}  	memcpy(offset, source_entry, sizeof(git_index_entry)); -	index->sorted = 0; + +	/* duplicate the path string so we own it */ +	offset->path = git__strdup(source_entry->path); +	if (offset->path == NULL) +		return GIT_ENOMEM; + +	/* make sure that the path length flag is correct */ +	path_length = strlen(offset->path); + +	offset->flags &= ~GIT_IDXENTRY_NAMEMASK; + +	if (path_length < GIT_IDXENTRY_NAMEMASK) +		offset->flags |= path_length & GIT_IDXENTRY_NAMEMASK; +	else +		offset->flags |= GIT_IDXENTRY_NAMEMASK;; + +	/* TODO: force the extended index entry flag? */ + +	assert(offset->path);  	return GIT_SUCCESS;  } @@ -500,6 +567,7 @@ static size_t read_entry(git_index_entry *dest, const void *buffer, size_t buffe  		return 0;  	dest->path = git__strdup(path_ptr); +	assert(dest->path);  	return entry_size;  } @@ -602,6 +670,9 @@ int git_index__parse(git_index *index, const char *buffer, size_t buffer_size)  		seek_forward(entry_size);  	} +	if (i != index->entry_count) +		return GIT_EOBJCORRUPTED; +  	/* There's still space for some extensions! */  	while (buffer_size > INDEX_FOOTER_SIZE) {  		size_t extension_size; diff --git a/src/index.h b/src/index.h index 6a3c11e82..818f1f120 100644 --- a/src/index.h +++ b/src/index.h @@ -26,9 +26,8 @@ struct git_index_tree {  typedef struct git_index_tree git_index_tree;  struct git_index { - +	git_repository *repository;  	char *index_file_path; -	char *working_path;  	time_t last_modified; diff --git a/src/repository.c b/src/repository.c index 4beb3e0c7..ef51b08e7 100644 --- a/src/repository.c +++ b/src/repository.c @@ -196,7 +196,7 @@ void git_repository_free(git_repository *repo)  git_index *git_repository_index(git_repository *repo)  {  	if (repo->index == NULL) { -		if (git_index_open(&repo->index, repo->path_index, repo->path_workdir) < 0) +		if (git_index_open_inrepo(&repo->index, repo) < 0)  			return NULL;  		assert(repo->index && repo->index->on_disk); @@ -298,8 +298,6 @@ static int write_back(git_object *object)  	object->source.raw.len = object->source.written_bytes; -	git_obj_hash(&new_id, &object->source.raw); -  	if ((error = git_odb_write(&new_id, object->repo->db, &object->source.raw)) < 0)  		return error; diff --git a/tests/t0601-read.c b/tests/t0601-read.c index 133a26679..615674509 100644 --- a/tests/t0601-read.c +++ b/tests/t0601-read.c @@ -29,7 +29,7 @@ struct test_entry TEST_ENTRIES[] = {  BEGIN_TEST(index_loadempty_test)  	git_index *index; -	must_pass(git_index_open(&index, "in-memory-index", NULL)); +	must_pass(git_index_open_bare(&index, "in-memory-index"));  	must_be_true(index->on_disk == 0);  	must_pass(git_index_read(index)); @@ -45,7 +45,7 @@ BEGIN_TEST(index_load_test)  	git_index *index;  	unsigned int i; -	must_pass(git_index_open(&index, TEST_INDEX_PATH, NULL)); +	must_pass(git_index_open_bare(&index, TEST_INDEX_PATH));  	must_be_true(index->on_disk);  	must_pass(git_index_read(index)); @@ -68,7 +68,7 @@ END_TEST  BEGIN_TEST(index2_load_test)  	git_index *index; -	must_pass(git_index_open(&index, TEST_INDEX2_PATH, NULL)); +	must_pass(git_index_open_bare(&index, TEST_INDEX2_PATH));  	must_be_true(index->on_disk);  	must_pass(git_index_read(index)); @@ -85,7 +85,7 @@ BEGIN_TEST(index_find_test)  	git_index *index;  	unsigned int i; -	must_pass(git_index_open(&index, TEST_INDEX_PATH, NULL)); +	must_pass(git_index_open_bare(&index, TEST_INDEX_PATH));  	must_pass(git_index_read(index));  	for (i = 0; i < ARRAY_SIZE(TEST_ENTRIES); ++i) { @@ -100,7 +100,7 @@ BEGIN_TEST(index_findempty_test)  	git_index *index;  	unsigned int i; -	must_pass(git_index_open(&index, "fake-index", NULL)); +	must_pass(git_index_open_bare(&index, "fake-index"));  	for (i = 0; i < ARRAY_SIZE(TEST_ENTRIES); ++i) {  		int idx = git_index_find(index, TEST_ENTRIES[i].path); diff --git a/tests/t0602-write.c b/tests/t0602-write.c index 415183f94..6463773fb 100644 --- a/tests/t0602-write.c +++ b/tests/t0602-write.c @@ -35,7 +35,7 @@ BEGIN_TEST(index_load_test)  	git_index *index;  	git_filelock out_file; -	must_pass(git_index_open(&index, TEST_INDEX_PATH, NULL)); +	must_pass(git_index_open_bare(&index, TEST_INDEX_PATH));  	must_pass(git_index_read(index));  	must_be_true(index->on_disk); diff --git a/tests/t0603-sort.c b/tests/t0603-sort.c index 0ee14d713..d47c93c77 100644 --- a/tests/t0603-sort.c +++ b/tests/t0603-sort.c @@ -36,7 +36,7 @@ BEGIN_TEST(index_sort_test)  	git_index *index;  	unsigned int i; -	must_pass(git_index_open(&index, TEST_INDEX_PATH, NULL)); +	must_pass(git_index_open_bare(&index, TEST_INDEX_PATH));  	must_pass(git_index_read(index));  	randomize_entries(index); @@ -54,7 +54,7 @@ END_TEST  BEGIN_TEST(index_sort_empty_test)  	git_index *index; -	must_pass(git_index_open(&index, "fake-index", NULL)); +	must_pass(git_index_open_bare(&index, "fake-index"));  	git_index__sort(index);  	must_be_true(index->sorted);  | 
