Skip to content

Commit

Permalink
fix: localToCloud/cloudBackup/twoWay mode deletions
Browse files Browse the repository at this point in the history
  • Loading branch information
Dwynr committed Nov 23, 2024
1 parent e5724f5 commit af64582
Show file tree
Hide file tree
Showing 5 changed files with 113 additions and 57 deletions.
8 changes: 4 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@filen/sync",
"version": "0.1.82",
"version": "0.1.83",
"description": "Filen Sync",
"main": "dist/index.js",
"types": "dist/index.d.ts",
Expand Down Expand Up @@ -54,7 +54,7 @@
"wait-on": "^7.2.0"
},
"dependencies": {
"@filen/sdk": "^0.1.182",
"@filen/sdk": "^0.1.183",
"@parcel/watcher": "^2.5.0",
"fast-glob": "^3.3.2",
"fs-extra": "^11.2.0",
Expand Down
152 changes: 101 additions & 51 deletions src/lib/deltas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,6 @@ export class Deltas {
// 6. Remote additions/filemodifications

// Local file/directory move/rename

if (this.sync.mode === "twoWay" || this.sync.mode === "localBackup" || this.sync.mode === "localToCloud") {
for (const inode in currentLocalTree.inodes) {
const currentItem = currentLocalTree.inodes[inode]
Expand Down Expand Up @@ -178,7 +177,6 @@ export class Deltas {
}

// Remote file/directory move/rename

if (this.sync.mode === "twoWay" || this.sync.mode === "cloudBackup" || this.sync.mode === "cloudToLocal") {
for (const uuid in currentRemoteTree.uuids) {
const currentItem = currentRemoteTree.uuids[uuid]
Expand Down Expand Up @@ -217,77 +215,130 @@ export class Deltas {
}

// Local deletions

if (this.sync.mode === "twoWay" || this.sync.mode === "localToCloud") {
for (const path in previousLocalTree.tree) {
if (pathsAdded[path] || erroredLocalPaths[path]) {
continue
}
// Only run current/previous comparisons if the sync already has saved state
if (this.sync.mode === "twoWay" && !this.sync.isPreviousSavedTreeStateEmpty) {
for (const path in previousLocalTree.tree) {
if (pathsAdded[path] || erroredLocalPaths[path]) {
continue
}

const previousLocalItem = previousLocalTree.tree[path]
const currentLocalItem = currentLocalTree.tree[path]
const previousLocalItem = previousLocalTree.tree[path]
const currentLocalItem = currentLocalTree.tree[path]

// If the item does not exist in the current tree but does in the previous one, it has been deleted.
// We also check if the previous inode does not exist in the current tree, and if so, we skip it (only in cloud -> local modes. It should always be deleted in local -> cloud modes if it exists remotely).
if (
!currentLocalItem &&
previousLocalItem //&&
//(this.sync.mode !== "localToCloud" ? !currentLocalTree.inodes[previousLocalItem.inode] : true)
) {
const delta: Delta = {
type: previousLocalItem.type === "directory" ? "deleteRemoteDirectory" : "deleteRemoteFile",
path
}

// If the item does not exist in the current tree but does in the previous one, it has been deleted.
// We also check if the previous inode does not exist in the current tree, and if so, we skip it (only in cloud -> local modes. It should always be deleted in local -> cloud modes if it exists remotely).
if (
!currentLocalItem &&
previousLocalItem //&&
//(this.sync.mode !== "localToCloud" ? !currentLocalTree.inodes[previousLocalItem.inode] : true)
) {
const delta: Delta = {
type: previousLocalItem.type === "directory" ? "deleteRemoteDirectory" : "deleteRemoteFile",
path
}
deltas.push(delta)

deltas.push(delta)
if (previousLocalItem.type === "directory") {
deletedRemoteDirectories.push(delta)
}

if (previousLocalItem.type === "directory") {
deletedRemoteDirectories.push(delta)
pathsAdded[path] = true
pathsAdded[previousLocalItem.path] = true
}
}
} else {
for (const path in currentRemoteTree.tree) {
if (pathsAdded[path] || erroredLocalPaths[path]) {
continue
}

pathsAdded[path] = true
pathsAdded[previousLocalItem.path] = true
const currentLocalItem = currentLocalTree.tree[path]
const currentRemoteItem = currentRemoteTree.tree[path]

// If the item does not exist in the current local tree but does in the remote one, it needs to be deleted remotely in localToCloud mode.
if (!currentLocalItem && currentRemoteItem) {
const delta: Delta = {
type: currentRemoteItem.type === "directory" ? "deleteRemoteDirectory" : "deleteRemoteFile",
path
}

deltas.push(delta)

if (currentRemoteItem.type === "directory") {
deletedRemoteDirectories.push(delta)
}

pathsAdded[path] = true
}
}
}
}

// Remote deletions

if (this.sync.mode === "twoWay" || this.sync.mode === "cloudToLocal") {
for (const path in previousRemoteTree.tree) {
if (pathsAdded[path]) {
continue
}
// Only run current/previous comparisons if the sync already has saved state
if (this.sync.mode === "twoWay" && !this.sync.isPreviousSavedTreeStateEmpty) {
for (const path in previousRemoteTree.tree) {
if (pathsAdded[path]) {
continue
}

const previousRemoteItem = previousRemoteTree.tree[path]
const currentRemoteItem = currentRemoteTree.tree[path]
const previousRemoteItem = previousRemoteTree.tree[path]
const currentRemoteItem = currentRemoteTree.tree[path]

// If the item does not exist in the current tree but does in the previous one, it has been deleted.
// We also check if the previous UUID does not exist in the current tree, and if so, we skip it (only in local -> cloud modes. It should always be deleted in cloud -> local modes if it exists locally).
if (
!currentRemoteItem &&
previousRemoteItem //&&
//(this.sync.mode !== "cloudToLocal" ? !currentRemoteTree.uuids[previousRemoteItem.uuid] : true)
) {
const delta: Delta = {
type: previousRemoteItem.type === "directory" ? "deleteLocalDirectory" : "deleteLocalFile",
path
}

// If the item does not exist in the current tree but does in the previous one, it has been deleted.
// We also check if the previous UUID does not exist in the current tree, and if so, we skip it (only in local -> cloud modes. It should always be deleted in cloud -> local modes if it exists locally).
if (
!currentRemoteItem &&
previousRemoteItem //&&
//(this.sync.mode !== "cloudToLocal" ? !currentRemoteTree.uuids[previousRemoteItem.uuid] : true)
) {
const delta: Delta = {
type: previousRemoteItem.type === "directory" ? "deleteLocalDirectory" : "deleteLocalFile",
path
}
deltas.push(delta)

deltas.push(delta)
if (previousRemoteItem.type === "directory") {
deletedLocalDirectories.push(delta)
}

if (previousRemoteItem.type === "directory") {
deletedLocalDirectories.push(delta)
pathsAdded[path] = true
pathsAdded[previousRemoteItem.path] = true
}
}
} else {
for (const path in currentLocalTree.tree) {
if (pathsAdded[path]) {
continue
}

pathsAdded[path] = true
pathsAdded[previousRemoteItem.path] = true
const currentLocalItem = currentLocalTree.tree[path]
const currentRemoteItem = currentRemoteTree.tree[path]

// If the item does not exist in the current remote tree but does in the local one, it needs to be deleted locally in cloudToLocal mode.
if (!currentRemoteItem && currentLocalItem) {
const delta: Delta = {
type: currentLocalItem.type === "directory" ? "deleteLocalDirectory" : "deleteLocalFile",
path
}

deltas.push(delta)

if (currentLocalItem.type === "directory") {
deletedLocalDirectories.push(delta)
}

pathsAdded[path] = true
}
}
}
}

// Local additions/filemodifications

// Local additions/fileModifications
if (this.sync.mode === "twoWay" || this.sync.mode === "localBackup" || this.sync.mode === "localToCloud") {
for (const path in currentLocalTree.tree) {
if (pathsAdded[path] || erroredLocalPaths[path]) {
Expand Down Expand Up @@ -348,7 +399,6 @@ export class Deltas {
}

// Remote additions/changes

if (this.sync.mode === "twoWay" || this.sync.mode === "cloudBackup" || this.sync.mode === "cloudToLocal") {
for (const path in currentRemoteTree.tree) {
if (pathsAdded[path]) {
Expand Down
5 changes: 5 additions & 0 deletions src/lib/state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -475,9 +475,12 @@ export class State {
!(await fs.exists(this.previousRemoteTreePath)) ||
!(await fs.exists(this.previousRemoteUUIDsPath))
) {
this.sync.isPreviousSavedTreeStateEmpty = true

return
}

this.sync.isPreviousSavedTreeStateEmpty = false
this.sync.previousLocalTree.tree = await this.readLargeRecordFromLineStream<LocalItem>(this.previousLocalTreePath)
this.sync.previousLocalTree.inodes = await this.readLargeRecordFromLineStream<LocalItem>(this.previousLocalINodesPath)
this.sync.previousRemoteTree.tree = await this.readLargeRecordFromLineStream<RemoteItem>(this.previousRemoteTreePath)
Expand All @@ -491,6 +494,8 @@ export class State {
await this.writeLargeRecordSerializedAndAtomically(this.previousLocalINodesPath, this.sync.previousLocalTree.inodes)
await this.writeLargeRecordSerializedAndAtomically(this.previousRemoteTreePath, this.sync.previousRemoteTree.tree)
await this.writeLargeRecordSerializedAndAtomically(this.previousRemoteUUIDsPath, this.sync.previousRemoteTree.uuids)

this.sync.isPreviousSavedTreeStateEmpty = false
}

public async clear(): Promise<void> {
Expand Down
1 change: 1 addition & 0 deletions src/lib/sync.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ export class Sync {
public localTrashDisabled: boolean
public localTreeErrors: LocalTreeError[] = []
public cleaningLocalTrash: boolean = false
public isPreviousSavedTreeStateEmpty: boolean = true

/**
* Creates an instance of Sync.
Expand Down

0 comments on commit af64582

Please sign in to comment.