backend: allow negative timestamps in commits and operations

I was reading a draft of "Git Rev News: Edition 91" [1] where Peff
mentions some unfinished patches to allow negative timestamps in
Git. So I figured I should add support for that before I forget. I
haven't checked if libgit2 supports it, so it might be that our Git
backend still doesn't support it after this patch.

 [1] https://github.com/git/git.github.io/blob/master/rev_news/drafts/edition-91.md
This commit is contained in:
Martin von Zweigbergk 2022-09-29 21:29:45 -07:00 committed by Martin von Zweigbergk
parent 3fc7b549ec
commit 3b3f6129e6
8 changed files with 13 additions and 12 deletions

View file

@ -226,7 +226,7 @@ pub enum Phase {
}
#[derive(Debug, PartialEq, Eq, Clone, PartialOrd, Ord)]
pub struct MillisSinceEpoch(pub u64);
pub struct MillisSinceEpoch(pub i64);
#[derive(Debug, PartialEq, Eq, Clone, PartialOrd, Ord)]
pub struct Timestamp {
@ -244,7 +244,7 @@ impl Timestamp {
datetime: chrono::DateTime<Tz>,
) -> Self {
Self {
timestamp: MillisSinceEpoch(datetime.timestamp_millis() as u64),
timestamp: MillisSinceEpoch(datetime.timestamp_millis()),
tz_offset: datetime.offset().local_minus_utc() / 60,
}
}

View file

@ -101,7 +101,7 @@ impl GitBackend {
fn signature_from_git(signature: git2::Signature) -> Signature {
let name = signature.name().unwrap_or("<no name>").to_owned();
let email = signature.email().unwrap_or("<no email>").to_owned();
let timestamp = MillisSinceEpoch((signature.when().seconds() * 1000) as u64);
let timestamp = MillisSinceEpoch(signature.when().seconds() * 1000);
let tz_offset = signature.when().offset_minutes();
Signature {
name,
@ -117,7 +117,7 @@ fn signature_to_git(signature: &Signature) -> git2::Signature {
let name = &signature.name;
let email = &signature.email;
let time = git2::Time::new(
(signature.timestamp.timestamp.0 / 1000) as i64,
signature.timestamp.timestamp.0.div_euclid(1000),
signature.timestamp.tz_offset,
);
git2::Signature::new(name, email, &time).unwrap()

View file

@ -78,7 +78,7 @@ message Operation {
// TODO: Share with store.proto? Do we even need the timezone here?
message Timestamp {
uint64 millis_since_epoch = 1;
int64 millis_since_epoch = 1;
int32 tz_offset = 2;
}

View file

@ -47,7 +47,7 @@ message Commit {
string description = 5;
message Timestamp {
uint64 millis_since_epoch = 1;
int64 millis_since_epoch = 1;
int32 tz_offset = 2;
}
message Signature {

View file

@ -24,7 +24,7 @@ enum FileType {
}
message FileState {
uint64 mtime_millis_since_epoch = 1;
int64 mtime_millis_since_epoch = 1;
uint64 size = 2;
FileType file_type = 3;
// Set only if file_type is Conflict

View file

@ -222,7 +222,8 @@ fn mtime_from_metadata(metadata: &Metadata) -> MillisSinceEpoch {
.expect("mtime before unix epoch");
MillisSinceEpoch(
u64::try_from(since_epoch.as_millis()).expect("mtime billions of years into the future"),
i64::try_from(since_epoch.as_millis())
.expect("mtime billions of years into the future or past"),
)
}

View file

@ -3685,8 +3685,8 @@ fn cmd_bench(
fn format_timestamp(timestamp: &Timestamp) -> String {
let utc = Utc
.timestamp(
timestamp.timestamp.0 as i64 / 1000,
(timestamp.timestamp.0 % 1000) as u32 * 1000000,
timestamp.timestamp.0.div_euclid(1000),
(timestamp.timestamp.0.rem_euclid(1000)) as u32 * 1000000,
)
.with_timezone(&FixedOffset::east(timestamp.tz_offset * 60));
utc.format("%Y-%m-%d %H:%M:%S.%3f %:z").to_string()

View file

@ -101,8 +101,8 @@ impl TemplateProperty<Signature, String> for SignatureTimestamp {
fn extract(&self, context: &Signature) -> String {
let utc = Utc
.timestamp(
context.timestamp.timestamp.0 as i64 / 1000,
(context.timestamp.timestamp.0 % 1000) as u32 * 1000000,
context.timestamp.timestamp.0.div_euclid(1000),
context.timestamp.timestamp.0.rem_euclid(1000) as u32 * 1000000,
)
.with_timezone(&FixedOffset::east(context.timestamp.tz_offset * 60));
utc.format("%Y-%m-%d %H:%M:%S.%3f %:z").to_string()