diff --git a/app/src/lib/components/SyncButton.svelte b/app/src/lib/components/SyncButton.svelte
index 9806943d9..94e9bbb1f 100644
--- a/app/src/lib/components/SyncButton.svelte
+++ b/app/src/lib/components/SyncButton.svelte
@@ -31,8 +31,8 @@
>
{#if $baseServiceBusy$}
busy…
- {:else if $baseBranch?.lastFetched}
-
+ {:else if $baseBranch?.lastFetchedAt}
+
{/if}
diff --git a/app/src/lib/history/types.ts b/app/src/lib/history/types.ts
index 60ced1f4a..1255dfa24 100644
--- a/app/src/lib/history/types.ts
+++ b/app/src/lib/history/types.ts
@@ -1,4 +1,4 @@
-import { RemoteHunk } from '$lib/vbranches/types';
+import { RemoteHunk, dateFromDuration } from '$lib/vbranches/types';
import { Transform, Type } from 'class-transformer';
export type Operation =
@@ -61,6 +61,6 @@ export class Snapshot {
linesRemoved!: number;
filesChanged!: string[];
details?: SnapshotDetails;
- @Transform((obj) => new Date(obj.value * 1000))
+ @Transform(dateFromDuration)
createdAt!: Date;
}
diff --git a/app/src/lib/testing/fixtures.ts b/app/src/lib/testing/fixtures.ts
index 7473c8e43..7c84b739e 100644
--- a/app/src/lib/testing/fixtures.ts
+++ b/app/src/lib/testing/fixtures.ts
@@ -60,7 +60,7 @@ export const baseBranch = {
behind: 0,
upstreamCommits: [],
recentCommits: [remoteCommit0],
- lastFetchedMs: 1714843209991
+ lastFetchedAt: new Date(1714843209991)
};
export const user: User = {
diff --git a/app/src/lib/vbranches/types.ts b/app/src/lib/vbranches/types.ts
index 43385685f..f84308e1e 100644
--- a/app/src/lib/vbranches/types.ts
+++ b/app/src/lib/vbranches/types.ts
@@ -3,7 +3,28 @@ import { splitMessage } from '$lib/utils/commitMessage';
import { hashCode } from '$lib/utils/string';
import { isDefined, notNull } from '$lib/utils/typeguards';
import { convertRemoteToWebUrl } from '$lib/utils/url';
-import { Type, Transform } from 'class-transformer';
+import { Type, Transform, type TransformFnParams } from 'class-transformer';
+
+interface Duration {
+ secs: number;
+ nanos: number;
+}
+
+function isDuration(object: any): object is Duration {
+ const secsIsNumber = typeof object.secs === 'number';
+ const nanosIsNumber = typeof object.nanos === 'number';
+
+ return secsIsNumber && nanosIsNumber;
+}
+
+export function dateFromDuration(params: TransformFnParams): Date | undefined {
+ if (!params.value) return;
+
+ if (!isDuration(params.value)) {
+ throw Error('Expected a Duration object');
+ }
+ return new Date(params.value.secs * 1000 + params.value.nanos / 1000000);
+}
export type ChangeType =
/// Entry does not exist in old version
@@ -16,9 +37,7 @@ export type ChangeType =
export class Hunk {
id!: string;
diff!: string;
- @Transform((obj) => {
- return new Date(obj.value);
- })
+ @Transform(dateFromDuration)
modifiedAt!: Date;
filePath!: string;
hash?: string;
@@ -43,7 +62,7 @@ export class LocalFile {
@Type(() => Hunk)
hunks!: Hunk[];
expanded?: boolean;
- @Transform((obj) => new Date(obj.value))
+ @Transform(dateFromDuration)
modifiedAt!: Date;
// This indicates if a file has merge conflict markers generated and not yet resolved.
// This is true for files after a branch which does not apply cleanly (Branch.isMergeable == false) is applied.
@@ -121,7 +140,7 @@ export class Branch {
// If the branch has been already applied, then it was either performed cleanly or we generated conflict markers in the diffs.
// (therefore this field is applicable for stashed/unapplied or remote branches, i.e. active == false)
isMergeable!: Promise;
- @Transform((obj) => new Date(obj.value))
+ @Transform(dateFromDuration)
updatedAt!: Date;
// Indicates that branch is default target for new changes
selectedForChanges!: boolean;
@@ -152,7 +171,7 @@ export class Commit {
id!: string;
author!: Author;
description!: string;
- @Transform((obj) => new Date(obj.value))
+ @Transform(dateFromDuration)
createdAt!: Date;
isRemote!: boolean;
isIntegrated!: boolean;
@@ -197,7 +216,7 @@ export class RemoteCommit {
id!: string;
author!: Author;
description!: string;
- @Transform((obj) => new Date(obj.value * 1000))
+ @Transform(dateFromDuration)
createdAt!: Date;
changeId!: string;
isSigned!: boolean;
@@ -361,16 +380,13 @@ export class BaseBranch {
upstreamCommits!: RemoteCommit[];
@Type(() => RemoteCommit)
recentCommits!: RemoteCommit[];
- lastFetchedMs?: number;
+ @Transform(dateFromDuration)
+ lastFetchedAt?: Date;
actualPushRemoteName(): string {
return this.pushRemoteName || this.remoteName;
}
- get lastFetched(): Date | undefined {
- return this.lastFetchedMs ? new Date(this.lastFetchedMs) : undefined;
- }
-
get pushRepoBaseUrl(): string {
return convertRemoteToWebUrl(this.pushRemoteUrl);
}
diff --git a/crates/gitbutler-cli/src/main.rs b/crates/gitbutler-cli/src/main.rs
index 71111b5e2..35b133b7d 100644
--- a/crates/gitbutler-cli/src/main.rs
+++ b/crates/gitbutler-cli/src/main.rs
@@ -51,7 +51,8 @@ fn list_snapshots(repo_dir: &str) -> Result<()> {
let project = project_from_path(repo_dir);
let snapshots = project.list_snapshots(100, None)?;
for snapshot in snapshots {
- let ts = chrono::DateTime::from_timestamp(snapshot.created_at / 1000, 0);
+ // Using chrono for formatting the timestamp
+ let ts = chrono::DateTime::from_timestamp(snapshot.created_at.as_secs() as i64, 0);
let details = snapshot.details;
if let (Some(ts), Some(details)) = (ts, details) {
println!("{} {} {}", ts, snapshot.id, details.operation);
diff --git a/crates/gitbutler-core/src/git/commit.rs b/crates/gitbutler-core/src/git/commit.rs
index 665d468ce..b3c8c7d51 100644
--- a/crates/gitbutler-core/src/git/commit.rs
+++ b/crates/gitbutler-core/src/git/commit.rs
@@ -1,3 +1,5 @@
+use std::time::Duration;
+
use super::{Oid, Result, Signature, Tree};
use bstr::BStr;
@@ -54,8 +56,8 @@ impl<'repo> Commit<'repo> {
self.commit.parent(n).map(Into::into).map_err(Into::into)
}
- pub fn time(&self) -> git2::Time {
- self.commit.time()
+ pub fn time(&self) -> Duration {
+ Duration::from_secs(self.commit.time().seconds().try_into().unwrap())
}
pub fn author(&self) -> Signature<'_> {
diff --git a/crates/gitbutler-core/src/ops/entry.rs b/crates/gitbutler-core/src/ops/entry.rs
index 9d43d6e74..2808a964e 100644
--- a/crates/gitbutler-core/src/ops/entry.rs
+++ b/crates/gitbutler-core/src/ops/entry.rs
@@ -7,6 +7,7 @@ use std::fmt::Display;
use std::fmt::Formatter;
use std::path::PathBuf;
use std::str::FromStr;
+use std::time::Duration;
use strum::EnumString;
use serde::Serialize;
@@ -19,7 +20,7 @@ pub struct Snapshot {
/// The sha of the commit that represents the snapshot
pub id: String,
/// Snapshot creation time in epoch milliseconds
- pub created_at: i64,
+ pub created_at: Duration,
/// The number of working directory lines added in the snapshot
pub lines_added: usize,
/// The number of working directory lines removed in the snapshot
@@ -304,7 +305,7 @@ mod tests {
let commit_sha = "1234567890".to_string();
let commit_message =
"Create a new snapshot\n\nBody text 1\nBody text2\n\nBody text 3\n\nVersion: 1\nOperation: CreateCommit\nFoo: Bar\n".to_string();
- let created_at = 1234567890;
+ let created_at = Duration::from_secs(1234567890);
let details = SnapshotDetails::from_str(&commit_message.clone()).unwrap();
let snapshot = Snapshot {
id: commit_sha.clone(),
diff --git a/crates/gitbutler-core/src/ops/oplog.rs b/crates/gitbutler-core/src/ops/oplog.rs
index 9e4442a65..a3dbd2486 100644
--- a/crates/gitbutler-core/src/ops/oplog.rs
+++ b/crates/gitbutler-core/src/ops/oplog.rs
@@ -3,6 +3,7 @@ use git2::FileMode;
use itertools::Itertools;
use std::collections::HashMap;
use std::str::FromStr;
+use std::time::Duration;
use std::{fs, path::PathBuf};
use anyhow::Result;
@@ -349,7 +350,7 @@ impl Oplog for Project {
lines_added,
lines_removed,
files_changed,
- created_at: commit.time().seconds(),
+ created_at: Duration::from_secs(commit.time().seconds().try_into().unwrap()),
});
if snapshots.len() >= limit {
@@ -363,7 +364,7 @@ impl Oplog for Project {
lines_added: 0,
lines_removed: 0,
files_changed: Vec::new(), // Fix: Change 0 to an empty vector
- created_at: commit.time().seconds(),
+ created_at: Duration::from_secs(commit.time().seconds().try_into().unwrap()),
});
break;
}
diff --git a/crates/gitbutler-core/src/project_repository/repository.rs b/crates/gitbutler-core/src/project_repository/repository.rs
index d2f5d96b4..55f1bcd1f 100644
--- a/crates/gitbutler-core/src/project_repository/repository.rs
+++ b/crates/gitbutler-core/src/project_repository/repository.rs
@@ -7,7 +7,6 @@ use std::{
use anyhow::{Context, Result};
use super::conflicts;
-use crate::error::{AnyhowContextExt, Code, ErrorWithContext};
use crate::{
askpass, error,
git::{self, credentials::HelpError, Url},
@@ -15,6 +14,10 @@ use crate::{
ssh, users,
virtual_branches::{Branch, BranchId},
};
+use crate::{
+ error::{AnyhowContextExt, Code, ErrorWithContext},
+ time,
+};
pub struct Repository {
pub git_repository: git::Repository,
@@ -175,7 +178,7 @@ impl Repository {
let branch = self.git_repository.find_branch(&target_branch_refname)?;
let commit_id = branch.peel_to_commit()?.id();
- let now = crate::time::now_ms();
+ let now = time::now_ms();
let branch_name = format!("test-push-{now}");
let refname =
diff --git a/crates/gitbutler-core/src/projects/project.rs b/crates/gitbutler-core/src/projects/project.rs
index e59e70a64..22576c329 100644
--- a/crates/gitbutler-core/src/projects/project.rs
+++ b/crates/gitbutler-core/src/projects/project.rs
@@ -1,6 +1,6 @@
use std::{
path::{self, PathBuf},
- time,
+ time::SystemTime,
};
use serde::{Deserialize, Serialize};
@@ -38,16 +38,16 @@ pub struct ApiProject {
#[serde(rename_all = "camelCase")]
pub enum FetchResult {
Fetched {
- timestamp: time::SystemTime,
+ timestamp: SystemTime,
},
Error {
- timestamp: time::SystemTime,
+ timestamp: SystemTime,
error: String,
},
}
impl FetchResult {
- pub fn timestamp(&self) -> &time::SystemTime {
+ pub fn timestamp(&self) -> &SystemTime {
match self {
FetchResult::Fetched { timestamp } | FetchResult::Error { timestamp, .. } => timestamp,
}
@@ -57,7 +57,7 @@ impl FetchResult {
#[derive(Debug, Deserialize, Serialize, Copy, Clone)]
pub struct CodePushState {
pub id: git::Oid,
- pub timestamp: time::SystemTime,
+ pub timestamp: SystemTime,
}
pub type ProjectId = Id;
diff --git a/crates/gitbutler-core/src/time.rs b/crates/gitbutler-core/src/time.rs
index 50d9c28e7..35e6f11cb 100644
--- a/crates/gitbutler-core/src/time.rs
+++ b/crates/gitbutler-core/src/time.rs
@@ -1,12 +1,43 @@
-use std::time::UNIX_EPOCH;
+use std::time::{Duration, UNIX_EPOCH};
+
+/// Gets the duration of time since the Unix epoch.
+///
+/// # Panics
+/// Panics if the system time is set before the Unix epoch.
+pub fn now() -> Duration {
+ UNIX_EPOCH
+ .elapsed()
+ .expect("system time is set before the Unix epoch")
+}
/// Gets the number of milliseconds since the Unix epoch.
///
/// # Panics
/// Panics if the system time is set before the Unix epoch.
pub fn now_ms() -> u128 {
- UNIX_EPOCH
- .elapsed()
- .expect("system time is set before the Unix epoch")
- .as_millis()
+ now().as_millis()
+}
+
+pub mod duration_serializer {
+ use std::time::Duration;
+
+ use serde::{Deserialize, Deserializer, Serializer};
+
+ pub fn serialize(duration: &Duration, serializer: S) -> Result
+ where
+ S: Serializer,
+ {
+ serializer.serialize_str(&duration.as_millis().to_string())
+ }
+
+ pub fn deserialize<'de, D>(deserializer: D) -> Result
+ where
+ D: Deserializer<'de>,
+ {
+ let millis_str = String::deserialize(deserializer)?;
+ let millis = millis_str
+ .parse::()
+ .map_err(serde::de::Error::custom)?;
+ Ok(Duration::from_millis(millis))
+ }
}
diff --git a/crates/gitbutler-core/src/virtual_branches/base.rs b/crates/gitbutler-core/src/virtual_branches/base.rs
index d43157895..22099f50b 100644
--- a/crates/gitbutler-core/src/virtual_branches/base.rs
+++ b/crates/gitbutler-core/src/virtual_branches/base.rs
@@ -1,4 +1,7 @@
-use std::{path::Path, time};
+use std::{
+ path::Path,
+ time::{self, Duration},
+};
use anyhow::{Context, Result};
use serde::Serialize;
@@ -31,7 +34,7 @@ pub struct BaseBranch {
pub behind: usize,
pub upstream_commits: Vec,
pub recent_commits: Vec,
- pub last_fetched_ms: Option,
+ pub last_fetched_at: Option,
}
pub fn get_base_branch_data(
@@ -210,7 +213,7 @@ pub fn set_base_branch(
},
);
- let now_ms = crate::time::now_ms();
+ let now = crate::time::now();
let (upstream, upstream_head) = if let git::Refname::Local(head_name) = &head_name {
let upstream_name = target_branch_ref.with_branch(head_name.branch());
@@ -244,8 +247,8 @@ pub fn set_base_branch(
applied: true,
upstream,
upstream_head,
- created_timestamp_ms: now_ms,
- updated_timestamp_ms: now_ms,
+ created_at: now,
+ updated_at: now,
head: current_head_commit.id(),
tree: super::write_tree_onto_commit(
project_repository,
@@ -646,13 +649,13 @@ pub fn target_to_base_branch(
behind: upstream_commits.len(),
upstream_commits,
recent_commits,
- last_fetched_ms: project_repository
+ last_fetched_at: project_repository
.project()
.project_data_last_fetch
.as_ref()
.map(FetchResult::timestamp)
.copied()
- .map(|t| t.duration_since(time::UNIX_EPOCH).unwrap().as_millis()),
+ .map(|t| t.duration_since(time::UNIX_EPOCH).unwrap()),
};
Ok(base)
}
diff --git a/crates/gitbutler-core/src/virtual_branches/branch/hunk.rs b/crates/gitbutler-core/src/virtual_branches/branch/hunk.rs
index 0379698b4..59b0f0062 100644
--- a/crates/gitbutler-core/src/virtual_branches/branch/hunk.rs
+++ b/crates/gitbutler-core/src/virtual_branches/branch/hunk.rs
@@ -2,6 +2,7 @@ use std::{fmt::Display, ops::RangeInclusive, str::FromStr};
use anyhow::{anyhow, Context, Result};
use bstr::ByteSlice;
+use std::time::Duration;
use crate::git::diff;
@@ -10,7 +11,7 @@ pub type HunkHash = md5::Digest;
#[derive(Debug, Eq, Clone)]
pub struct Hunk {
pub hash: Option,
- pub timestamp_ms: Option,
+ pub timestamp: Option,
pub start: u32,
pub end: u32,
pub locked_to: Vec,
@@ -22,7 +23,7 @@ impl From<&diff::GitHunk> for Hunk {
start: hunk.new_start,
end: hunk.new_start + hunk.new_lines,
hash: Some(Hunk::hash_diff(&hunk.diff_lines)),
- timestamp_ms: None,
+ timestamp: None,
locked_to: hunk.locked_to.to_vec(),
}
}
@@ -44,7 +45,7 @@ impl From> for Hunk {
start: *range.start(),
end: *range.end(),
hash: None,
- timestamp_ms: None,
+ timestamp: None,
locked_to: vec![],
}
}
@@ -83,27 +84,28 @@ impl FromStr for Hunk {
None
};
- let timestamp_ms = if let Some(raw_timestamp_ms) = range.next() {
- Some(
- raw_timestamp_ms
- .parse::()
- .context(format!("failed to parse timestamp_ms of range: {}", s))?,
- )
+ let timestamp = if let Some(raw_timestamp_ms) = range.next() {
+ let parsed_millis = raw_timestamp_ms
+ .parse::()
+ .context(format!("failed to parse timestamp_ms of range: {}", s))?;
+ Some(Duration::from_millis(parsed_millis))
} else {
None
};
- Hunk::new(start, end, hash, timestamp_ms)
+ Hunk::new(start, end, hash, timestamp)
}
}
impl Display for Hunk {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}-{}", self.start, self.end)?;
- match (&self.hash, &self.timestamp_ms) {
- (Some(hash), Some(timestamp_ms)) => write!(f, "-{:x}-{}", hash, timestamp_ms),
+ match (&self.hash, &self.timestamp) {
+ (Some(hash), Some(timestamp)) => {
+ write!(f, "-{:x}-{}", hash, timestamp.as_millis())
+ }
(Some(hash), None) => write!(f, "-{:x}", hash),
- (None, Some(timestamp_ms)) => write!(f, "--{}", timestamp_ms),
+ (None, Some(timestamp)) => write!(f, "--{}", timestamp.as_millis()),
(None, None) => Ok(()),
}
}
@@ -114,14 +116,14 @@ impl Hunk {
start: u32,
end: u32,
hash: Option,
- timestamp_ms: Option,
+ timestamp: Option,
) -> Result {
if start > end {
Err(anyhow!("invalid range: {}-{}", start, end))
} else {
Ok(Hunk {
hash,
- timestamp_ms,
+ timestamp,
start,
end,
locked_to: vec![],
@@ -134,13 +136,13 @@ impl Hunk {
self
}
- pub fn with_timestamp(mut self, timestamp_ms: u128) -> Self {
- self.timestamp_ms = Some(timestamp_ms);
+ pub fn with_timestamp(mut self, timestamp: Duration) -> Self {
+ self.timestamp = Some(timestamp);
self
}
- pub fn timestamp_ms(&self) -> Option {
- self.timestamp_ms
+ pub fn timestamp(&self) -> Option {
+ self.timestamp
}
pub fn contains(&self, line: u32) -> bool {
diff --git a/crates/gitbutler-core/src/virtual_branches/branch/mod.rs b/crates/gitbutler-core/src/virtual_branches/branch/mod.rs
index f01badac4..43657e669 100644
--- a/crates/gitbutler-core/src/virtual_branches/branch/mod.rs
+++ b/crates/gitbutler-core/src/virtual_branches/branch/mod.rs
@@ -2,12 +2,14 @@ mod file_ownership;
mod hunk;
mod ownership;
-use anyhow::Result;
+use std::time::Duration;
+
pub use file_ownership::OwnershipClaim;
pub use hunk::{Hunk, HunkHash};
pub use ownership::{reconcile_claims, BranchOwnershipClaims};
use serde::{Deserialize, Serialize};
+use crate::time::duration_serializer;
use crate::{git, id::Id};
pub type BranchId = Id;
@@ -25,16 +27,10 @@ pub struct Branch {
pub upstream: Option,
// upstream_head is the last commit on we've pushed to the upstream branch
pub upstream_head: Option,
- #[serde(
- serialize_with = "serialize_u128",
- deserialize_with = "deserialize_u128"
- )]
- pub created_timestamp_ms: u128,
- #[serde(
- serialize_with = "serialize_u128",
- deserialize_with = "deserialize_u128"
- )]
- pub updated_timestamp_ms: u128,
+ #[serde(rename = "created_timestamp_ms", with = "duration_serializer")]
+ pub created_at: Duration,
+ #[serde(rename = "updated_timestamp_ms", with = "duration_serializer")]
+ pub updated_at: Duration,
/// tree is the last git tree written to a session, or merge base tree if this is new. use this for delta calculation from the session data
pub tree: git::Oid,
/// head is id of the last "virtual" commit in this branch
@@ -47,22 +43,6 @@ pub struct Branch {
pub selected_for_changes: Option,
}
-fn serialize_u128(x: &u128, s: S) -> Result
-where
- S: serde::Serializer,
-{
- s.serialize_str(&x.to_string())
-}
-
-fn deserialize_u128<'de, D>(d: D) -> Result
-where
- D: serde::Deserializer<'de>,
-{
- let s = String::deserialize(d)?;
- let x: u128 = s.parse().map_err(serde::de::Error::custom)?;
- Ok(x)
-}
-
impl Branch {
pub fn refname(&self) -> git::VirtualRefname {
self.into()
@@ -87,144 +67,3 @@ pub struct BranchCreateRequest {
pub order: Option,
pub selected_for_changes: Option,
}
-
-impl Branch {
- pub fn from_reader(reader: &crate::reader::Reader<'_>) -> Result {
- let results = reader.batch(&[
- "id",
- "meta/name",
- "meta/notes",
- "meta/applied",
- "meta/order",
- "meta/upstream",
- "meta/upstream_head",
- "meta/tree",
- "meta/head",
- "meta/created_timestamp_ms",
- "meta/updated_timestamp_ms",
- "meta/ownership",
- "meta/selected_for_changes",
- ])?;
-
- let id: String = results[0].clone()?.try_into()?;
- let id: BranchId = id.parse().map_err(|e| {
- crate::reader::Error::Io(
- std::io::Error::new(std::io::ErrorKind::Other, format!("id: {}", e)).into(),
- )
- })?;
- let name: String = results[1].clone()?.try_into()?;
-
- let notes: String = match results[2].clone() {
- Ok(notes) => Ok(notes.try_into()?),
- Err(crate::reader::Error::NotFound) => Ok(String::new()),
- Err(e) => Err(e),
- }?;
-
- let applied = match results[3].clone() {
- Ok(applied) => applied.try_into(),
- _ => Ok(false),
- }
- .unwrap_or(false);
-
- let order: usize = match results[4].clone() {
- Ok(order) => Ok(order.try_into()?),
- Err(crate::reader::Error::NotFound) => Ok(0),
- Err(e) => Err(e),
- }?;
-
- let upstream = match results[5].clone() {
- Ok(crate::reader::Content::UTF8(upstream)) => {
- if upstream.is_empty() {
- Ok(None)
- } else {
- upstream
- .parse::()
- .map(Some)
- .map_err(|e| {
- crate::reader::Error::Io(
- std::io::Error::new(
- std::io::ErrorKind::Other,
- format!("meta/upstream: {}", e),
- )
- .into(),
- )
- })
- }
- }
- Ok(_) | Err(crate::reader::Error::NotFound) => Ok(None),
- Err(e) => Err(e),
- }?;
-
- let upstream_head = match results[6].clone() {
- Ok(crate::reader::Content::UTF8(upstream_head)) => {
- upstream_head.parse().map(Some).map_err(|e| {
- crate::reader::Error::Io(
- std::io::Error::new(
- std::io::ErrorKind::Other,
- format!("meta/upstream_head: {}", e),
- )
- .into(),
- )
- })
- }
- Ok(_) | Err(crate::reader::Error::NotFound) => Ok(None),
- Err(e) => Err(e),
- }?;
-
- let tree: String = results[7].clone()?.try_into()?;
- let head: String = results[8].clone()?.try_into()?;
- let created_timestamp_ms = results[9].clone()?.try_into()?;
- let updated_timestamp_ms = results[10].clone()?.try_into()?;
-
- let ownership_string: String = results[11].clone()?.try_into()?;
- let ownership = ownership_string.parse().map_err(|e| {
- crate::reader::Error::Io(
- std::io::Error::new(std::io::ErrorKind::Other, format!("meta/ownership: {}", e))
- .into(),
- )
- })?;
-
- let selected_for_changes = match results[12].clone() {
- Ok(raw_ts) => {
- let ts = raw_ts.try_into().map_err(|e| {
- crate::reader::Error::Io(
- std::io::Error::new(
- std::io::ErrorKind::Other,
- format!("meta/selected_for_changes: {}", e),
- )
- .into(),
- )
- })?;
- Ok(Some(ts))
- }
- Err(crate::reader::Error::NotFound) => Ok(None),
- Err(e) => Err(e),
- }?;
-
- Ok(Self {
- id,
- name,
- notes,
- applied,
- upstream,
- upstream_head,
- tree: tree.parse().map_err(|e| {
- crate::reader::Error::Io(
- std::io::Error::new(std::io::ErrorKind::Other, format!("meta/tree: {}", e))
- .into(),
- )
- })?,
- head: head.parse().map_err(|e| {
- crate::reader::Error::Io(
- std::io::Error::new(std::io::ErrorKind::Other, format!("meta/head: {}", e))
- .into(),
- )
- })?,
- created_timestamp_ms,
- updated_timestamp_ms,
- ownership,
- order,
- selected_for_changes,
- })
- }
-}
diff --git a/crates/gitbutler-core/src/virtual_branches/controller.rs b/crates/gitbutler-core/src/virtual_branches/controller.rs
index 10efcaf83..a59f221d0 100644
--- a/crates/gitbutler-core/src/virtual_branches/controller.rs
+++ b/crates/gitbutler-core/src/virtual_branches/controller.rs
@@ -6,7 +6,7 @@ use crate::{
snapshot::Snapshot,
},
};
-use std::{collections::HashMap, path::Path, sync::Arc};
+use std::{collections::HashMap, path::Path, sync::Arc, time::SystemTime};
use anyhow::Context;
use tokio::{sync::Semaphore, task::JoinHandle};
@@ -930,10 +930,10 @@ impl ControllerInner {
.map_err(errors::FetchFromTargetError::Remote)
{
Ok(()) => projects::FetchResult::Fetched {
- timestamp: std::time::SystemTime::now(),
+ timestamp: SystemTime::now(),
},
Err(error) => projects::FetchResult::Error {
- timestamp: std::time::SystemTime::now(),
+ timestamp: SystemTime::now(),
error: error.to_string(),
},
};
diff --git a/crates/gitbutler-core/src/virtual_branches/remote.rs b/crates/gitbutler-core/src/virtual_branches/remote.rs
index fb4dede60..ee7914047 100644
--- a/crates/gitbutler-core/src/virtual_branches/remote.rs
+++ b/crates/gitbutler-core/src/virtual_branches/remote.rs
@@ -1,4 +1,4 @@
-use std::path::Path;
+use std::{path::Path, time::Duration};
use anyhow::{Context, Result};
use bstr::BString;
@@ -25,7 +25,7 @@ pub struct RemoteBranch {
pub sha: git::Oid,
pub name: git::Refname,
pub upstream: Option,
- pub last_commit_timestamp_ms: Option,
+ pub last_commit_at: Option,
pub last_commit_author: Option,
}
@@ -45,7 +45,7 @@ pub struct RemoteCommit {
pub id: String,
#[serde(serialize_with = "crate::serde::as_string_lossy")]
pub description: BString,
- pub created_at: u128,
+ pub created_at: Duration,
pub author: Author,
}
@@ -128,12 +128,7 @@ pub fn branch_to_remote_branch(branch: &git::Branch) -> Result