GitHub fetcher: Restore the lastModified field

This commit is contained in:
Eelco Dolstra 2022-08-22 12:33:11 +02:00
parent 37d859ba22
commit a115c4f4b2
3 changed files with 46 additions and 10 deletions

View file

@ -195,30 +195,23 @@ struct GitArchiveInputScheme : InputScheme
{"rev", rev->gitRev()}, {"rev", rev->gitRev()},
}); });
if (auto res = getCache()->lookup(store, lockedAttrs)) { if (auto res = getCache()->lookup(store, lockedAttrs))
// FIXME return {std::move(res->second), std::move(input)};
//input.attrs.insert_or_assign("lastModified", getIntAttr(res->first, "lastModified"));
return {std::move(res->second), input};
}
auto url = getDownloadUrl(input); auto url = getDownloadUrl(input);
auto res = downloadFile(store, url.url, input.getName(), true, url.headers); auto res = downloadFile(store, url.url, input.getName(), true, url.headers);
//input.attrs.insert_or_assign("lastModified", uint64_t(lastModified));
getCache()->add( getCache()->add(
store, store,
lockedAttrs, lockedAttrs,
{ {
{"rev", rev->gitRev()}, {"rev", rev->gitRev()},
// FIXME: get lastModified
//{"lastModified", uint64_t(lastModified)}
}, },
res.storePath, res.storePath,
true); true);
return {res.storePath, input}; return {res.storePath, std::move(input)};
} }
std::pair<ref<InputAccessor>, Input> getAccessor(ref<Store> store, const Input & input) const override std::pair<ref<InputAccessor>, Input> getAccessor(ref<Store> store, const Input & input) const override
@ -227,6 +220,10 @@ struct GitArchiveInputScheme : InputScheme
auto accessor = makeZipInputAccessor(CanonPath(store->toRealPath(storePath))); auto accessor = makeZipInputAccessor(CanonPath(store->toRealPath(storePath)));
auto lastModified = accessor->getLastModified();
assert(lastModified);
input2.attrs.insert_or_assign("lastModified", uint64_t(*lastModified));
accessor->setPathDisplay("«" + input2.to_string() + "»"); accessor->setPathDisplay("«" + input2.to_string() + "»");
return {accessor, input2}; return {accessor, input2};

View file

@ -85,6 +85,13 @@ struct InputAccessor : public std::enable_shared_from_this<InputAccessor>
virtual std::string showPath(const CanonPath & path); virtual std::string showPath(const CanonPath & path);
SourcePath root(); SourcePath root();
/* Return the maximum last-modified time of the files in this
tree, if available. */
virtual std::optional<time_t> getLastModified()
{
return std::nullopt;
}
}; };
typedef std::function<RestrictedPathError(const CanonPath & path)> MakeNotAllowedError; typedef std::function<RestrictedPathError(const CanonPath & path)> MakeNotAllowedError;

View file

@ -1,6 +1,7 @@
#include "input-accessor.hh" #include "input-accessor.hh"
#include <zip.h> #include <zip.h>
#include <endian.h>
namespace nix { namespace nix {
@ -28,6 +29,8 @@ struct ZipInputAccessor : InputAccessor
typedef std::map<const char *, struct zip_stat, cmp_str> Members; typedef std::map<const char *, struct zip_stat, cmp_str> Members;
Members members; Members members;
time_t lastModified = 0;
ZipInputAccessor(const CanonPath & _zipPath) ZipInputAccessor(const CanonPath & _zipPath)
: zipPath(_zipPath) : zipPath(_zipPath)
{ {
@ -47,10 +50,34 @@ struct ZipInputAccessor : InputAccessor
for (zip_uint64_t n = 0; n < nrEntries; ++n) { for (zip_uint64_t n = 0; n < nrEntries; ++n) {
if (zip_stat_index(zipFile, n, 0, &sb)) if (zip_stat_index(zipFile, n, 0, &sb))
throw Error("couldn't stat archive member #%d in '%s': %s", n, zipPath, zip_strerror(zipFile)); throw Error("couldn't stat archive member #%d in '%s': %s", n, zipPath, zip_strerror(zipFile));
/* Get the timestamp of this file. */
#if 0
if (sb.valid & ZIP_STAT_MTIME)
lastModified = std::max(lastModified, sb.mtime);
#endif
auto nExtra = zip_file_extra_fields_count(zipFile, n, ZIP_FL_CENTRAL);
for (auto i = 0; i < nExtra; ++i) {
zip_uint16_t id, len;
auto extra = zip_file_extra_field_get(zipFile, i, 0, &id, &len, ZIP_FL_CENTRAL);
if (id == 0x5455 && len >= 5)
lastModified = std::max(lastModified, (time_t) le32toh(*((uint32_t *) (extra + 1))));
}
auto slash = strchr(sb.name, '/'); auto slash = strchr(sb.name, '/');
if (!slash) continue; if (!slash) continue;
members.emplace(slash, sb); members.emplace(slash, sb);
} }
#if 0
/* Sigh, libzip returns a local time, so convert to Unix
time. */
if (lastModified) {
struct tm tm;
localtime_r(&lastModified, &tm);
lastModified = timegm(&tm);
}
#endif
} }
~ZipInputAccessor() ~ZipInputAccessor()
@ -164,6 +191,11 @@ struct ZipInputAccessor : InputAccessor
return _readFile(path); return _readFile(path);
} }
std::optional<time_t> getLastModified() override
{
return lastModified;
}
}; };
ref<InputAccessor> makeZipInputAccessor(const CanonPath & path) ref<InputAccessor> makeZipInputAccessor(const CanonPath & path)