Skip to content

Add an API to get the timestamp of a unit by its output path #239

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 7, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions Sources/IndexStoreDB/IndexStoreDB.swift
Original file line number Diff line number Diff line change
Expand Up @@ -488,6 +488,19 @@ public final class IndexStoreDB {
}
return Date(timeIntervalSince1970: Double(timestamp) / 1_000_000_000)
}

/// Returns a modification date of the latest unit that contains the given source file.
///
/// If no unit containing the given source file exists, returns `nil`
public func dateOfUnitFor(outputPath: String) -> Date? {
let timestamp = outputPath.withCString { outputPathCString in
indexstoredb_timestamp_of_unit_for_output_path(impl, outputPathCString)
}
if timestamp == 0 {
return nil
}
return Date(timeIntervalSince1970: Double(timestamp) / 1_000_000_000)
}
}

public protocol IndexStoreLibraryProvider {
Expand Down
17 changes: 17 additions & 0 deletions Sources/IndexStoreDB_CIndexStoreDB/CIndexStoreDB.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -698,4 +698,21 @@ indexstoredb_timestamp_of_latest_unit_for_file(
return 0;
}

INDEXSTOREDB_PUBLIC uint64_t
indexstoredb_timestamp_of_unit_for_output_path(
_Nonnull indexstoredb_index_t index,
const char *_Nonnull unitOutputPath
) {
auto obj = (Object<std::shared_ptr<IndexSystem>> *)index;
llvm::Optional<llvm::sys::TimePoint<>> timePoint = obj->value->timestampOfUnitForOutputPath(unitOutputPath);
if (timePoint) {
// Up until C++20 the reference date of time_since_epoch is undefined but according to
// https://en.cppreference.com/w/cpp/chrono/system_clock most implementations use Unix Time.
// Since C++20, system_clock is defined to measure time since 1/1/1970.
// We rely on `time_since_epoch` always returning the nanoseconds since 1/1/1970.
return timePoint->time_since_epoch().count();
}
return 0;
}

ObjectBase::~ObjectBase() {}
Original file line number Diff line number Diff line change
Expand Up @@ -601,6 +601,15 @@ indexstoredb_timestamp_of_latest_unit_for_file(
const char *_Nonnull fileName
);

/// Returns a Unix timestamp (nanoseconds since 1/1/1970) of the unit that has the given output path.
///
/// If no unit with this output paths exits, returns 0.
INDEXSTOREDB_PUBLIC uint64_t
indexstoredb_timestamp_of_unit_for_output_path(
_Nonnull indexstoredb_index_t index,
const char *_Nonnull unitOutputPath
);

INDEXSTOREDB_END_DECLS

#endif
19 changes: 16 additions & 3 deletions Sources/IndexStoreDB_Index/IndexDatastore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
//===----------------------------------------------------------------------===//

#include "IndexDatastore.h"
#include "IndexStoreDB_LLVMSupport/llvm_ADT_None.h"
#include "StoreSymbolRecord.h"
#include <IndexStoreDB_Core/Symbol.h>
#include <IndexStoreDB_Index/FilePathIndex.h>
Expand Down Expand Up @@ -172,6 +173,7 @@ class IndexDatastoreImpl {

bool isUnitOutOfDate(StringRef unitOutputPath, ArrayRef<StringRef> dirtyFiles);
bool isUnitOutOfDate(StringRef unitOutputPath, llvm::sys::TimePoint<> outOfDateModTime);
llvm::Optional<sys::TimePoint<>> timestampOfUnitForOutputPath(StringRef unitOutputPath);
void checkUnitContainingFileIsOutOfDate(StringRef file);

void addUnitOutFilePaths(ArrayRef<StringRef> filePaths, bool waitForProcessing);
Expand Down Expand Up @@ -1101,16 +1103,23 @@ bool IndexDatastoreImpl::isUnitOutOfDate(StringRef unitOutputPath, ArrayRef<Stri
}

bool IndexDatastoreImpl::isUnitOutOfDate(StringRef unitOutputPath, sys::TimePoint<> outOfDateModTime) {
auto unitModTime = timestampOfUnitForOutputPath(unitOutputPath);
if (!unitModTime) {
return true;
}
return outOfDateModTime > unitModTime;
}

llvm::Optional<sys::TimePoint<>> IndexDatastoreImpl::timestampOfUnitForOutputPath(StringRef unitOutputPath) {
SmallString<128> nameBuf;
IdxStore->getUnitNameFromOutputPath(unitOutputPath, nameBuf);
StringRef unitName = nameBuf.str();
std::string error;
auto optUnitModTime = IdxStore->getUnitModificationTime(unitName, error);
if (!optUnitModTime)
return true;
return llvm::None;

auto unitModTime = toTimePoint(optUnitModTime.getValue());
return outOfDateModTime > unitModTime;
return toTimePoint(optUnitModTime.getValue());
}

void IndexDatastoreImpl::checkUnitContainingFileIsOutOfDate(StringRef file) {
Expand Down Expand Up @@ -1169,6 +1178,10 @@ bool IndexDatastore::isUnitOutOfDate(StringRef unitOutputPath, sys::TimePoint<>
return IMPL->isUnitOutOfDate(unitOutputPath, outOfDateModTime);
}

llvm::Optional<sys::TimePoint<>> IndexDatastore::timestampOfUnitForOutputPath(StringRef unitOutputPath) {
return IMPL->timestampOfUnitForOutputPath(unitOutputPath);
}

void IndexDatastore::checkUnitContainingFileIsOutOfDate(StringRef file) {
return IMPL->checkUnitContainingFileIsOutOfDate(file);
}
Expand Down
1 change: 1 addition & 0 deletions Sources/IndexStoreDB_Index/IndexDatastore.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ class IndexDatastore {

bool isUnitOutOfDate(StringRef unitOutputPath, ArrayRef<StringRef> dirtyFiles);
bool isUnitOutOfDate(StringRef unitOutputPath, llvm::sys::TimePoint<> outOfDateModTime);
llvm::Optional<llvm::sys::TimePoint<>> timestampOfUnitForOutputPath(StringRef unitOutputPath);

/// Check whether any unit(s) containing \p file are out of date and if so,
/// *synchronously* notify the delegate.
Expand Down
9 changes: 9 additions & 0 deletions Sources/IndexStoreDB_Index/IndexSystem.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@ class IndexSystemImpl {

bool isUnitOutOfDate(StringRef unitOutputPath, ArrayRef<StringRef> dirtyFiles);
bool isUnitOutOfDate(StringRef unitOutputPath, llvm::sys::TimePoint<> outOfDateModTime);
llvm::Optional<llvm::sys::TimePoint<>> timestampOfUnitForOutputPath(StringRef unitOutputPath);
void checkUnitContainingFileIsOutOfDate(StringRef file);

void registerMainFiles(ArrayRef<StringRef> filePaths, StringRef productName);
Expand Down Expand Up @@ -305,6 +306,10 @@ bool IndexSystemImpl::isUnitOutOfDate(StringRef unitOutputPath, llvm::sys::TimeP
return IndexStore->isUnitOutOfDate(unitOutputPath, outOfDateModTime);
}

llvm::Optional<llvm::sys::TimePoint<>> IndexSystemImpl::timestampOfUnitForOutputPath(StringRef unitOutputPath) {
return IndexStore->timestampOfUnitForOutputPath(unitOutputPath);
}

void IndexSystemImpl::checkUnitContainingFileIsOutOfDate(StringRef file) {
return IndexStore->checkUnitContainingFileIsOutOfDate(file);
}
Expand Down Expand Up @@ -686,6 +691,10 @@ bool IndexSystem::isUnitOutOfDate(StringRef unitOutputPath, llvm::sys::TimePoint
return IMPL->isUnitOutOfDate(unitOutputPath, outOfDateModTime);
}

llvm::Optional<llvm::sys::TimePoint<>> IndexSystem::timestampOfUnitForOutputPath(StringRef unitOutputPath) {
return IMPL->timestampOfUnitForOutputPath(unitOutputPath);
}

void IndexSystem::checkUnitContainingFileIsOutOfDate(StringRef file) {
return IMPL->checkUnitContainingFileIsOutOfDate(file);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ class INDEXSTOREDB_EXPORT IndexSystem {

bool isUnitOutOfDate(StringRef unitOutputPath, ArrayRef<StringRef> dirtyFiles);
bool isUnitOutOfDate(StringRef unitOutputPath, llvm::sys::TimePoint<> outOfDateModTime);
llvm::Optional<llvm::sys::TimePoint<>> timestampOfUnitForOutputPath(StringRef unitOutputPath);

/// Check whether any unit(s) containing \p file are out of date and if so,
/// *synchronously* notify the delegate.
Expand Down