diff --git a/pro/src/conflictLogic.ts b/pro/src/conflictLogic.ts index f9744c2..8a3b42b 100644 --- a/pro/src/conflictLogic.ts +++ b/pro/src/conflictLogic.ts @@ -167,7 +167,7 @@ export async function mergeFile( key, newArrayBuffer, rightEntity.mtimeCli ?? mtime, - rightEntity.mtimeCli ?? mtime + rightEntity.ctimeCli ?? rightEntity.mtimeCli ?? mtime ); return { diff --git a/pro/src/fsOnedriveFull.ts b/pro/src/fsOnedriveFull.ts index 3aaf39f..63c9991 100644 --- a/pro/src/fsOnedriveFull.ts +++ b/pro/src/fsOnedriveFull.ts @@ -294,13 +294,21 @@ const fromDriveItemToEntity = (x: DriveItem, remoteBaseDir: string): Entity => { if (mtimeTry === undefined || mtimeTry === null) { throw Error(`onedrive cannot parse mtime: ${JSON.stringify(x, null, 2)}`); } + let ctimeTry = x?.fileSystemInfo?.createdDateTime; + if (ctimeTry === undefined || ctimeTry === null) { + // throw Error(`onedrive cannot parse ctime: ${JSON.stringify(x, null, 2)}`); + // it doesn't hurt, we just use mtimeTry to fullfill + ctimeTry = mtimeTry; + } const mtimeSvr = Date.parse(mtimeTry); const mtimeCli = Date.parse(mtimeTry); + const ctimeCli = Date.parse(ctimeTry); return { key: key, keyRaw: key, mtimeSvr: mtimeSvr, mtimeCli: mtimeCli, + ctimeCli: ctimeCli, size: isFolder ? 0 : x.size!, sizeRaw: isFolder ? 0 : x.size!, synthesizedFile: false, @@ -771,6 +779,7 @@ export class FakeFsOnedriveFull extends FakeFs { keyRaw: origKey, mtimeSvr: mtime, mtimeCli: mtime, + ctimeCli: ctime, size: 0, sizeRaw: 0, synthesizedFile: true, diff --git a/pro/src/sync.ts b/pro/src/sync.ts index bef5d91..27b9d51 100644 --- a/pro/src/sync.ts +++ b/pro/src/sync.ts @@ -60,6 +60,17 @@ const copyEntityAndFixTimeFormat = ( result.mtimeCliFmt = unixTimeToStr(result.mtimeCli); } } + if (result.ctimeCli !== undefined) { + if (result.ctimeCli === 0) { + result.ctimeCli = undefined; + } else { + if (serviceType === "s3" || serviceType === "dropbox") { + // round to second instead of millisecond + result.ctimeCli = Math.floor(result.ctimeCli / 1000.0) * 1000; + } + result.ctimeCliFmt = unixTimeToStr(result.ctimeCli); + } + } if (result.mtimeSvr !== undefined) { if (result.mtimeSvr === 0) { result.mtimeSvr = undefined; diff --git a/src/baseTypes.ts b/src/baseTypes.ts index 8fb559f..2f86ca3 100644 --- a/src/baseTypes.ts +++ b/src/baseTypes.ts @@ -271,6 +271,8 @@ export interface Entity { keyRaw: string; mtimeCli?: number; mtimeCliFmt?: string; + ctimeCli?: number; + ctimeCliFmt?: string; mtimeSvr?: number; mtimeSvrFmt?: string; prevSyncTime?: number; diff --git a/src/copyLogic.ts b/src/copyLogic.ts index 851fe8a..5816bbc 100644 --- a/src/copyLogic.ts +++ b/src/copyLogic.ts @@ -41,7 +41,7 @@ export async function copyFile(key: string, left: FakeFs, right: FakeFs) { key, content, statsLeft.mtimeCli, - statsLeft.mtimeCli /* TODO */ + statsLeft.ctimeCli ?? statsLeft.mtimeCli ), content: content, }; diff --git a/src/fsLocal.ts b/src/fsLocal.ts index 54e7751..ae7be28 100644 --- a/src/fsLocal.ts +++ b/src/fsLocal.ts @@ -133,8 +133,10 @@ export class FakeFsLocal extends FakeFs { return { key: isFolder ? `${key}/` : key, // local always unencrypted keyRaw: isFolder ? `${key}/` : key, + ctimeCli: statRes.ctime, mtimeCli: statRes.mtime, mtimeSvr: statRes.mtime, + ctimeCliFmt: unixTimeToStr(statRes.ctime), mtimeCliFmt: unixTimeToStr(statRes.mtime), mtimeSvrFmt: unixTimeToStr(statRes.mtime), size: statRes.size, // local always unencrypted diff --git a/src/fsOnedrive.ts b/src/fsOnedrive.ts index 19a087b..e64e8c0 100644 --- a/src/fsOnedrive.ts +++ b/src/fsOnedrive.ts @@ -403,13 +403,23 @@ ${constructFromDriveItemToEntityError(x)}` if (mtimeTry === undefined || mtimeTry === null) { throw Error(`onedrive cannot parse mtime: ${JSON.stringify(x, null, 2)}`); } + + let ctimeTry = x?.fileSystemInfo?.createdDateTime; + if (ctimeTry === undefined || ctimeTry === null) { + // throw Error(`onedrive cannot parse ctime: ${JSON.stringify(x, null, 2)}`); + // it doesn't hurt, we just use mtimeTry to fullfill + ctimeTry = mtimeTry; + } + const mtimeSvr = Date.parse(mtimeTry); const mtimeCli = Date.parse(mtimeTry); + const ctimeCli = Date.parse(ctimeTry); return { key: key, keyRaw: key, mtimeSvr: mtimeSvr, mtimeCli: mtimeCli, + ctimeCli: ctimeCli, size: isFolder ? 0 : x.size!, sizeRaw: isFolder ? 0 : x.size!, synthesizedFile: false, @@ -878,6 +888,7 @@ export class FakeFsOnedrive extends FakeFs { keyRaw: origKey, mtimeSvr: mtime, mtimeCli: mtime, + ctimeCli: ctime, size: 0, sizeRaw: 0, synthesizedFile: true,