summaryrefslogtreecommitdiff
path: root/src/index.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/index.c')
-rw-r--r--src/index.c131
1 files changed, 101 insertions, 30 deletions
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;