diff options
author | Carlos Martín Nieto <cmn@elego.de> | 2011-05-05 16:22:06 +0200 |
---|---|---|
committer | Carlos Martín Nieto <cmn@elego.de> | 2011-05-05 16:22:06 +0200 |
commit | ca8d2dfc0cea0c16e2d6bae16d95d652e292f473 (patch) | |
tree | f98e0c362a388f9a9efe644ac3e38828f5f14807 /src | |
parent | 094aaaaee92f4fc98a6c3c3af36183cb217948a8 (diff) | |
parent | cc3b82e376e0216c1af4ad46d24327d61e9efd99 (diff) | |
download | libgit2-ca8d2dfc0cea0c16e2d6bae16d95d652e292f473.tar.gz |
Merge remote-tracking branch 'upstream/development' into config
Diffstat (limited to 'src')
-rw-r--r-- | src/blob.c | 1 | ||||
-rw-r--r-- | src/commit.c | 13 | ||||
-rw-r--r-- | src/index.c | 156 | ||||
-rw-r--r-- | src/odb_loose.c | 3 | ||||
-rw-r--r-- | src/odb_pack.c | 80 | ||||
-rw-r--r-- | src/refs.c | 18 | ||||
-rw-r--r-- | src/refs.h | 1 | ||||
-rw-r--r-- | src/repository.c | 3 | ||||
-rw-r--r-- | src/revwalk.c | 4 | ||||
-rw-r--r-- | src/tag.c | 26 | ||||
-rw-r--r-- | src/tree.c | 3 |
11 files changed, 209 insertions, 99 deletions
diff --git a/src/blob.c b/src/blob.c index bc0a08a8a..5e3c22fbf 100644 --- a/src/blob.c +++ b/src/blob.c @@ -115,6 +115,7 @@ int git_blob_create_fromfile(git_oid *oid, git_repository *repo, const char *pat error = stream->finalize_write(oid, stream); stream->free(stream); + gitfo_close(fd); return error; } diff --git a/src/commit.c b/src/commit.c index 9621703c3..0c37ec59b 100644 --- a/src/commit.c +++ b/src/commit.c @@ -224,9 +224,18 @@ int git_commit_create( if (error < GIT_SUCCESS) return error; - if (git_reference_type(head) == GIT_REF_SYMBOLIC) { - if ((error = git_reference_resolve(&head, head)) < GIT_SUCCESS) + error = git_reference_resolve(&head, head); + if (error < GIT_SUCCESS) { + if (error != GIT_ENOTFOUND) return error; + /* + * The target of the reference was not found. This can happen + * just after a repository has been initialized (the master + * branch doesn't exist yet, as it doesn't have anything to + * point to) or after an orphan checkout, so if the target + * branch doesn't exist yet, create it and return. + */ + return git_reference_create_oid_f(&head, repo, git_reference_target(head), oid); } error = git_reference_set_oid(head, oid); diff --git a/src/index.c b/src/index.c index 68bb9e2b9..130d1fd36 100644 --- a/src/index.c +++ b/src/index.c @@ -101,6 +101,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 *); static int parse_index(git_index *index, const char *buffer, size_t buffer_size); +static int is_index_extended(git_index *index); static void sort_index(git_index *index); static int write_index(git_index *index, git_filebuf *file); @@ -289,56 +290,12 @@ git_index_entry *git_index_get(git_index *index, int n) return git_vector_get(&index->entries, (unsigned int)n); } -int git_index_add(git_index *index, const char *rel_path, int stage) -{ - git_index_entry entry; - char full_path[GIT_PATH_MAX]; - struct stat st; - int error; - - if (index->repository == NULL) - return GIT_EBAREINDEX; - - git__joinpath(full_path, index->repository->path_workdir, rel_path); - - 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; - - memset(&entry, 0x0, sizeof(git_index_entry)); - - entry.ctime.seconds = (git_time_t)st.st_ctime; - entry.mtime.seconds = (git_time_t)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_create_fromfile(&entry.oid, index->repository, rel_path)) < GIT_SUCCESS) - return error; - - 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 sort_index(git_index *index) +static void sort_index(git_index *index) { git_vector_sort(&index->entries); } -int git_index_insert(git_index *index, const git_index_entry *source_entry) +static int index_insert(git_index *index, const git_index_entry *source_entry, int replace) { git_index_entry *entry; size_t path_length; @@ -374,13 +331,15 @@ int git_index_insert(git_index *index, const git_index_entry *source_entry) /* look if an entry with this path already exists */ position = git_index_find(index, source_entry->path); - /* if no entry exists, add the entry at the end; + /* if no entry exists and replace is not set, + * add the entry at the end; * the index is no longer sorted */ - if (position == GIT_ENOTFOUND) { + if (!replace || position == GIT_ENOTFOUND) { if (git_vector_insert(&index->entries, entry) < GIT_SUCCESS) return GIT_ENOMEM; - /* if a previous entry exists, replace it */ + /* if a previous entry exists and replace is set, + * replace it */ } else { git_index_entry **entry_array = (git_index_entry **)index->entries.contents; @@ -393,6 +352,81 @@ int git_index_insert(git_index *index, const git_index_entry *source_entry) return GIT_SUCCESS; } +static int index_init_entry(git_index_entry *entry, git_index *index, const char *rel_path, int stage) +{ + char full_path[GIT_PATH_MAX]; + struct stat st; + int error; + + if (index->repository == NULL) + return GIT_EBAREINDEX; + + git__joinpath(full_path, index->repository->path_workdir, rel_path); + + 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; + + memset(entry, 0x0, sizeof(git_index_entry)); + + entry->ctime.seconds = (git_time_t)st.st_ctime; + entry->mtime.seconds = (git_time_t)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_create_fromfile(&entry->oid, index->repository, rel_path)) < GIT_SUCCESS) + return error; + + entry->flags |= (stage << GIT_IDXENTRY_STAGESHIFT); + entry->path = (char *)rel_path; /* do not duplicate; index_insert already does this */ + return GIT_SUCCESS; +} + +int git_index_add(git_index *index, const char *path, int stage) +{ + int error; + git_index_entry entry; + + if ((error = index_init_entry(&entry, index, path, stage)) < GIT_SUCCESS) + return error; + + return index_insert(index, &entry, 1); +} + +int git_index_append(git_index *index, const char *path, int stage) +{ + int error; + git_index_entry entry; + + if ((error = index_init_entry(&entry, index, path, stage)) < GIT_SUCCESS) + return error; + + return index_insert(index, &entry, 0); +} + +int git_index_add2(git_index *index, const git_index_entry *source_entry) +{ + return index_insert(index, source_entry, 1); +} + +int git_index_apppend2(git_index *index, const git_index_entry *source_entry) +{ + return index_insert(index, source_entry, 0); +} + + int git_index_remove(git_index *index, int position) { assert(index); @@ -685,6 +719,24 @@ static int parse_index(git_index *index, const char *buffer, size_t buffer_size) return GIT_SUCCESS; } +static int is_index_extended(git_index *index) +{ + unsigned int i, extended; + + extended = 0; + + for (i = 0; i < index->entries.length; ++i) { + git_index_entry *entry; + entry = git_vector_get(&index->entries, i); + entry->flags &= ~GIT_IDXENTRY_EXTENDED; + if (entry->flags_extended & GIT_IDXENTRY_EXTENDED_FLAGS) { + extended++; + entry->flags |= GIT_IDXENTRY_EXTENDED; + } + } + return extended; +} + static int write_disk_entry(git_filebuf *file, git_index_entry *entry) { struct entry_short *ondisk; @@ -753,12 +805,14 @@ static int write_index(git_index *index, git_filebuf *file) struct index_header header; - int is_extended = 1; + int is_extended; assert(index && file); + is_extended = is_index_extended(index); + header.signature = htonl(INDEX_HEADER_SIG); - header.version = htonl(is_extended ? INDEX_VERSION_NUMBER : INDEX_VERSION_NUMBER_EXT); + header.version = htonl(is_extended ? INDEX_VERSION_NUMBER_EXT : INDEX_VERSION_NUMBER); header.entry_count = htonl(index->entries.length); git_filebuf_write(file, &header, sizeof(struct index_header)); diff --git a/src/odb_loose.c b/src/odb_loose.c index 8ee01cd2c..4f475f2c3 100644 --- a/src/odb_loose.c +++ b/src/odb_loose.c @@ -434,6 +434,9 @@ static int read_header_loose(git_rawobj *out, const char *loc) if ((read_bytes = read(fd, raw_buffer, sizeof(raw_buffer))) > 0) { set_stream_input(&zs, raw_buffer, read_bytes); z_return = inflate(&zs, 0); + } else { + z_return = Z_STREAM_END; + break; } } while (z_return == Z_OK); diff --git a/src/odb_pack.c b/src/odb_pack.c index 8c527bcf3..57ad5e34b 100644 --- a/src/odb_pack.c +++ b/src/odb_pack.c @@ -108,15 +108,12 @@ struct pack_entry { struct pack_file *p; }; -struct pack__dirent { - struct pack_backend *backend; - int is_pack_local; -}; - struct pack_backend { git_odb_backend parent; git_vector packs; struct pack_file *last_found; + char *pack_folder; + time_t pack_folder_mtime; size_t window_size; /* needs default value */ @@ -259,9 +256,9 @@ static int pack_index_open(struct pack_file *p); static struct pack_file *packfile_alloc(int extra); static int packfile_open(struct pack_file *p); -static int packfile_check(struct pack_file **pack_out, const char *path, int local); +static int packfile_check(struct pack_file **pack_out, const char *path); static int packfile_load__cb(void *_data, char *path); -static int packfile_load_all(struct pack_backend *backend, const char *odb_path, int local); +static int packfile_refresh_all(struct pack_backend *backend); static off_t nth_packed_object_offset(const struct pack_file *p, uint32_t n); @@ -790,7 +787,7 @@ cleanup: return GIT_EPACKCORRUPTED; } -static int packfile_check(struct pack_file **pack_out, const char *path, int local) +static int packfile_check(struct pack_file **pack_out, const char *path) { struct stat st; struct pack_file *p; @@ -826,7 +823,7 @@ static int packfile_check(struct pack_file **pack_out, const char *path, int loc * actually mapping the pack file. */ p->pack_size = (off_t)st.st_size; - p->pack_local = local; + p->pack_local = 1; p->mtime = (git_time_t)st.st_mtime; /* see if we can parse the sha1 oid in the packfile name */ @@ -840,22 +837,25 @@ static int packfile_check(struct pack_file **pack_out, const char *path, int loc static int packfile_load__cb(void *_data, char *path) { - struct pack__dirent *data = (struct pack__dirent *)_data; + struct pack_backend *backend = (struct pack_backend *)_data; struct pack_file *pack; int error; + size_t i; if (git__suffixcmp(path, ".idx") != 0) return GIT_SUCCESS; /* not an index */ - /* FIXME: git.git checks for duplicate packs. - * But that makes no fucking sense. Our dirent is not - * going to generate dupicate entries */ + for (i = 0; i < backend->packs.length; ++i) { + struct pack_file *p = git_vector_get(&backend->packs, i); + if (memcmp(p->pack_name, path, strlen(path) - STRLEN(".idx")) == 0) + return GIT_SUCCESS; + } - error = packfile_check(&pack, path, data->is_pack_local); + error = packfile_check(&pack, path); if (error < GIT_SUCCESS) return error; - if (git_vector_insert(&data->backend->packs, pack) < GIT_SUCCESS) { + if (git_vector_insert(&backend->packs, pack) < GIT_SUCCESS) { free(pack); return GIT_ENOMEM; } @@ -863,25 +863,29 @@ static int packfile_load__cb(void *_data, char *path) return GIT_SUCCESS; } -static int packfile_load_all(struct pack_backend *backend, const char *odb_path, int local) +static int packfile_refresh_all(struct pack_backend *backend) { int error; - char path[GIT_PATH_MAX]; - struct pack__dirent data; - - data.backend = backend; - data.is_pack_local = local; + struct stat st; - git__joinpath(path, odb_path, "pack"); - if (gitfo_isdir(path) < GIT_SUCCESS) + if (backend->pack_folder == NULL) return GIT_SUCCESS; - error = gitfo_dirent(path, GIT_PATH_MAX, packfile_load__cb, (void *)&data); - if (error < GIT_SUCCESS) - return error; + if (gitfo_stat(backend->pack_folder, &st) < 0 || !S_ISDIR(st.st_mode)) + return GIT_ENOTFOUND; - git_vector_sort(&backend->packs); - backend->last_found = git_vector_get(&backend->packs, 0); + if (st.st_mtime != backend->pack_folder_mtime) { + char path[GIT_PATH_MAX]; + strcpy(path, backend->pack_folder); + + /* reload all packs */ + error = gitfo_dirent(path, GIT_PATH_MAX, packfile_load__cb, (void *)backend); + if (error < GIT_SUCCESS) + return error; + + git_vector_sort(&backend->packs); + backend->pack_folder_mtime = st.st_mtime; + } return GIT_SUCCESS; } @@ -1026,8 +1030,12 @@ static int pack_entry_find1( static int pack_entry_find(struct pack_entry *e, struct pack_backend *backend, const git_oid *oid) { + int error; size_t i; + if ((error = packfile_refresh_all(backend)) < GIT_SUCCESS) + return error; + if (backend->last_found && pack_entry_find1(e, backend->last_found, oid) == GIT_SUCCESS) return GIT_SUCCESS; @@ -1377,13 +1385,14 @@ void pack_backend__free(git_odb_backend *_backend) } git_vector_free(&backend->packs); + free(backend->pack_folder); free(backend); } int git_odb_backend_pack(git_odb_backend **backend_out, const char *objects_dir) { - int error; struct pack_backend *backend; + char path[GIT_PATH_MAX]; backend = git__calloc(1, sizeof(struct pack_backend)); if (backend == NULL) @@ -1397,10 +1406,15 @@ int git_odb_backend_pack(git_odb_backend **backend_out, const char *objects_dir) backend->window_size = DEFAULT_WINDOW_SIZE; backend->mapped_limit = DEFAULT_MAPPED_LIMIT; - error = packfile_load_all(backend, objects_dir, 1); - if (error < GIT_SUCCESS) { - pack_backend__free((git_odb_backend *)backend); - return error; + git__joinpath(path, objects_dir, "pack"); + if (gitfo_isdir(path) == GIT_SUCCESS) { + backend->pack_folder = git__strdup(path); + backend->pack_folder_mtime = 0; + + if (backend->pack_folder == NULL) { + free(backend); + return GIT_ENOMEM; + } } backend->parent.read = &pack_backend__read; diff --git a/src/refs.c b/src/refs.c index 00b9ff6b2..ea968196f 100644 --- a/src/refs.c +++ b/src/refs.c @@ -684,7 +684,7 @@ static int packed_loadloose(git_repository *repository) /* Remove any loose references from the cache */ { - const void *_unused; + const void *GIT_UNUSED(_unused); git_reference *reference; GIT_HASHTABLE_FOREACH(repository->references.loose_cache, _unused, reference, @@ -787,6 +787,8 @@ static int packed_find_peel(reference_oid *ref) */ } + git_object_close(object); + return GIT_SUCCESS; } @@ -868,7 +870,7 @@ static int packed_write(git_repository *repo) /* Load all the packfile into a vector */ { git_reference *reference; - const void *_unused; + const void *GIT_UNUSED(_unused); GIT_HASHTABLE_FOREACH(repo->references.packfile, _unused, reference, git_vector_insert(&packing_list, reference); /* cannot fail: vector already has the right size */ @@ -1480,8 +1482,9 @@ int git_reference_resolve(git_reference **resolved_ref, git_reference *ref) for (i = 0; i < MAX_NESTING_LEVEL; ++i) { reference_symbolic *ref_sym; + *resolved_ref = ref; + if (ref->type & GIT_REF_OID) { - *resolved_ref = ref; return GIT_SUCCESS; } @@ -1518,7 +1521,7 @@ int git_reference_listcb(git_repository *repo, unsigned int list_flags, int (*ca /* list all the packed references first */ if (list_flags & GIT_REF_PACKED) { const char *ref_name; - void *_unused; + void *GIT_UNUSED(_unused); if ((error = packed_load(repo)) < GIT_SUCCESS) return error; @@ -1597,7 +1600,7 @@ int git_repository__refcache_init(git_refcache *refs) void git_repository__refcache_free(git_refcache *refs) { git_reference *reference; - const void *_unused; + const void *GIT_UNUSED(_unused); assert(refs); @@ -1692,8 +1695,9 @@ static int normalize_name(char *buffer_out, const char *name, int is_oid_ref) } /* Object id refname have to contain at least one slash, except - * for HEAD in a detached state */ - if (is_oid_ref && !contains_a_slash && strcmp(name, GIT_HEAD_FILE)) + * for HEAD in a detached state or MERGE_HEAD if we're in the + * middle of a merge */ + if (is_oid_ref && !contains_a_slash && (strcmp(name, GIT_HEAD_FILE) && strcmp(name, GIT_MERGE_HEAD_FILE))) return GIT_EINVALIDREFNAME; /* A refname can not end with ".lock" */ diff --git a/src/refs.h b/src/refs.h index bebb1b97d..b8f3e2f6d 100644 --- a/src/refs.h +++ b/src/refs.h @@ -17,6 +17,7 @@ #define MAX_GITDIR_TREE_STRUCTURE_PATH_LENGTH 100 #define GIT_HEAD_FILE "HEAD" +#define GIT_MERGE_HEAD_FILE "MERGE_HEAD" #define GIT_REFS_HEADS_MASTER_FILE GIT_REFS_HEADS_DIR "master" struct git_reference { diff --git a/src/repository.c b/src/repository.c index c428b00af..8cc2644ca 100644 --- a/src/repository.c +++ b/src/repository.c @@ -58,7 +58,6 @@ static int assign_repository_dirs( const char *git_work_tree) { char path_aux[GIT_PATH_MAX]; - size_t git_dir_path_len; int error = GIT_SUCCESS; assert(repo); @@ -70,8 +69,6 @@ static int assign_repository_dirs( if (error < GIT_SUCCESS) return error; - git_dir_path_len = strlen(path_aux); - /* store GIT_DIR */ repo->path_repository = git__strdup(path_aux); if (repo->path_repository == NULL) diff --git a/src/revwalk.c b/src/revwalk.c index b62b09961..78798480f 100644 --- a/src/revwalk.c +++ b/src/revwalk.c @@ -483,7 +483,7 @@ int git_revwalk_new(git_revwalk **revwalk_out, git_repository *repo) void git_revwalk_free(git_revwalk *walk) { unsigned int i; - const void *_unused; + const void *GIT_UNUSED(_unused); commit_object *commit; if (walk == NULL) @@ -558,7 +558,7 @@ int git_revwalk_next(git_oid *oid, git_revwalk *walk) void git_revwalk_reset(git_revwalk *walk) { - const void *_unused; + const void *GIT_UNUSED(_unused); commit_object *commit; assert(walk); @@ -377,3 +377,29 @@ int git_tag__parse(git_tag *tag, git_odb_object *obj) return parse_tag_buffer(tag, obj->raw.data, (char *)obj->raw.data + obj->raw.len); } +static int tag_list_cb(const char *tag_name, void *payload) +{ + if (git__prefixcmp(tag_name, GIT_REFS_TAGS_DIR) == 0) + return git_vector_insert((git_vector *)payload, git__strdup(tag_name)); + + return GIT_SUCCESS; +} + +int git_tag_list(git_strarray *tag_names, git_repository *repo) +{ + int error; + git_vector taglist; + + if (git_vector_init(&taglist, 8, NULL) < GIT_SUCCESS) + return GIT_ENOMEM; + + error = git_reference_listcb(repo, GIT_REF_OID|GIT_REF_PACKED, &tag_list_cb, (void *)&taglist); + if (error < GIT_SUCCESS) { + git_vector_free(&taglist); + return error; + } + + tag_names->strings = (char **)taglist.contents; + tag_names->count = taglist.length; + return GIT_SUCCESS; +} diff --git a/src/tree.c b/src/tree.c index 64f81d780..b7daf39c4 100644 --- a/src/tree.c +++ b/src/tree.c @@ -424,7 +424,8 @@ int git_treebuilder_write(git_oid *oid, git_repository *repo, git_treebuilder *b if (entry->removed) continue; - size += (entry->attr > 0x7FF) ? 7 : 6; + snprintf(filemode, sizeof(filemode), "%o ", entry->attr); + size += strlen(filemode); size += entry->filename_len + 1; size += GIT_OID_RAWSZ; } |