summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/submodule.c42
-rw-r--r--src/submodule.h48
-rw-r--r--tests-clar/diff/submodules.c13
3 files changed, 77 insertions, 26 deletions
diff --git a/src/submodule.c b/src/submodule.c
index dcd58d016..e6ed7e33e 100644
--- a/src/submodule.c
+++ b/src/submodule.c
@@ -9,9 +9,7 @@
#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"
@@ -544,6 +542,15 @@ const git_oid *git_submodule_wd_id(git_submodule *submodule)
{
assert(submodule);
+ /* if we know the submodule index timestamp and it has moved, then
+ * let's reload the working directory information for the submodule
+ */
+ if (submodule->wd_head_path != NULL &&
+ git_futils_filestamp_check(
+ &submodule->wd_stamp, submodule->wd_head_path))
+ submodule->flags &= ~GIT_SUBMODULE_STATUS__WD_OID_VALID;
+
+ /* load unless we think we have a valid oid */
if (!(submodule->flags & GIT_SUBMODULE_STATUS__WD_OID_VALID)) {
git_repository *subrepo;
@@ -702,11 +709,36 @@ int git_submodule_open(
/* if we have opened the submodule successfully, let's grab the HEAD OID */
if (!error) {
+ git_buf buf = GIT_BUF_INIT;
+
+ /* For now, let's just the index timestamp...
+ *
+ * git_buf_joinpath(&buf, git_repository_path(*subrepo), GIT_HEAD_FILE);
+ * if (!git_path_exists(buf.ptr)) {
+ */
+ git_index *index;
+ if (!git_repository_index__weakptr(&index, *subrepo))
+ git_buf_sets(&buf, git_index_path(index));
+ else
+ git_buf_free(&buf);
+ /* } */
+
+ if (git_buf_len(&buf) > 0) {
+ git__free(submodule->wd_head_path);
+ submodule->wd_head_path = git_buf_detach(&buf);
+ }
+
if (!git_reference_name_to_id(
- &submodule->wd_oid, *subrepo, GIT_HEAD_FILE))
+ &submodule->wd_oid, *subrepo, GIT_HEAD_FILE)) {
+
submodule->flags |= GIT_SUBMODULE_STATUS__WD_OID_VALID;
- else
- giterr_clear();
+
+ if (submodule->wd_head_path)
+ git_futils_filestamp_check(
+ &submodule->wd_stamp, submodule->wd_head_path);
+ }
+
+ giterr_clear();
}
return error;
diff --git a/src/submodule.h b/src/submodule.h
index ba8e2518e..88d4f97c7 100644
--- a/src/submodule.h
+++ b/src/submodule.h
@@ -7,6 +7,10 @@
#ifndef INCLUDE_submodule_h__
#define INCLUDE_submodule_h__
+#include "git2/submodule.h"
+#include "git2/repository.h"
+#include "fileops.h"
+
/* Notes:
*
* Submodule information can be in four places: the index, the config files
@@ -44,43 +48,53 @@
* an entry for every submodule found in the HEAD and index, and for every
* submodule described in .gitmodules. The fields are as follows:
*
- * - `owner` is the git_repository containing this submodule
* - `name` is the name of the submodule from .gitmodules.
* - `path` is the path to the submodule from the repo root. It is almost
* always the same as `name`.
* - `url` is the url for the submodule.
- * - `tree_oid` is the SHA1 for the submodule path in the repo HEAD.
- * - `index_oid` is the SHA1 for the submodule recorded in the index.
- * - `workdir_oid` is the SHA1 for the HEAD of the checked out submodule.
* - `update` is a git_submodule_update_t value - see gitmodules(5) update.
+ * - `update_default` is the update value from the config
* - `ignore` is a git_submodule_ignore_t value - see gitmodules(5) ignore.
+ * - `ignore_default` is the ignore value from the config
* - `fetch_recurse` is 0 or 1 - see gitmodules(5) fetchRecurseSubmodules.
- * - `refcount` tracks how many hashmap entries there are for this submodule.
- * It only comes into play if the name and path of the submodule differ.
- * - `flags` is for internal use, tracking where this submodule has been
- * found (head, index, config, workdir) and other misc info about it.
+ *
+ * - `owner` is the git_repository containing this submodule
+ * - `flags` after for internal use, tracking where this submodule has been
+ * found (head, index, config, workdir) and known status info, etc.
+ * - `head_oid` is the SHA1 for the submodule path in the repo HEAD.
+ * - `index_oid` is the SHA1 for the submodule recorded in the index.
+ * - `wd_oid` is the SHA1 for the HEAD of the checked out submodule.
+ * - `wd_index_path` is the path to the index of the checked out submodule
+ * - `wd_last_index` is a timestamp of that submodule index so we can
+ * quickly check if the `wd_oid` should be rechecked
+ * - `refcount` tracks how many hash table entries in the
+ * git_submodule_cache there are for this submodule. It only comes into
+ * play if the name and path of the submodule differ.
*
* If the submodule has been added to .gitmodules but not yet git added,
- * then the `index_oid` will be valid and zero. If the submodule has been
- * deleted, but the delete has not been committed yet, then the `index_oid`
- * will be set, but the `url` will be NULL.
+ * then the `index_oid` will be zero but still marked valid. If the
+ * submodule has been deleted, but the delete has not been committed yet,
+ * then the `index_oid` will be set, but the `url` will be NULL.
*/
struct git_submodule {
- git_repository *owner;
+ /* information from config */
char *name;
char *path; /* important: may point to same string data as "name" */
char *url;
- uint32_t flags;
- git_oid head_oid;
- git_oid index_oid;
- git_oid wd_oid;
- /* information from config */
git_submodule_update_t update;
git_submodule_update_t update_default;
git_submodule_ignore_t ignore;
git_submodule_ignore_t ignore_default;
int fetch_recurse;
+
/* internal information */
+ git_repository *owner;
+ uint32_t flags;
+ git_oid head_oid;
+ git_oid index_oid;
+ git_oid wd_oid;
+ char *wd_head_path;
+ git_futils_filestamp wd_stamp;
int refcount;
};
diff --git a/tests-clar/diff/submodules.c b/tests-clar/diff/submodules.c
index 9b77897b7..c94fd57c6 100644
--- a/tests-clar/diff/submodules.c
+++ b/tests-clar/diff/submodules.c
@@ -333,29 +333,34 @@ void test_diff_submodules__invalid_cache(void)
check_diff_patches(diff, expected_unchanged);
git_diff_list_free(diff);
+ sleep(2);
+
/* commit changed index of submodule */
{
git_object *parent;
git_oid tree_id, commit_id;
git_tree *tree;
git_signature *sig;
+ git_reference *ref;
- cl_git_pass(git_revparse_single(&parent, smrepo, "HEAD"));
+ cl_git_pass(git_revparse_ext(&parent, &ref, smrepo, "HEAD"));
cl_git_pass(git_index_write_tree(&tree_id, smindex));
cl_git_pass(git_index_write(smindex));
cl_git_pass(git_tree_lookup(&tree, smrepo, &tree_id));
cl_git_pass(git_signature_new(&sig, "Sm Test", "sm@tester.test", 1372350000, 480));
cl_git_pass(git_commit_create_v(
- &commit_id, smrepo, "HEAD", sig, sig, NULL,
- "Move it", tree, 1, parent));
+ &commit_id, smrepo, git_reference_name(ref), sig, sig,
+ NULL, "Move it", tree, 1, parent));
git_object_free(parent);
git_tree_free(tree);
+ git_reference_free(ref);
git_signature_free(sig);
}
- /* THIS RELOAD SHOULD NOT BE REQUIRED */
+ /* THIS RELOAD SHOULD NOT BE REQUIRED
cl_git_pass(git_submodule_reload_all(g_repo));
cl_git_pass(git_submodule_lookup(&sm, g_repo, smpath));
+ */
git_submodule_set_ignore(sm, GIT_SUBMODULE_IGNORE_DIRTY);