summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/git/common.h3
-rw-r--r--src/git/index.h39
-rw-r--r--src/index.c131
-rw-r--r--src/index.h3
-rw-r--r--src/repository.c4
-rw-r--r--tests/t0601-read.c10
-rw-r--r--tests/t0602-write.c2
-rw-r--r--tests/t0603-sort.c4
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);