Skip to content

Commit 81298c5

Browse files
committed
feat(cli): Add --delete flag to remove remote files not present locally
1 parent 77cf22f commit 81298c5

File tree

2 files changed

+41
-1
lines changed

2 files changed

+41
-1
lines changed

cli/src/commands/upload.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,10 @@ export async function uploadAction(
142142
"command": "clone",
143143
})
144144

145+
if (options.delete) {
146+
worker.postMessage({ command: "clearWorktree" })
147+
}
148+
145149
// Upload all files
146150
await addGitFiles(worker, dataset_directory_abs)
147151

@@ -184,6 +188,13 @@ export const upload = validateCommand
184188
.option("-n, --new", "Skip confirmation to create a new dataset.", {
185189
conflicts: ["dataset"],
186190
})
191+
.option(
192+
"--delete",
193+
"Similar to rsync --delete, remove files in the remote dataset that are not present in the local dataset.",
194+
{
195+
depends: ["dataset"],
196+
},
197+
)
187198
.option(
188199
"--affirmDefaced",
189200
"All structural scans have been defaced, obscuring any tissue on or near the face that could potentially be used to reconstruct the facial structure.",

cli/src/worker/git.ts

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import type { GitWorkerEventAdd } from "./types/git-context.ts"
22
import type { GitAnnexAttributes, GitAnnexBackend } from "../gitattributes.ts"
33
import { matchGitAttributes, parseGitAttributes } from "../gitattributes.ts"
44
import { dirname, join } from "@std/path"
5-
import { default as git, STAGE, TREE } from "isomorphic-git"
5+
import { default as git, STAGE, TREE, walk } from "isomorphic-git"
66
import { logger, setupLogging } from "../logger.ts"
77
import { PromiseQueue } from "./queue.ts"
88
import { checkKey, storeKey } from "./transferKey.ts"
@@ -76,6 +76,33 @@ async function update() {
7676
logger.info(`${context.datasetId} draft fetched!`)
7777
}
7878

79+
/**
80+
* Stages removal of all files from the working tree
81+
* Used when the --delete flag prior to adding new files
82+
*/
83+
async function clearWorktree() {
84+
logger.info(`Clearing working tree (--delete flag)...`)
85+
await resetWorktree(context, await getDefault(context))
86+
let fileCount = 0
87+
for (const file of await git.listFiles({ ...context.config() })) {
88+
if (file === ".gitattributes" || file === ".datalad/config") {
89+
continue
90+
}
91+
await git.remove({
92+
...context.config(),
93+
filepath: file,
94+
})
95+
const filePath = join(context.repoPath, file)
96+
if ((await context.fs.promises.lstat(filePath)).isSymbolicLink()) {
97+
await context.fs.promises.unlink(filePath)
98+
} else {
99+
await context.fs.promises.rm(filePath)
100+
}
101+
fileCount += 1
102+
}
103+
logger.info(`Cleared working tree (${fileCount} files removed)`)
104+
}
105+
79106
/**
80107
* Load or return a cache copy of .gitattributes
81108
*/
@@ -530,6 +557,8 @@ self.onmessage = (event: GitWorkerEvent) => {
530557
setupLogging(event.data.logLevel)
531558
} else if (event.data.command === "clone") {
532559
workQueue.enqueue(update)
560+
} else if (event.data.command === "clearWorktree") {
561+
workQueue.enqueue(clearWorktree)
533562
} else if (event.data.command === "add") {
534563
workQueue.enqueue(add, event)
535564
} else if (event.data.command === "commit") {

0 commit comments

Comments
 (0)