def _check_can_merge(self, out): if self.scheme != out.scheme: raise MergeError("unable to auto-merge outputs of different types") my = self.dumpd() other = out.dumpd() ignored = [ self.fs.PARAM_CHECKSUM, HashInfo.PARAM_SIZE, HashInfo.PARAM_NFILES, ] for opt in ignored: my.pop(opt, None) other.pop(opt, None) if my != other: raise MergeError( "unable to auto-merge outputs with different options" ) if not out.is_dir_checksum: raise MergeError( "unable to auto-merge outputs that are not directories" )
def _check_can_merge(stage, ancestor_out=None): if isinstance(stage, PipelineStage): raise MergeError("unable to auto-merge pipeline stages") if not stage.is_data_source or stage.deps or len(stage.outs) > 1: raise MergeError("unable to auto-merge DVC files that weren't " "created by `dvc add`") if ancestor_out and not stage.outs: raise MergeError( "unable to auto-merge DVC files with deleted outputs")
def merge(self, ancestor, other): from dvc_data.objects.tree import MergeError as TreeMergeError from dvc_data.objects.tree import du, merge assert other if ancestor: self._check_can_merge(ancestor) ancestor_info = ancestor.hash_info else: ancestor_info = None self._check_can_merge(self) self._check_can_merge(other) try: merged = merge( self.odb, ancestor_info, self.hash_info, other.hash_info ) except TreeMergeError as exc: raise MergeError(str(exc)) from exc self.odb.add(merged.path, merged.fs, merged.oid) self.hash_info = merged.hash_info self.meta = Meta( size=du(self.odb, merged), nfiles=len(merged), )
def _check_can_merge(self, out): if self.scheme != out.scheme: raise MergeError("unable to auto-merge outputs of different types") my = self.dumpd() other = out.dumpd() my.pop(self.tree.PARAM_CHECKSUM) other.pop(self.tree.PARAM_CHECKSUM) if my != other: raise MergeError( "unable to auto-merge outputs with different options") if not out.is_dir_checksum: raise MergeError( "unable to auto-merge outputs that are not directories")
def _diff(ancestor, other, allow_removed=False): from dictdiffer import diff allowed = ["add"] if allow_removed: allowed.append("remove") result = list(diff(ancestor, other)) for typ, _, _ in result: if typ not in allowed: raise MergeError( "unable to auto-merge directories with diff that contains " f"'{typ}'ed files") return result