]> git.proxmox.com Git - libgit2.git/blobdiff - src/submodule.c
Add range checking around cache opts
[libgit2.git] / src / submodule.c
index d69559dc24e782dd8b2877d3eccead282d4989af..0a22e3b13e55b93ce74c5e51fd0745a985a49f37 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2012 the libgit2 contributors
+ * Copyright (C) the libgit2 contributors. All rights reserved.
  *
  * This file is part of libgit2, distributed under the GNU GPL v2 with
  * a Linking Exception. For full terms see the included COPYING file.
@@ -7,11 +7,13 @@
 
 #include "common.h"
 #include "git2/config.h"
+#include "git2/sys/config.h"
 #include "git2/types.h"
 #include "git2/repository.h"
 #include "git2/index.h"
 #include "git2/submodule.h"
 #include "buffer.h"
+#include "buf_text.h"
 #include "vector.h"
 #include "posix.h"
 #include "config_file.h"
@@ -65,8 +67,8 @@ __KHASH_IMPL(
        str, static kh_inline, const char *, void *, 1,
        str_hash_no_trailing_slash, str_equal_no_trailing_slash);
 
-static int load_submodule_config(git_repository *repo, bool force);
-static git_config_file *open_gitmodules(git_repository *, bool, const git_oid *);
+static int load_submodule_config(git_repository *repo);
+static git_config_backend *open_gitmodules(git_repository *, bool, const git_oid *);
 static int lookup_head_remote(git_buf *url, git_repository *repo);
 static int submodule_get(git_submodule **, git_repository *, const char *, const char *);
 static void submodule_release(git_submodule *sm, int decr);
@@ -105,7 +107,7 @@ int git_submodule_lookup(
 
        assert(repo && name);
 
-       if ((error = load_submodule_config(repo, false)) < 0)
+       if ((error = load_submodule_config(repo)) < 0)
                return error;
 
        pos = git_strmap_lookup_index(repo->submodules, name);
@@ -147,7 +149,7 @@ int git_submodule_foreach(
 
        assert(repo && callback);
 
-       if ((error = load_submodule_config(repo, false)) < 0)
+       if ((error = load_submodule_config(repo)) < 0)
                return error;
 
        git_strmap_foreach_value(repo->submodules, sm, {
@@ -156,7 +158,7 @@ int git_submodule_foreach(
                 * and path are not the same.
                 */
                if (sm->refcount > 1) {
-                       if (git_vector_bsearch(&seen, sm) != GIT_ENOTFOUND)
+                       if (git_vector_bsearch(NULL, &seen, sm) != GIT_ENOTFOUND)
                                continue;
                        if ((error = git_vector_insert(&seen, sm)) < 0)
                                break;
@@ -201,10 +203,10 @@ int git_submodule_add_setup(
        int use_gitlink)
 {
        int error = 0;
-       git_config_file *mods = NULL;
+       git_config_backend *mods = NULL;
        git_submodule *sm;
        git_buf name = GIT_BUF_INIT, real_url = GIT_BUF_INIT;
-       git_repository_init_options initopt;
+       git_repository_init_options initopt = GIT_REPOSITORY_INIT_OPTIONS_INIT;
        git_repository *subrepo = NULL;
 
        assert(repo && url && path);
@@ -274,7 +276,6 @@ int git_submodule_add_setup(
         * Old style: sub-repo goes directly into repo/<name>/.git/
         */
 
-       memset(&initopt, 0, sizeof(initopt));
        initopt.flags = GIT_REPOSITORY_INIT_MKPATH |
                GIT_REPOSITORY_INIT_NO_REINIT;
        initopt.origin_url = real_url.ptr;
@@ -332,7 +333,7 @@ int git_submodule_add_finalize(git_submodule *sm)
        assert(sm);
 
        if ((error = git_repository_index__weakptr(&index, sm->owner)) < 0 ||
-               (error = git_index_add_from_workdir(index, GIT_MODULES_FILE)) < 0)
+               (error = git_index_add_bypath(index, GIT_MODULES_FILE)) < 0)
                return error;
 
        return git_submodule_add_to_index(sm, true);
@@ -341,7 +342,7 @@ int git_submodule_add_finalize(git_submodule *sm)
 int git_submodule_add_to_index(git_submodule *sm, int write_index)
 {
        int error;
-       git_repository *repo, *sm_repo;
+       git_repository *repo, *sm_repo = NULL;
        git_index *index;
        git_buf path = GIT_BUF_INIT;
        git_commit *head;
@@ -371,7 +372,7 @@ int git_submodule_add_to_index(git_submodule *sm, int write_index)
 
        memset(&entry, 0, sizeof(entry));
        entry.path = sm->path;
-       git_index__init_entry_from_stat(&st, &entry);
+       git_index_entry__init_from_stat(&entry, &st);
 
        /* calling git_submodule_open will have set sm->wd_oid if possible */
        if ((sm->flags & GIT_SUBMODULE_STATUS__WD_OID_VALID) == 0) {
@@ -412,7 +413,7 @@ cleanup:
 int git_submodule_save(git_submodule *submodule)
 {
        int error = 0;
-       git_config_file *mods;
+       git_config_backend *mods;
        git_buf key = GIT_BUF_INIT;
 
        assert(submodule);
@@ -513,7 +514,7 @@ int git_submodule_set_url(git_submodule *submodule, const char *url)
        return 0;
 }
 
-const git_oid *git_submodule_index_oid(git_submodule *submodule)
+const git_oid *git_submodule_index_id(git_submodule *submodule)
 {
        assert(submodule);
 
@@ -523,7 +524,7 @@ const git_oid *git_submodule_index_oid(git_submodule *submodule)
                return NULL;
 }
 
-const git_oid *git_submodule_head_oid(git_submodule *submodule)
+const git_oid *git_submodule_head_id(git_submodule *submodule)
 {
        assert(submodule);
 
@@ -533,7 +534,7 @@ const git_oid *git_submodule_head_oid(git_submodule *submodule)
                return NULL;
 }
 
-const git_oid *git_submodule_wd_oid(git_submodule *submodule)
+const git_oid *git_submodule_wd_id(git_submodule *submodule)
 {
        assert(submodule);
 
@@ -694,8 +695,8 @@ int git_submodule_open(
        git_buf_free(&path);
 
        /* if we have opened the submodule successfully, let's grab the HEAD OID */
-       if (!error && !(submodule->flags & GIT_SUBMODULE_STATUS__WD_OID_VALID)) {
-               if (!git_reference_name_to_oid(
+       if (!error) {
+               if (!git_reference_name_to_id(
                                &submodule->wd_oid, *subrepo, GIT_HEAD_FILE))
                        submodule->flags |= GIT_SUBMODULE_STATUS__WD_OID_VALID;
                else
@@ -708,16 +709,18 @@ int git_submodule_open(
 int git_submodule_reload_all(git_repository *repo)
 {
        assert(repo);
-       return load_submodule_config(repo, true);
+       git_submodule_config_free(repo);
+       return load_submodule_config(repo);
 }
 
 int git_submodule_reload(git_submodule *submodule)
 {
        git_repository *repo;
        git_index *index;
-       int pos, error;
+       int error;
+       size_t pos;
        git_tree *head;
-       git_config_file *mods;
+       git_config_backend *mods;
 
        assert(submodule);
 
@@ -731,9 +734,8 @@ int git_submodule_reload(git_submodule *submodule)
                ~(GIT_SUBMODULE_STATUS_IN_INDEX |
                  GIT_SUBMODULE_STATUS__INDEX_OID_VALID);
 
-       pos = git_index_find(index, submodule->path);
-       if (pos >= 0) {
-               git_index_entry *entry = git_index_get_byindex(index, pos);
+       if (!git_index_find(&pos, index, submodule->path)) {
+               const git_index_entry *entry = git_index_get_byindex(index, pos);
 
                if (S_ISGITLINK(entry->mode)) {
                        if ((error = submodule_load_from_index(repo, entry)) < 0)
@@ -782,7 +784,7 @@ int git_submodule_reload(git_submodule *submodule)
                git_buf path = GIT_BUF_INIT;
 
                git_buf_sets(&path, "submodule\\.");
-               git_buf_puts_escape_regex(&path, submodule->name);
+               git_buf_text_puts_escape_regex(&path, submodule->name);
                git_buf_puts(&path, ".*");
 
                if (git_buf_oom(&path))
@@ -829,6 +831,20 @@ int git_submodule_status(
        return error;
 }
 
+int git_submodule_location(
+       unsigned int *location_status,
+       git_submodule *submodule)
+{
+       assert(location_status && submodule);
+
+       *location_status = submodule->flags &
+               (GIT_SUBMODULE_STATUS_IN_HEAD | GIT_SUBMODULE_STATUS_IN_INDEX |
+                GIT_SUBMODULE_STATUS_IN_CONFIG | GIT_SUBMODULE_STATUS_IN_WD);
+
+       return 0;
+}
+
+
 /*
  * INTERNAL FUNCTIONS
  */
@@ -1115,13 +1131,15 @@ static int load_submodule_config_from_index(
        git_repository *repo, git_oid *gitmodules_oid)
 {
        int error;
+       git_index *index;
        git_iterator *i;
        const git_index_entry *entry;
 
-       if ((error = git_iterator_for_index(&i, repo)) < 0)
+       if ((error = git_repository_index__weakptr(&index, repo)) < 0 ||
+               (error = git_iterator_for_index(&i, index, 0, NULL, NULL)) < 0)
                return error;
 
-       error = git_iterator_current(i, &entry);
+       error = git_iterator_current(&entry, i);
 
        while (!error && entry != NULL) {
 
@@ -1137,7 +1155,7 @@ static int load_submodule_config_from_index(
                                git_oid_cpy(gitmodules_oid, &entry->oid);
                }
 
-               error = git_iterator_advance(i, &entry);
+               error = git_iterator_advance(&entry, i);
        }
 
        git_iterator_free(i);
@@ -1156,12 +1174,12 @@ static int load_submodule_config_from_head(
        if ((error = git_repository_head_tree(&head, repo)) < 0)
                return error;
 
-       if ((error = git_iterator_for_tree(&i, repo, head)) < 0) {
+       if ((error = git_iterator_for_tree(&i, head, 0, NULL, NULL)) < 0) {
                git_tree_free(head);
                return error;
        }
 
-       error = git_iterator_current(i, &entry);
+       error = git_iterator_current(&entry, i);
 
        while (!error && entry != NULL) {
 
@@ -1178,7 +1196,7 @@ static int load_submodule_config_from_head(
                                git_oid_cpy(gitmodules_oid, &entry->oid);
                }
 
-               error = git_iterator_advance(i, &entry);
+               error = git_iterator_advance(&entry, i);
        }
 
        git_iterator_free(i);
@@ -1187,14 +1205,14 @@ static int load_submodule_config_from_head(
        return error;
 }
 
-static git_config_file *open_gitmodules(
+static git_config_backend *open_gitmodules(
        git_repository *repo,
        bool okay_to_create,
        const git_oid *gitmodules_oid)
 {
        const char *workdir = git_repository_workdir(repo);
        git_buf path = GIT_BUF_INIT;
-       git_config_file *mods = NULL;
+       git_config_backend *mods = NULL;
 
        if (workdir != NULL) {
                if (git_buf_joinpath(&path, workdir, GIT_MODULES_FILE) != 0)
@@ -1225,14 +1243,14 @@ static git_config_file *open_gitmodules(
        return mods;
 }
 
-static int load_submodule_config(git_repository *repo, bool force)
+static int load_submodule_config(git_repository *repo)
 {
        int error;
        git_oid gitmodules_oid;
        git_buf path = GIT_BUF_INIT;
-       git_config_file *mods = NULL;
+       git_config_backend *mods = NULL;
 
-       if (repo->submodules && !force)
+       if (repo->submodules)
                return 0;
 
        memset(&gitmodules_oid, 0, sizeof(gitmodules_oid));
@@ -1310,13 +1328,13 @@ static int lookup_head_remote(git_buf *url, git_repository *repo)
                goto cleanup;
        }
 
-       if ((error = git_branch_tracking(&remote, head)) < 0)
+       if ((error = git_branch_upstream(&remote, head)) < 0)
                goto cleanup;
 
        /* remote should refer to something like refs/remotes/ORIGIN/BRANCH */
 
        if (git_reference_type(remote) != GIT_REF_SYMBOLIC ||
-               git__prefixcmp(git_reference_target(remote), GIT_REFS_REMOTES_DIR) != 0)
+               git__prefixcmp(git_reference_symbolic_target(remote), GIT_REFS_REMOTES_DIR) != 0)
        {
                giterr_set(GITERR_SUBMODULE,
                        "Cannot resolve relative URL when HEAD is not symbolic");
@@ -1324,7 +1342,7 @@ static int lookup_head_remote(git_buf *url, git_repository *repo)
                goto cleanup;
        }
 
-       scan = tgt = git_reference_target(remote) + strlen(GIT_REFS_REMOTES_DIR);
+       scan = tgt = git_reference_symbolic_target(remote) + strlen(GIT_REFS_REMOTES_DIR);
        while (*scan && (*scan != '/' || (scan > tgt && scan[-1] != '\\')))
                scan++; /* find non-escaped slash to end ORIGIN name */
 
@@ -1378,7 +1396,7 @@ static int submodule_update_config(
                goto cleanup;
 
        if (!value)
-               error = git_config_delete(config, key.ptr);
+               error = git_config_delete_entry(config, key.ptr);
        else
                error = git_config_set_string(config, key.ptr, value);
 
@@ -1389,8 +1407,8 @@ cleanup:
 
 static int submodule_index_status(unsigned int *status, git_submodule *sm)
 {
-       const git_oid *head_oid  = git_submodule_head_oid(sm);
-       const git_oid *index_oid = git_submodule_index_oid(sm);
+       const git_oid *head_oid  = git_submodule_head_id(sm);
+       const git_oid *index_oid = git_submodule_index_id(sm);
 
        if (!head_oid) {
                if (index_oid)
@@ -1410,7 +1428,7 @@ static int submodule_wd_status(unsigned int *status, git_submodule *sm)
        const git_oid *wd_oid, *index_oid;
        git_repository *sm_repo = NULL;
 
-       /* open repo now if we need it (so wd_oid() call won't reopen) */
+       /* open repo now if we need it (so wd_id() call won't reopen) */
        if ((sm->ignore == GIT_SUBMODULE_IGNORE_NONE ||
                 sm->ignore == GIT_SUBMODULE_IGNORE_UNTRACKED) &&
                (sm->flags & GIT_SUBMODULE_STATUS_IN_WD) != 0)
@@ -1419,8 +1437,8 @@ static int submodule_wd_status(unsigned int *status, git_submodule *sm)
                        return error;
        }
 
-       index_oid = git_submodule_index_oid(sm);
-       wd_oid    = git_submodule_wd_oid(sm);
+       index_oid = git_submodule_index_id(sm);
+       wd_oid    = git_submodule_wd_id(sm);
 
        if (!index_oid) {
                if (wd_oid)
@@ -1438,7 +1456,7 @@ static int submodule_wd_status(unsigned int *status, git_submodule *sm)
 
        if (sm_repo != NULL) {
                git_tree *sm_head;
-               git_diff_options opt;
+               git_diff_options opt = GIT_DIFF_OPTIONS_INIT;
                git_diff_list *diff;
 
                /* the diffs below could be optimized with an early termination
@@ -1451,11 +1469,10 @@ static int submodule_wd_status(unsigned int *status, git_submodule *sm)
                if ((error = git_repository_head_tree(&sm_head, sm_repo)) < 0)
                        return error;
 
-               memset(&opt, 0, sizeof(opt));
                if (sm->ignore == GIT_SUBMODULE_IGNORE_NONE)
                        opt.flags |= GIT_DIFF_INCLUDE_UNTRACKED;
 
-               error = git_diff_index_to_tree(sm_repo, &opt, sm_head, &diff);
+               error = git_diff_tree_to_index(&diff, sm_repo, sm_head, NULL, &opt);
 
                if (!error) {
                        if (git_diff_num_deltas(diff) > 0)
@@ -1472,7 +1489,7 @@ static int submodule_wd_status(unsigned int *status, git_submodule *sm)
 
                /* perform index-to-workdir diff on submodule */
 
-               error = git_diff_workdir_to_index(sm_repo, &opt, &diff);
+               error = git_diff_index_to_workdir(&diff, sm_repo, NULL, &opt);
 
                if (!error) {
                        size_t untracked =
@@ -1481,7 +1498,7 @@ static int submodule_wd_status(unsigned int *status, git_submodule *sm)
                        if (untracked > 0)
                                *status |= GIT_SUBMODULE_STATUS_WD_UNTRACKED;
 
-                       if ((git_diff_num_deltas(diff) - untracked) > 0)
+                       if (git_diff_num_deltas(diff) != untracked)
                                *status |= GIT_SUBMODULE_STATUS_WD_WD_MODIFIED;
 
                        git_diff_list_free(diff);