diff options
-rw-r--r-- | docs/manual/repo.md | 16 | ||||
-rw-r--r-- | src/libostree/ostree-repo-checkout.c | 4 | ||||
-rw-r--r-- | src/libostree/ostree-repo-commit.c | 8 | ||||
-rw-r--r-- | src/libostree/ostree-repo-libarchive.c | 6 | ||||
-rw-r--r-- | src/libostree/ostree-repo-private.h | 2 | ||||
-rw-r--r-- | src/libostree/ostree-repo.c | 8 | ||||
-rwxr-xr-x | tests/basic-test.sh | 4 |
7 files changed, 35 insertions, 13 deletions
diff --git a/docs/manual/repo.md b/docs/manual/repo.md index d6f67090..bce7e0c9 100644 --- a/docs/manual/repo.md +++ b/docs/manual/repo.md @@ -47,6 +47,22 @@ payload sections. The header contains uid, gid, mode, and symbolic link target (for symlinks), as well as extended attributes. After the header, for regular files, the content follows. +The OSTree data format intentionally does not contain timestamps. The reasoning +is that data files may be downloaded at different times, and by different build +systems, and so will have different timestamps but identical physical content. +These files may be large, so most users would like them to be shared, both in +the repository and between the repository and deployments. + +This could cause problems with programs that check if files are out-of-date by +comparing timestamps. For Git, the logical choice is to not mess with +timestamps, because unnecessary rebuilding is better than a broken tree. +However, OSTree has to hardlink files to check them out, and commits are assumed +to be internally consistent with no build steps needed. For this reason, OSTree +acts as though all timestamps are set to time_t 1, so that comparisons will be +considered up-to-date. 1 is a better choice than 0 because some programs use 0 +as a special value; for example, GNU Tar warns of an "implausibly old time +stamp" with 0. + # Repository types and locations Also unlike git, an OSTree repository can be in one of three separate diff --git a/src/libostree/ostree-repo-checkout.c b/src/libostree/ostree-repo-checkout.c index 95d3747b..227227b6 100644 --- a/src/libostree/ostree-repo-checkout.c +++ b/src/libostree/ostree-repo-checkout.c @@ -752,12 +752,12 @@ checkout_tree_at (OstreeRepo *self, } } - /* Set directory mtime to 0, so that it is constant for all checkouts. + /* Set directory mtime to OSTREE_TIMESTAMP, so that it is constant for all checkouts. * Must be done after setting permissions and creating all children. */ if (!did_exist) { - const struct timespec times[2] = { { 0, UTIME_OMIT }, { 0, } }; + const struct timespec times[2] = { { OSTREE_TIMESTAMP, UTIME_OMIT }, { OSTREE_TIMESTAMP, 0} }; do res = futimens (destination_dfd, times); while (G_UNLIKELY (res == -1 && errno == EINTR)); diff --git a/src/libostree/ostree-repo-commit.c b/src/libostree/ostree-repo-commit.c index 6cb46ca9..6166c652 100644 --- a/src/libostree/ostree-repo-commit.c +++ b/src/libostree/ostree-repo-commit.c @@ -210,7 +210,6 @@ commit_loose_object_trusted (OstreeRepo *self, else { int res; - struct timespec times[2]; if (objtype == OSTREE_OBJECT_TYPE_FILE && self->mode == OSTREE_REPO_MODE_BARE) { @@ -266,12 +265,9 @@ commit_loose_object_trusted (OstreeRepo *self, { /* To satisfy tools such as guile which compare mtimes * to determine whether or not source files need to be compiled, - * set the modification time to 0. + * set the modification time to OSTREE_TIMESTAMP. */ - times[0].tv_sec = 0; /* atime */ - times[0].tv_nsec = UTIME_OMIT; - times[1].tv_sec = 0; /* mtime */ - times[1].tv_nsec = 0; + const struct timespec times[2] = { { OSTREE_TIMESTAMP, UTIME_OMIT }, { OSTREE_TIMESTAMP, 0} }; do res = futimens (fd, times); while (G_UNLIKELY (res == -1 && errno == EINTR)); diff --git a/src/libostree/ostree-repo-libarchive.c b/src/libostree/ostree-repo-libarchive.c index 0d62124d..45427ef7 100644 --- a/src/libostree/ostree-repo-libarchive.c +++ b/src/libostree/ostree-repo-libarchive.c @@ -982,9 +982,9 @@ file_to_archive_entry_common (GFile *root, } archive_entry_update_pathname_utf8 (entry, pathstr); - archive_entry_set_ctime (entry, ts, 0); - archive_entry_set_mtime (entry, ts, 0); - archive_entry_set_atime (entry, ts, 0); + archive_entry_set_ctime (entry, ts, OSTREE_TIMESTAMP); + archive_entry_set_mtime (entry, ts, OSTREE_TIMESTAMP); + archive_entry_set_atime (entry, ts, OSTREE_TIMESTAMP); archive_entry_set_uid (entry, g_file_info_get_attribute_uint32 (file_info, "unix::uid")); archive_entry_set_gid (entry, g_file_info_get_attribute_uint32 (file_info, "unix::gid")); archive_entry_set_mode (entry, g_file_info_get_attribute_uint32 (file_info, "unix::mode")); diff --git a/src/libostree/ostree-repo-private.h b/src/libostree/ostree-repo-private.h index 62a3c8f6..35b05c76 100644 --- a/src/libostree/ostree-repo-private.h +++ b/src/libostree/ostree-repo-private.h @@ -36,6 +36,8 @@ G_BEGIN_DECLS #define _OSTREE_SUMMARY_CACHE_DIR "summaries" #define _OSTREE_CACHE_DIR "cache" +#define OSTREE_TIMESTAMP (1) + typedef enum { OSTREE_REPO_TEST_ERROR_PRE_COMMIT = (1 << 0) } OstreeRepoTestErrorFlags; diff --git a/src/libostree/ostree-repo.c b/src/libostree/ostree-repo.c index 6af5d8e6..fd02833a 100644 --- a/src/libostree/ostree-repo.c +++ b/src/libostree/ostree-repo.c @@ -942,6 +942,14 @@ ostree_repo_is_writable (OstreeRepo *self, return self->writable; } +/** + * _ostree_repo_update_mtime: + * @self: Repo + * @error: a #GError + * + * Bump the mtime of the repository so that programs + * can detect that the refs have updated. + */ gboolean _ostree_repo_update_mtime (OstreeRepo *self, GError **error) diff --git a/tests/basic-test.sh b/tests/basic-test.sh index 93f67f17..0fe372dc 100755 --- a/tests/basic-test.sh +++ b/tests/basic-test.sh @@ -386,9 +386,9 @@ else $OSTREE checkout test2 test2-checkout fi stat '--format=%Y' test2-checkout/baz/cow > cow-mtime -assert_file_has_content cow-mtime 0 +assert_file_has_content cow-mtime 1 stat '--format=%Y' test2-checkout/baz/deeper > deeper-mtime -assert_file_has_content deeper-mtime 0 +assert_file_has_content deeper-mtime 1 echo "ok content mtime" cd ${test_tmpdir} |