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); |
