Skip to contents

rfp_mergin_list() reports has_conflict per project, straight from the server. That is the right signal for "does this project need attention" and the wrong one for "is it safe to read this file", because it cannot distinguish a conflict over an empty rebuilt form from one holding a season's records. This resolves it to the file level.

Usage

rfp_mergin_conflicts(project, version = NULL)

Arguments

project

Character. namespace/project.

version

Character. "vN", or NULL (default) for HEAD.

Value

Tibble with one row per conflicted copy: path (the copy), base_path (the file it is a copy of), base_present (whether the project still holds that file at this version), author, version (the version the author diverged from), and size, checksum and mtime passed through from the listing. Zero rows, with those columns, when there are no conflicts.

Details

Measured on newgraph/restoration_wedzin_kwa v112: the project reports has_conflict = TRUE and carries eight conflicted copies, of which the four current-season ones are empty. A consumer failing closed on the project flag refuses to read the project over four empty files; one ignoring it silently drops whatever a populated conflict holds. Knowing which files is the only thing between those two.

What is and is not derived from the server

The candidate set comes from rfp_mergin_files() - the server's own listing at a given version - rather than from a walk of somebody's clone, which is what makes this usable without one.

The parse is a regular expression, because there is no structured field to read: a conflicted copy is an ordinary file whose name encodes its author and divergence version. So the claim here is not that a regex is avoided, it is that the pattern is anchored to Mergin's actual naming and has a tested negative case - as against matching the substring "conflicted", which a file legitimately named notes (conflicted requirements).md also satisfies.

Two details that make the difference between a working guard and one that silently never fires:

  • The extension is on the far side of the parenthetical. Stripping from " (conflicted copy" onwards turns form_vri_qa (conflicted copy, u v95).gpkg into form_vri_qa, which never matches the form_vri_qa.gpkg a caller is about to read. It is reattached here.

  • Matching is on the full path, not the basename, so a stale conflict under data_field/2023/archive/ cannot be mistaken for one over a same-named file at the project root.

What this does not tell you

Whether the conflicted copy holds any records. The file listing carries a size and no row count, and none is derivable - an empty 53-column GeoPackage is a nonzero and unpredictable size. Deciding that means fetching the file with rfp_mergin_file_get() and opening it, which is the caller's call to make: a listing function that quietly starts transferring files is a worse thing to have than an extra step.

Examples

if (FALSE) { # \dontrun{
cf <- rfp_mergin_conflicts("newgraph/restoration_wedzin_kwa")

# Is anything in conflict with a file I am about to read?
cf[cf$base_path %in% c("form_vri_qa.gpkg", "form_edna.gpkg"), ]
} # }