You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@opendal.apache.org by xu...@apache.org on 2026/10/26 20:12:45 UTC

(opendal-yinyang) branch xuanwo/managed-sync-cli updated (ddc26c7 -> 0262d3b)

This is an automated email from the ASF dual-hosted git repository.

Xuanwo pushed a change to branch xuanwo/managed-sync-cli
in repository https://gitbox.apache.org/repos/asf/opendal-yinyang.git


    from ddc26c7  docs: correct the Managed Sync offline-export scope
     add 24ee7d4  test: keep interleaved remote edits safe from a local run
     add 09713d0  test: adapt the interleaving regression to the inspection API
     add 4d87a66  fix: map publication conflicts, retire resolved work, complete inspection evidence
     add f94eb89  fix: initialize the work insertion sequence field
     add 44dbe49  fix: apply namespace-only receipts without adopting stale content
     add 59a51bb  test: keep interleaved content through a namespace-only rename receipt
     add 9a28867  fix: read work rows with the prepended sequence column
     new b00646c  merge: integrate artifact evidence and offline conflict-local export
     new 0262d3b  feat: project artifact evidence and export conflict-local offline

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 specs/directory-sync.md  | 103 ++++++++++
 specs/linux-sync.md      |  12 +-
 src/replica/directory.rs | 486 ++++++++++++++++++++++++++++++++++++++---------
 src/replica/linux.rs     |  52 +++--
 src/replica/mod.rs       |   2 +-
 src/replica/state.rs     | 112 ++++++++---
 src/sync_cli.rs          |  48 ++---
 tests/directory_sync.rs  | 401 +++++++++++++++++++++++++++++++++++++-
 8 files changed, 1045 insertions(+), 171 deletions(-)
 create mode 100644 specs/directory-sync.md


(opendal-yinyang) 02/02: feat: project artifact evidence and export conflict-local offline

Posted by xu...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

Xuanwo pushed a commit to branch xuanwo/managed-sync-cli
in repository https://gitbox.apache.org/repos/asf/opendal-yinyang.git

commit 0262d3b6d442a5cd8b7bda78352bcdc7ef0274a3
Author: Xuanwo <gi...@xuanwo.io>
AuthorDate: Tue Oct 27 04:12:39 2026 +0800

    feat: project artifact evidence and export conflict-local offline
    
    Use the domain artifact `path`/`exportable` directly instead of
    deriving the quarantine layout, and route `export --conflict --side local`
    through the authority-free `replica::export_conflict_local`. Only a
    conflict's remote side still needs the authority. Update the Linux
    Managed Sync specification to match.
    
    Co-authored-by: Chojan Shang <ps...@apache.org>
---
 specs/linux-sync.md | 12 ++++++------
 src/sync_cli.rs     | 48 ++++++++++++++++++++++++------------------------
 2 files changed, 30 insertions(+), 30 deletions(-)

diff --git a/specs/linux-sync.md b/specs/linux-sync.md
index 4ebcc56..2ba0d14 100644
--- a/specs/linux-sync.md
+++ b/specs/linux-sync.md
@@ -77,10 +77,10 @@ decide whether to retry.
 `status` and `export --artifact` work without remote connectivity. `status`
 classifies the local binding first and reports remote availability truthfully,
 marking it unavailable with the real connection error when the authority cannot
-be reached; it never fabricates success. `export --artifact` reads retained
-bytes from the local replica and never contacts the authority. `export
---conflict` currently connects to the authority, because the remote side reads
-a retained revision.
+be reached; it never fabricates success. `export --artifact` and `export
+--conflict --side local` read durable local bytes and never contact the
+authority. `export --conflict --side remote` reads a retained revision and
+needs the authority.
 
 ## Status document
 
@@ -165,5 +165,5 @@ yy --volume sync.json sync status --json
 
 `sync` is implemented only on Linux and drives an ordinary directory; it does
 not provide macOS File Provider integration, an automatic watcher or a daemon.
-Retained-artifact export is offline; conflict-side export currently needs the
-authority.
+A retained artifact's bytes and a conflict's local side are exported offline; a
+conflict's remote side needs the authority.
diff --git a/src/sync_cli.rs b/src/sync_cli.rs
index bd13be1..0b77bad 100644
--- a/src/sync_cli.rs
+++ b/src/sync_cli.rs
@@ -531,14 +531,12 @@ async fn export(
         // Retained bytes are local; export must not require remote connectivity.
         export_artifact_local(config, id, &mut file).await
     } else {
-        export_conflict(
-            config,
-            operator,
-            conflict.as_deref().expect("conflict selector present"),
-            side.expect("conflict side present").as_str(),
-            &mut file,
-        )
-        .await
+        let id = conflict.as_deref().expect("conflict selector present");
+        match side.expect("conflict side present") {
+            // The local side is durable local bytes; no authority is needed.
+            SyncSide::Local => export_conflict_local(config, id, &mut file),
+            SyncSide::Remote => export_conflict_remote(config, operator, id, &mut file).await,
+        }
     };
     drop(file);
     if let Err(error) = outcome {
@@ -568,13 +566,22 @@ async fn export_artifact_local(
     Ok(())
 }
 
-/// Exports one side of a conflict. The remote side reads the retained revision,
-/// so this path needs the publication authority.
-async fn export_conflict(
+/// Exports a conflict's local side through the authority-free local reader.
+fn export_conflict_local(
+    config: &VolumeConfig,
+    id: &str,
+    output: &mut dyn std::io::Write,
+) -> Result<(), Box<dyn std::error::Error>> {
+    yinyang::replica::export_conflict_local(&config.staging, id, output).map_err(fatal)?;
+    Ok(())
+}
+
+/// Exports a conflict's remote side. It reads a retained revision, so this path
+/// needs the publication authority.
+async fn export_conflict_remote(
     config: &VolumeConfig,
     operator: opendal::Operator,
     id: &str,
-    side: &str,
     output: &mut dyn std::io::Write,
 ) -> Result<(), Box<dyn std::error::Error>> {
     let authority = connect(config, operator).await?;
@@ -582,7 +589,7 @@ async fn export_conflict(
         .await
         .map_err(fatal)?;
     directory
-        .export_conflict_side(id, side, output)
+        .export_conflict_side(id, "remote", output)
         .await
         .map_err(fatal)?;
     Ok(())
@@ -666,7 +673,7 @@ fn project(inspection: &domain::Inspection) -> Result<SyncStatus, String> {
     let artifacts = inspection
         .artifacts
         .iter()
-        .map(|artifact| project_artifact(artifact, &inspection.binding.state_directory))
+        .map(project_artifact)
         .collect::<Result<Vec<_>, _>>()?;
     Ok(SyncStatus {
         schema: SyncStatus::SCHEMA.to_owned(),
@@ -869,7 +876,7 @@ fn conflict_side(side: &str) -> ConflictSide {
     }
 }
 
-fn project_artifact(artifact: &domain::Artifact, state: &Path) -> Result<ArtifactRecord, String> {
+fn project_artifact(artifact: &domain::Artifact) -> Result<ArtifactRecord, String> {
     let kind = match artifact.kind.as_str() {
         "replaced-file" => ArtifactKind::ReplacedFile,
         "rollback-displaced" => ArtifactKind::RollbackDisplaced,
@@ -892,15 +899,8 @@ fn project_artifact(artifact: &domain::Artifact, state: &Path) -> Result<Artifac
         origin: artifact.origin.clone(),
         kind,
         phase,
-        // Retained bytes live under the state directory's quarantine. The
-        // domain record exposes the file name; the adapter composes the public
-        // path the operator and export use.
-        path: state
-            .join("quarantine")
-            .join(&artifact.name)
-            .display()
-            .to_string(),
-        exportable: kind != ArtifactKind::QuarantinedDirectory,
+        path: artifact.path.display().to_string(),
+        exportable: artifact.exportable,
         error: artifact.error.clone(),
     })
 }


(opendal-yinyang) 01/02: merge: integrate artifact evidence and offline conflict-local export

Posted by xu...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

Xuanwo pushed a commit to branch xuanwo/managed-sync-cli
in repository https://gitbox.apache.org/repos/asf/opendal-yinyang.git

commit b00646cd8c2b63919c9f89bc007aca4df0cc808e
Merge: ddc26c7 9a28867
Author: Xuanwo <gi...@xuanwo.io>
AuthorDate: Tue Oct 27 04:11:31 2026 +0800

    merge: integrate artifact evidence and offline conflict-local export
    
    Take G's canonical artifact path/exportability and the authority-free
    local conflict export, so the CLI stops deriving layout and can export a
    conflict's local side offline.
    
    Co-authored-by: Chojan Shang <ps...@apache.org>

 specs/directory-sync.md  | 103 ++++++++++
 src/replica/directory.rs | 486 ++++++++++++++++++++++++++++++++++++++---------
 src/replica/linux.rs     |  52 +++--
 src/replica/mod.rs       |   2 +-
 src/replica/state.rs     | 112 ++++++++---
 tests/directory_sync.rs  | 401 +++++++++++++++++++++++++++++++++++++-
 6 files changed, 1015 insertions(+), 141 deletions(-)