diff --git a/src/core/opamFilename.ml b/src/core/opamFilename.ml index e97de1df57b..5ea7f84c65e 100644 --- a/src/core/opamFilename.ml +++ b/src/core/opamFilename.ml @@ -813,4 +813,19 @@ module Unix = struct let of_filename x = OpamSystem.back_to_forward (concat x.dirname x.basename) let to_filename x = {dirname = dirname x; basename = basename x} + + let to_relative_canonical_list x = + if Filename.is_relative x then + match String.split_on_char '/' x with + | [] | ""::_::_ -> assert false + | [""] -> [current_dir_name] + | x -> + List.filter (fun seg -> + if seg = ".." then + invalid_arg "'..' is forbidden" + else + seg <> "" && not (String.equal current_dir_name seg)) + x + else + invalid_arg "not relative" end diff --git a/src/core/opamFilename.mli b/src/core/opamFilename.mli index c20cafc3edc..6a21da0e458 100644 --- a/src/core/opamFilename.mli +++ b/src/core/opamFilename.mli @@ -426,4 +426,6 @@ module Unix : sig val of_filename : filename -> t val to_filename : t -> filename + + val to_relative_canonical_list : t -> string list end diff --git a/src/repository/opamRepositoryPath.ml b/src/repository/opamRepositoryPath.ml index ccc79df1bbb..71675839f6c 100644 --- a/src/repository/opamRepositoryPath.ml +++ b/src/repository/opamRepositoryPath.ml @@ -53,6 +53,29 @@ let url repo_root prefix nv = let files repo_root prefix nv = packages repo_root prefix nv / "files" +let get_pkg_dir file = + let rec find_pkg_rev prefix_files = function + | x::xs -> + begin match OpamPackage.of_string_opt x with + | Some nv -> Some (nv, x::prefix_files) + | None -> find_pkg_rev (x::prefix_files) xs + end + | [] -> None + in + match OpamFilename.Unix.to_relative_canonical_list file with + | "packages"::xs -> + begin match find_pkg_rev [] xs with + | Some (nv, full_rev_prefix) -> + let dir = + List.rev full_rev_prefix + |> List.fold_left OpamFilename.Unix.Op.(/) + (OpamFilename.Unix.Dir.of_string "packages") + in + Some (nv, dir) + | None -> None + end + | _ -> None + module Remote = struct (** URL, not FS paths *) open OpamUrl.Op diff --git a/src/repository/opamRepositoryPath.mli b/src/repository/opamRepositoryPath.mli index 19a8a576390..56df9b6d330 100644 --- a/src/repository/opamRepositoryPath.mli +++ b/src/repository/opamRepositoryPath.mli @@ -51,6 +51,17 @@ val url: dirname -> string option -> package -> OpamFile.URL_legacy.t OpamFile.t (** files {i $repo/packages/XXX/$NAME.$VERSION/files} *) val files: dirname -> string option -> package -> dirname +(** [get_pkg_dir f] returns the pair of package and directory [(p, d)], + where [d] is a prefix of [f], that matches a repository package folder. + [p] is the pair [nv] associated with that folder. + It returns [None] if no folder was detected. + + Note: [f] must always be a relative filename starting at a repository root. + + For example, [get_pkg_dir packages/a/a.1/files/extrafile] will return + [(a.1, packages/a/a.1)]. *) +val get_pkg_dir : unix_filename -> (package * unix_dirname) option + (** Url constructor for parts of remote repositories, when applicable (http and rsync). Function take the repo's root url. *) module Remote: sig diff --git a/src/state/opamRepositoryState.ml b/src/state/opamRepositoryState.ml index eff38dff0fc..c41fe27e498 100644 --- a/src/state/opamRepositoryState.ml +++ b/src/state/opamRepositoryState.ml @@ -101,17 +101,7 @@ let get_repo_files rt name dir = let read_package_opam ~repo_name ~repo_root package_dir = match OpamFileTools.read_repo_opam ~repo_name ~repo_root package_dir with - | Some opam -> - (try - let nv = - OpamPackage.of_string - (OpamFilename.Base.to_string (OpamFilename.basename_dir package_dir)) - in - Some (nv, opam) - with Failure _ -> - log "ERR: directory name not a valid package: ignored %s" - (OpamFilename.to_string OpamFilename.Op.(package_dir // "opam")); - None) + | Some opam -> Some opam | None -> log "ERR: Could not load %s, ignored" (OpamFilename.to_string OpamFilename.Op.(package_dir // "opam")); @@ -123,25 +113,33 @@ let load_opams_from_dir repo_name repo_root = (OpamConsole.colorise `blue (OpamRepositoryName.to_string repo_name)); (* FIXME: why is this different from OpamPackage.list ? *) let rec aux r dir = - if OpamFilename.exists_dir dir then - let fnames = Sys.readdir (OpamFilename.Dir.to_string dir) in - if Array.exists (fun f -> f = "opam") fnames then - match read_package_opam ~repo_name ~repo_root dir with - | Some (nv, opam) -> OpamPackage.Map.add nv opam r + let full_path = + OpamFilename.Op.(repo_root / OpamFilename.Unix.Dir.to_string dir) + in + if OpamFilename.exists_dir full_path then + match OpamRepositoryPath.get_pkg_dir OpamFilename.Unix.Op.(dir // "") with + | Some (nv, _pkg_dir) -> + (* NOTE: we ignore [pkg_dir] because load_opams_from_dir + will always scan parent directories before going deeper *) + begin match read_package_opam ~repo_name ~repo_root full_path with + | Some opam -> OpamPackage.Map.add nv opam r | None -> r - else - Array.fold_left (fun r name -> aux r OpamFilename.Op.(dir / name)) - r fnames + end + | None -> + Array.fold_left (fun r name -> aux r OpamFilename.Unix.Op.(dir / name)) + r (Sys.readdir (OpamFilename.Dir.to_string full_path)) else r in Fun.protect - (fun () -> aux OpamPackage.Map.empty (OpamRepositoryPath.packages_dir repo_root)) + (fun () -> + aux OpamPackage.Map.empty (OpamFilename.Unix.Dir.of_string "packages")) ~finally:OpamConsole.clear_status let load_opams_from_diff repo diffs rt = if OpamConsole.disp_status_line () || OpamConsole.verbose () then OpamConsole.status_line "Processing: [%s: loading data]" - (OpamConsole.colorise `blue (OpamRepositoryName.to_string repo.repo_name)); + (OpamConsole.colorise `blue + (OpamRepositoryName.to_string repo.repo_name)); let existing_opams = OpamRepositoryName.Map.find repo.repo_name rt.repo_opams in @@ -149,45 +147,38 @@ let load_opams_from_diff repo diffs rt = (* processed_dirs: used to avoid re-read in case of diff generated by extra files. added_pkgs: used to skip removing version-equivalent packages *) let process_file (opams, processed_dirs, added_pkgs) file ~is_removal = - let pkg_dir = - let file = OpamFilename.raw file in - let dirname = OpamFilename.dirname file in - let basename = OpamFilename.basename_dir dirname in - let full_path = - Filename.concat - (OpamFilename.Dir.to_string repo_root) - (OpamFilename.Dir.to_string dirname) - in - if OpamFilename.Base.to_string basename = "files" then - OpamFilename.Dir.of_string (Filename.dirname full_path) - else - OpamFilename.Dir.of_string full_path - in - if OpamFilename.Dir.Set.mem pkg_dir processed_dirs then + match OpamRepositoryPath.get_pkg_dir file with + | None -> + log "ERR: file name not a valid package: ignored %s" + (OpamFilename.Unix.to_string file); opams, processed_dirs, added_pkgs - else - let processed_dirs = OpamFilename.Dir.Set.add pkg_dir processed_dirs in - match read_package_opam ~repo_name:repo.repo_name ~repo_root pkg_dir with - | Some (nv, opam) -> - let added_pkgs = OpamPackage.Set.add nv added_pkgs in - OpamPackage.Map.add nv opam opams, processed_dirs, added_pkgs - | None -> - if is_removal then - match OpamPackage.of_dirname pkg_dir with - | None -> - log "ERR: directory name not a valid package: ignored %s" - (OpamFilename.Dir.to_string pkg_dir); - opams, processed_dirs, added_pkgs - | Some nv -> + | Some (nv, pkg_dir) -> + if OpamFilename.Unix.Dir.Set.mem pkg_dir processed_dirs then + opams, processed_dirs, added_pkgs + else + let processed_dirs = OpamFilename.Unix.Dir.Set.add pkg_dir processed_dirs in + let full_path = + OpamFilename.Op.(repo_root / OpamFilename.Unix.Dir.to_string pkg_dir) + in + match read_package_opam ~repo_name:repo.repo_name ~repo_root full_path with + | Some opam -> + let added_pkgs = OpamPackage.Set.add nv added_pkgs in + OpamPackage.Map.add nv opam opams, processed_dirs, added_pkgs + | None -> + if is_removal then if OpamPackage.Set.mem nv added_pkgs then opams, processed_dirs, added_pkgs else OpamPackage.Map.remove nv opams, processed_dirs, added_pkgs - else - opams, processed_dirs, added_pkgs + else + opams, processed_dirs, added_pkgs + in + let remove_file file acc = + process_file acc (OpamFilename.Unix.of_string file) ~is_removal:true + in + let add_file file acc = + process_file acc (OpamFilename.Unix.of_string file) ~is_removal:false in - let remove_file file acc = process_file acc file ~is_removal:true in - let add_file file acc = process_file acc file ~is_removal:false in let process_operation acc = function | Patch.Edit (old_file, new_file) -> if String.equal old_file new_file @@ -207,7 +198,9 @@ let load_opams_from_diff repo diffs rt = (fun () -> let opams, _, _ = List.fold_left process_operation - (existing_opams, OpamFilename.Dir.Set.empty, OpamPackage.Set.empty) + (existing_opams, + OpamFilename.Unix.Dir.Set.empty, + OpamPackage.Set.empty) diffs in opams) diff --git a/tests/reftests/dune.inc b/tests/reftests/dune.inc index 2033956de02..6374d6dd796 100644 --- a/tests/reftests/dune.inc +++ b/tests/reftests/dune.inc @@ -1868,6 +1868,27 @@ %{targets} (run ./run.exe %{exe:../../src/client/opamMain.exe.exe} %{dep:remove.test} %{read-lines:testing-env})))) +(rule + (alias reftest-repository-formats) + (enabled_if (and (or (<> %{env:TESTALL=1} 0) (= %{env:TESTN0REP0=0} 1)))) + (action + (diff repository-formats.test repository-formats.out))) + +(alias + (name reftest) + (enabled_if (and (or (<> %{env:TESTALL=1} 0) (= %{env:TESTN0REP0=0} 1)))) + (deps (alias reftest-repository-formats))) + +(rule + (targets repository-formats.out) + (deps root-N0REP0) + (enabled_if (and (or (<> %{env:TESTALL=1} 0) (= %{env:TESTN0REP0=0} 1)))) + (package opam) + (action + (with-stdout-to + %{targets} + (run ./run.exe %{exe:../../src/client/opamMain.exe.exe} %{dep:repository-formats.test} %{read-lines:testing-env})))) + (rule (alias reftest-repository-patchdiff) (enabled_if (and (or (<> %{env:TESTALL=1} 0) (= %{env:TESTN0REP0=0} 1)))) diff --git a/tests/reftests/repository-formats.test b/tests/reftests/repository-formats.test new file mode 100644 index 00000000000..a34caf0d243 --- /dev/null +++ b/tests/reftests/repository-formats.test @@ -0,0 +1,628 @@ +N0REP0 +### opam repository add default-strict ./REPO +[WARNING] No switch is currently set, perhaps you meant '--set-default'? +[default-strict] Initialised +[ERROR] No switch is currently set. Please use 'opam switch' to set or install a switch +# Return code 50 # +### +I'm the root one +### +I'm the second one, in a directory +### openssl md5 fst | '.*= ' -> '' >$ FST_MD5 +### openssl md5 snd | '.*= ' -> '' >$ SND_MD5 +### +set -eu +path="REPO/$1" +files="$path/files" +under="un/der" +innerfiles="$files/$under" +mkdir -p "$innerfiles" +cp fst "$files/" +cp snd "$innerfiles/" +cat > "$path/opam" << EOF +opam-version: "2.0" +extra-files: [ + ["fst" "md5=$FST_MD5"] + ["$under/snd" "md5=$SND_MD5"] +] +build: [ + [ "test" "-f" "fst" ] + [ "test" "-f" "$under/snd" ] +] +EOF +### +set -ue +n="$1" +path="REPO/$2" +cat >> "$path/opam" << EOF +name: "$n" +version: "1" +EOF +### sh populate.sh packages/good/good.1 +### sh populate.sh packages/not/no-n-nv.1 +### sh populate.sh packages/ba/baz/n-nv-not-root.1 +### sh populate.sh packages/v/e/r/y/very-inner.1 +### sh populate.sh packages/i/n/e/r/very-inned-n-nv/very-inner-n-nv.1 +### sh populate.sh packages/direct-root.1 +### sh populate.sh packages/no-nv +### sh add-nv.sh no-nv packages/no-nv +### sh populate.sh root-no-nv +### sh add-nv.sh root-no-nv root-no-nv +### sh populate.sh packages/not-same-nv-in/not-same-nv-in.2 +### sh add-nv.sh different packages/not-same-nv-in/not-same-nv-in.2 +### sh populate.sh pkg/z-good/z-good.1 +### sh populate.sh pkg/z-not/z-no-n-nv.1 +### sh populate.sh pkg/z-ba/z-baz/z-n-nv-not-root.1 +### sh populate.sh pkg/z-v/z-e/z-r/z-y/z-very-inner.1 +### sh populate.sh pkg/z-i/z-n/z-e/z-r/z-very-inned-n-nv/z-very-inner-n-nv.1 +### sh populate.sh pkg/z-direct-root.1 +### sh populate.sh pkg/z-no-nv +### OPAMYES=1 OPAMSTRICT=0 +### opam sw cr --empty exotic-formats-update +### :I: update from dir (diff mode) +### OPAMDEBUGSECTIONS="FILE(opam) opam-file RSTATE UPDATE" OPAMDEBUG=-3 opam update default-strict --strict +FILE(config) Read ${BASEDIR}/OPAM/config in 0.000s +RSTATE LOAD-REPOSITORY-STATE @ ${BASEDIR}/OPAM +RSTATE Cache found + +<><> Updating package repositories ><><><><><><><><><><><><><><><><><><><><><><> +[default-strict] synchronised from file://${BASEDIR}/REPO +UPDATE Repository has new changes +FILE(opam) Read ${BASEDIR}/OPAM/repo/default-strict/packages/ba/baz/n-nv-not-root.1/opam in 0.000s +FILE(opam) Read ${BASEDIR}/OPAM/repo/default-strict/packages/direct-root.1/opam in 0.000s +FILE(opam) Read ${BASEDIR}/OPAM/repo/default-strict/packages/good/good.1/opam in 0.000s +FILE(opam) Read ${BASEDIR}/OPAM/repo/default-strict/packages/i/n/e/r/very-inned-n-nv/very-inner-n-nv.1/opam in 0.000s +RSTATE ERR: file name not a valid package: ignored packages/no-nv/opam +RSTATE ERR: file name not a valid package: ignored packages/no-nv/files/fst +RSTATE ERR: file name not a valid package: ignored packages/no-nv/files/un/der/snd +FILE(opam) Read ${BASEDIR}/OPAM/repo/default-strict/packages/not/no-n-nv.1/opam in 0.000s +[ERROR] In ${BASEDIR}/OPAM/repo/default-strict/packages/not-same-nv-in/not-same-nv-in.2/opam: + This file is for package 'not-same-nv-in.2' but has mismatching fields 'name:different 'version:1. +[ERROR] Strict mode: aborting +[ERROR] Could not update repository "default-strict": OpamStd.OpamSys.Exit(30) +# Return code 40 # +### OPAMDEBUGSECTIONS="FILE(opam) opam-file RSTATE UPDATE" OPAMDEBUG=-3 opam update default +FILE(config) Read ${BASEDIR}/OPAM/config in 0.000s +RSTATE LOAD-REPOSITORY-STATE @ ${BASEDIR}/OPAM +RSTATE Cache found + +<><> Updating package repositories ><><><><><><><><><><><><><><><><><><><><><><> +[default] synchronised from file://${BASEDIR}/REPO +UPDATE Repository has new changes +FILE(opam) Read ${BASEDIR}/OPAM/repo/default/packages/ba/baz/n-nv-not-root.1/opam in 0.000s +FILE(opam) Read ${BASEDIR}/OPAM/repo/default/packages/direct-root.1/opam in 0.000s +FILE(opam) Read ${BASEDIR}/OPAM/repo/default/packages/good/good.1/opam in 0.000s +FILE(opam) Read ${BASEDIR}/OPAM/repo/default/packages/i/n/e/r/very-inned-n-nv/very-inner-n-nv.1/opam in 0.000s +RSTATE ERR: file name not a valid package: ignored packages/no-nv/opam +RSTATE ERR: file name not a valid package: ignored packages/no-nv/files/fst +RSTATE ERR: file name not a valid package: ignored packages/no-nv/files/un/der/snd +FILE(opam) Read ${BASEDIR}/OPAM/repo/default/packages/not/no-n-nv.1/opam in 0.000s +FILE(opam) Read ${BASEDIR}/OPAM/repo/default/packages/not-same-nv-in/not-same-nv-in.2/opam in 0.000s +FILE(opam) Read ${BASEDIR}/OPAM/repo/default/packages/v/e/r/y/very-inner.1/opam in 0.000s +RSTATE ERR: file name not a valid package: ignored pkg/z-no-nv/opam +RSTATE ERR: file name not a valid package: ignored pkg/z-no-nv/files/fst +RSTATE ERR: file name not a valid package: ignored pkg/z-no-nv/files/un/der/snd +RSTATE ERR: file name not a valid package: ignored pkg/z-direct-root.1/opam +RSTATE ERR: file name not a valid package: ignored pkg/z-direct-root.1/files/fst +RSTATE ERR: file name not a valid package: ignored pkg/z-direct-root.1/files/un/der/snd +RSTATE ERR: file name not a valid package: ignored pkg/z-i/z-n/z-e/z-r/z-very-inned-n-nv/z-very-inner-n-nv.1/opam +RSTATE ERR: file name not a valid package: ignored pkg/z-i/z-n/z-e/z-r/z-very-inned-n-nv/z-very-inner-n-nv.1/files/fst +RSTATE ERR: file name not a valid package: ignored pkg/z-i/z-n/z-e/z-r/z-very-inned-n-nv/z-very-inner-n-nv.1/files/un/der/snd +RSTATE ERR: file name not a valid package: ignored pkg/z-v/z-e/z-r/z-y/z-very-inner.1/opam +RSTATE ERR: file name not a valid package: ignored pkg/z-v/z-e/z-r/z-y/z-very-inner.1/files/fst +RSTATE ERR: file name not a valid package: ignored pkg/z-v/z-e/z-r/z-y/z-very-inner.1/files/un/der/snd +RSTATE ERR: file name not a valid package: ignored pkg/z-ba/z-baz/z-n-nv-not-root.1/opam +RSTATE ERR: file name not a valid package: ignored pkg/z-ba/z-baz/z-n-nv-not-root.1/files/fst +RSTATE ERR: file name not a valid package: ignored pkg/z-ba/z-baz/z-n-nv-not-root.1/files/un/der/snd +RSTATE ERR: file name not a valid package: ignored pkg/z-not/z-no-n-nv.1/opam +RSTATE ERR: file name not a valid package: ignored pkg/z-not/z-no-n-nv.1/files/fst +RSTATE ERR: file name not a valid package: ignored pkg/z-not/z-no-n-nv.1/files/un/der/snd +RSTATE ERR: file name not a valid package: ignored pkg/z-good/z-good.1/opam +RSTATE ERR: file name not a valid package: ignored pkg/z-good/z-good.1/files/fst +RSTATE ERR: file name not a valid package: ignored pkg/z-good/z-good.1/files/un/der/snd +RSTATE ERR: file name not a valid package: ignored root-no-nv/opam +RSTATE ERR: file name not a valid package: ignored root-no-nv/files/fst +RSTATE ERR: file name not a valid package: ignored root-no-nv/files/un/der/snd +Now run 'opam upgrade' to apply any package updates. +### : list all +### opam list -A +# Packages matching: any +# Name # Installed # Synopsis +direct-root -- +good -- +n-nv-not-root -- +no-n-nv -- +not-same-nv-in -- +very-inner -- +very-inner-n-nv -- +### : install all +### opam install good.1 +The following actions will be performed: +=== install 1 package + - install good 1 + +<><> Processing actions <><><><><><><><><><><><><><><><><><><><><><><><><><><><> +-> installed good.1 +Done. +### opam install no-n-nv.1 +The following actions will be performed: +=== install 1 package + - install no-n-nv 1 + +<><> Processing actions <><><><><><><><><><><><><><><><><><><><><><><><><><><><> +-> installed no-n-nv.1 +Done. +### opam install n-nv-not-root.1 +The following actions will be performed: +=== install 1 package + - install n-nv-not-root 1 + +<><> Processing actions <><><><><><><><><><><><><><><><><><><><><><><><><><><><> +-> installed n-nv-not-root.1 +Done. +### opam install very-inner.1 +The following actions will be performed: +=== install 1 package + - install very-inner 1 + +<><> Processing actions <><><><><><><><><><><><><><><><><><><><><><><><><><><><> +-> installed very-inner.1 +Done. +### opam install very-inner-n-nv.1 +The following actions will be performed: +=== install 1 package + - install very-inner-n-nv 1 + +<><> Processing actions <><><><><><><><><><><><><><><><><><><><><><><><><><><><> +-> installed very-inner-n-nv.1 +Done. +### opam install direct-root.1 +The following actions will be performed: +=== install 1 package + - install direct-root 1 + +<><> Processing actions <><><><><><><><><><><><><><><><><><><><><><><><><><><><> +-> installed direct-root.1 +Done. +### opam install no-nv +[ERROR] No package named no-nv found. +# Return code 5 # +### opam install root-no-nv +[ERROR] No package named root-no-nv found. +# Return code 5 # +### opam install not-same-nv-in.2 +The following actions will be performed: +=== install 1 package + - install not-same-nv-in 2 + +<><> Processing actions <><><><><><><><><><><><><><><><><><><><><><><><><><><><> +-> installed not-same-nv-in.2 +Done. +### opam install z-good.1 +[ERROR] No package named z-good found. +# Return code 5 # +### opam install z-no-n-nv.1 +[ERROR] No package named z-no-n-nv found. +# Return code 5 # +### opam install z-n-nv-not-root.1 +[ERROR] No package named z-n-nv-not-root found. +# Return code 5 # +### opam install z-very-inner.1 +[ERROR] No package named z-very-inner found. +# Return code 5 # +### opam install z-very-inner-n-nv.1 +[ERROR] No package named z-very-inner-n-nv found. +# Return code 5 # +### opam install z-direct-root.1 +[ERROR] No package named z-direct-root found. +# Return code 5 # +### opam install z-no-nv +[ERROR] No package named z-no-nv found. +# Return code 5 # +### :II: update from void (dir mode) +### opam sw cr --empty exotic-formats-from-scratch +### OPAMDEBUGSECTIONS="FILE(opam) opam-file RSTATE UPDATE" OPAMDEBUG=-3 opam repository add new-default-strict ./REPO --this-switch --strict +FILE(config) Read ${BASEDIR}/OPAM/config in 0.000s +RSTATE LOAD-REPOSITORY-STATE @ ${BASEDIR}/OPAM +RSTATE Cache found +[new-default-strict] Initialised +UPDATE Repository has new changes +[ERROR] In ${BASEDIR}/OPAM/repo/new-default-strict/packages/not-same-nv-in/not-same-nv-in.2/opam: + This file is for package 'not-same-nv-in.2' but has mismatching fields 'name:different 'version:1. +[ERROR] Strict mode: aborting +[ERROR] Could not update repository "new-default-strict": OpamStd.OpamSys.Exit(30) +[ERROR] Initial repository fetch failed +# Return code 40 # +### OPAMDEBUGSECTIONS="FILE(opam) opam-file RSTATE UPDATE" OPAMDEBUG=-3 opam repository add new-default ./REPO --this-switch | unordered +FILE(config) Read ${BASEDIR}/OPAM/config in 0.000s +RSTATE LOAD-REPOSITORY-STATE @ ${BASEDIR}/OPAM +RSTATE Cache found +[new-default] Initialised +UPDATE Repository has new changes +FILE(opam) Read ${BASEDIR}/OPAM/repo/new-default/packages/not-same-nv-in/not-same-nv-in.2/opam in 0.000s +FILE(opam) Read ${BASEDIR}/OPAM/repo/new-default/packages/direct-root.1/opam in 0.000s +FILE(opam) Read ${BASEDIR}/OPAM/repo/new-default/packages/i/n/e/r/very-inned-n-nv/very-inner-n-nv.1/opam in 0.000s +FILE(opam) Read ${BASEDIR}/OPAM/repo/new-default/packages/v/e/r/y/very-inner.1/opam in 0.000s +FILE(opam) Read ${BASEDIR}/OPAM/repo/new-default/packages/ba/baz/n-nv-not-root.1/opam in 0.000s +FILE(opam) Read ${BASEDIR}/OPAM/repo/new-default/packages/not/no-n-nv.1/opam in 0.000s +FILE(opam) Read ${BASEDIR}/OPAM/repo/new-default/packages/good/good.1/opam in 0.000s +### : list all +### opam list -A +# Packages matching: any +# Name # Installed # Synopsis +direct-root -- +good -- +n-nv-not-root -- +no-n-nv -- +not-same-nv-in -- +very-inner -- +very-inner-n-nv -- +### : install all +### opam install good.1 +The following actions will be performed: +=== install 1 package + - install good 1 + +<><> Processing actions <><><><><><><><><><><><><><><><><><><><><><><><><><><><> +-> installed good.1 +Done. +### opam install no-n-nv.1 +The following actions will be performed: +=== install 1 package + - install no-n-nv 1 + +<><> Processing actions <><><><><><><><><><><><><><><><><><><><><><><><><><><><> +-> installed no-n-nv.1 +Done. +### opam install n-nv-not-root.1 +The following actions will be performed: +=== install 1 package + - install n-nv-not-root 1 + +<><> Processing actions <><><><><><><><><><><><><><><><><><><><><><><><><><><><> +-> installed n-nv-not-root.1 +Done. +### opam install very-inner.1 +The following actions will be performed: +=== install 1 package + - install very-inner 1 + +<><> Processing actions <><><><><><><><><><><><><><><><><><><><><><><><><><><><> +-> installed very-inner.1 +Done. +### opam install very-inner-n-nv.1 +The following actions will be performed: +=== install 1 package + - install very-inner-n-nv 1 + +<><> Processing actions <><><><><><><><><><><><><><><><><><><><><><><><><><><><> +-> installed very-inner-n-nv.1 +Done. +### opam install direct-root.1 +The following actions will be performed: +=== install 1 package + - install direct-root 1 + +<><> Processing actions <><><><><><><><><><><><><><><><><><><><><><><><><><><><> +-> installed direct-root.1 +Done. +### opam install no-nv +[ERROR] No package named no-nv found. +# Return code 5 # +### opam install root-no-nv +[ERROR] No package named root-no-nv found. +# Return code 5 # +### opam install not-same-nv-in.2 +The following actions will be performed: +=== install 1 package + - install not-same-nv-in 2 + +<><> Processing actions <><><><><><><><><><><><><><><><><><><><><><><><><><><><> +-> installed not-same-nv-in.2 +Done. +### opam install not-same-nv-in.2 +[NOTE] Package not-same-nv-in is already installed (current version is 2). +### opam install z-good.1 +[ERROR] No package named z-good found. +# Return code 5 # +### opam install z-no-n-nv.1 +[ERROR] No package named z-no-n-nv found. +# Return code 5 # +### opam install z-n-nv-not-root.1 +[ERROR] No package named z-n-nv-not-root found. +# Return code 5 # +### opam install z-very-inner.1 +[ERROR] No package named z-very-inner found. +# Return code 5 # +### opam install z-very-inner-n-nv.1 +[ERROR] No package named z-very-inner-n-nv found. +# Return code 5 # +### opam install z-direct-root.1 +[ERROR] No package named z-direct-root found. +# Return code 5 # +### opam install z-no-nv +[ERROR] No package named z-no-nv found. +# Return code 5 # +### :III: Update only extra-files +### +yet another file, no longer ignored! +### openssl md5 thrd | '.*= ' -> '' >$ THRD_MD5 +### :III::1: first add in opam file +### +set -eu +path="REPO/$1" +files="$path/files" +under="un/der" +innerfiles="$files/$under" +cat > "$path/opam" << EOF +opam-version: "2.0" +extra-files: [ + ["fst" "md5=$FST_MD5"] + ["$under/snd" "md5=$SND_MD5"] + ["$under/thrd" "md5=$THRD_MD5"] +] +build: [ + [ "test" "-f" "fst" ] + [ "test" "-f" "$under/snd" ] + [ "test" "-f" "$under/thrd" ] +] +EOF +### sh xfile-opam.sh packages/good/good.1 +### sh xfile-opam.sh packages/not/no-n-nv.1 +### sh xfile-opam.sh packages/ba/baz/n-nv-not-root.1 +### sh xfile-opam.sh packages/v/e/r/y/very-inner.1 +### sh xfile-opam.sh packages/i/n/e/r/very-inned-n-nv/very-inner-n-nv.1 +### sh xfile-opam.sh packages/direct-root.1 +### sh xfile-opam.sh packages/no-nv +### sh add-nv.sh no-nv packages/no-nv +### sh xfile-opam.sh root-no-nv +### sh add-nv.sh root-no-nv root-no-nv +### sh xfile-opam.sh packages/not-same-nv-in/not-same-nv-in.2 +### sh add-nv.sh different packages/not-same-nv-in/not-same-nv-in.2 +### sh xfile-opam.sh pkg/z-good/z-good.1 +### sh xfile-opam.sh pkg/z-not/z-no-n-nv.1 +### sh xfile-opam.sh pkg/z-ba/z-baz/z-n-nv-not-root.1 +### sh xfile-opam.sh pkg/z-v/z-e/z-r/z-y/z-very-inner.1 +### sh xfile-opam.sh pkg/z-i/z-n/z-e/z-r/z-very-inned-n-nv/z-very-inner-n-nv.1 +### sh xfile-opam.sh pkg/z-direct-root.1 +### sh xfile-opam.sh pkg/z-no-nv +### OPAMDEBUGSECTIONS="FILE(opam) opam-file RSTATE UPDATE" OPAMDEBUG=-3 opam update default-strict --strict | unordered +FILE(config) Read ${BASEDIR}/OPAM/config in 0.000s +RSTATE LOAD-REPOSITORY-STATE @ ${BASEDIR}/OPAM +RSTATE Cache found + +<><> Updating package repositories ><><><><><><><><><><><><><><><><><><><><><><> +[default-strict] synchronised from file://${BASEDIR}/REPO +UPDATE Repository has new changes +FILE(opam) Read ${BASEDIR}/OPAM/repo/default-strict/packages/ba/baz/n-nv-not-root.1/opam in 0.000s +opam-file Mismatching extra-files at ${BASEDIR}/OPAM/repo/default-strict/packages/ba/baz/n-nv-not-root.1: missing from 'files' directory (1) +FILE(opam) Read ${BASEDIR}/OPAM/repo/default-strict/packages/direct-root.1/opam in 0.000s +opam-file Mismatching extra-files at ${BASEDIR}/OPAM/repo/default-strict/packages/direct-root.1: missing from 'files' directory (1) +FILE(opam) Read ${BASEDIR}/OPAM/repo/default-strict/packages/good/good.1/opam in 0.000s +opam-file Mismatching extra-files at ${BASEDIR}/OPAM/repo/default-strict/packages/good/good.1: missing from 'files' directory (1) +FILE(opam) Read ${BASEDIR}/OPAM/repo/default-strict/packages/i/n/e/r/very-inned-n-nv/very-inner-n-nv.1/opam in 0.000s +opam-file Mismatching extra-files at ${BASEDIR}/OPAM/repo/default-strict/packages/i/n/e/r/very-inned-n-nv/very-inner-n-nv.1: missing from 'files' directory (1) +RSTATE ERR: file name not a valid package: ignored packages/no-nv/opam +FILE(opam) Read ${BASEDIR}/OPAM/repo/default-strict/packages/not/no-n-nv.1/opam in 0.000s +opam-file Mismatching extra-files at ${BASEDIR}/OPAM/repo/default-strict/packages/not/no-n-nv.1: missing from 'files' directory (1) +[ERROR] In ${BASEDIR}/OPAM/repo/default-strict/packages/not-same-nv-in/not-same-nv-in.2/opam: + This file is for package 'not-same-nv-in.2' but has mismatching fields 'name:different 'version:1. +[ERROR] Strict mode: aborting +[ERROR] Could not update repository "default-strict": OpamStd.OpamSys.Exit(30) +# Return code 40 # +### OPAMDEBUGSECTIONS="FILE(opam) opam-file RSTATE UPDATE" OPAMDEBUG=-3 opam update default +FILE(config) Read ${BASEDIR}/OPAM/config in 0.000s +RSTATE LOAD-REPOSITORY-STATE @ ${BASEDIR}/OPAM +RSTATE Cache found + +<><> Updating package repositories ><><><><><><><><><><><><><><><><><><><><><><> +[default] synchronised from file://${BASEDIR}/REPO +UPDATE Repository has new changes +FILE(opam) Read ${BASEDIR}/OPAM/repo/default/packages/ba/baz/n-nv-not-root.1/opam in 0.000s +opam-file Mismatching extra-files at ${BASEDIR}/OPAM/repo/default/packages/ba/baz/n-nv-not-root.1: missing from 'files' directory (1) +FILE(opam) Read ${BASEDIR}/OPAM/repo/default/packages/direct-root.1/opam in 0.000s +opam-file Mismatching extra-files at ${BASEDIR}/OPAM/repo/default/packages/direct-root.1: missing from 'files' directory (1) +FILE(opam) Read ${BASEDIR}/OPAM/repo/default/packages/good/good.1/opam in 0.000s +opam-file Mismatching extra-files at ${BASEDIR}/OPAM/repo/default/packages/good/good.1: missing from 'files' directory (1) +FILE(opam) Read ${BASEDIR}/OPAM/repo/default/packages/i/n/e/r/very-inned-n-nv/very-inner-n-nv.1/opam in 0.000s +opam-file Mismatching extra-files at ${BASEDIR}/OPAM/repo/default/packages/i/n/e/r/very-inned-n-nv/very-inner-n-nv.1: missing from 'files' directory (1) +RSTATE ERR: file name not a valid package: ignored packages/no-nv/opam +FILE(opam) Read ${BASEDIR}/OPAM/repo/default/packages/not/no-n-nv.1/opam in 0.000s +opam-file Mismatching extra-files at ${BASEDIR}/OPAM/repo/default/packages/not/no-n-nv.1: missing from 'files' directory (1) +FILE(opam) Read ${BASEDIR}/OPAM/repo/default/packages/not-same-nv-in/not-same-nv-in.2/opam in 0.000s +opam-file Mismatching extra-files at ${BASEDIR}/OPAM/repo/default/packages/not-same-nv-in/not-same-nv-in.2: missing from 'files' directory (1) +FILE(opam) Read ${BASEDIR}/OPAM/repo/default/packages/v/e/r/y/very-inner.1/opam in 0.000s +opam-file Mismatching extra-files at ${BASEDIR}/OPAM/repo/default/packages/v/e/r/y/very-inner.1: missing from 'files' directory (1) +RSTATE ERR: file name not a valid package: ignored pkg/z-ba/z-baz/z-n-nv-not-root.1/opam +RSTATE ERR: file name not a valid package: ignored pkg/z-direct-root.1/opam +RSTATE ERR: file name not a valid package: ignored pkg/z-good/z-good.1/opam +RSTATE ERR: file name not a valid package: ignored pkg/z-i/z-n/z-e/z-r/z-very-inned-n-nv/z-very-inner-n-nv.1/opam +RSTATE ERR: file name not a valid package: ignored pkg/z-no-nv/opam +RSTATE ERR: file name not a valid package: ignored pkg/z-not/z-no-n-nv.1/opam +RSTATE ERR: file name not a valid package: ignored pkg/z-v/z-e/z-r/z-y/z-very-inner.1/opam +RSTATE ERR: file name not a valid package: ignored root-no-nv/opam +Now run 'opam upgrade' to apply any package updates. +### :III::2: then add the extrafiles +### +set -eu +path="REPO/$1" +files="$path/files" +under="un/der" +innerfiles="$files/$under" +cp thrd "$innerfiles/" +### sh xfile.sh packages/good/good.1 +### sh xfile.sh packages/not/no-n-nv.1 +### sh xfile.sh packages/ba/baz/n-nv-not-root.1 +### sh xfile.sh packages/v/e/r/y/very-inner.1 +### sh xfile.sh packages/i/n/e/r/very-inned-n-nv/very-inner-n-nv.1 +### sh xfile.sh packages/direct-root.1 +### sh xfile.sh packages/no-nv +### sh xfile.sh root-no-nv +### sh xfile.sh packages/not-same-nv-in/not-same-nv-in.2 +### sh xfile.sh pkg/z-good/z-good.1 +### sh xfile.sh pkg/z-not/z-no-n-nv.1 +### sh xfile.sh pkg/z-ba/z-baz/z-n-nv-not-root.1 +### sh xfile.sh pkg/z-v/z-e/z-r/z-y/z-very-inner.1 +### sh xfile.sh pkg/z-i/z-n/z-e/z-r/z-very-inned-n-nv/z-very-inner-n-nv.1 +### sh xfile.sh pkg/z-direct-root.1 +### sh xfile.sh pkg/z-no-nv +### OPAMDEBUGSECTIONS="FILE(opam) opam-file RSTATE UPDATE" OPAMDEBUG=-3 opam update default-strict --strict | unordered +FILE(config) Read ${BASEDIR}/OPAM/config in 0.000s +RSTATE LOAD-REPOSITORY-STATE @ ${BASEDIR}/OPAM +RSTATE Cache found + +<><> Updating package repositories ><><><><><><><><><><><><><><><><><><><><><><> +[default-strict] synchronised from file://${BASEDIR}/REPO +UPDATE Repository has new changes +FILE(opam) Read ${BASEDIR}/OPAM/repo/default-strict/packages/ba/baz/n-nv-not-root.1/opam in 0.000s +FILE(opam) Read ${BASEDIR}/OPAM/repo/default-strict/packages/direct-root.1/opam in 0.000s +FILE(opam) Read ${BASEDIR}/OPAM/repo/default-strict/packages/good/good.1/opam in 0.000s +FILE(opam) Read ${BASEDIR}/OPAM/repo/default-strict/packages/i/n/e/r/very-inned-n-nv/very-inner-n-nv.1/opam in 0.000s +RSTATE ERR: file name not a valid package: ignored packages/no-nv/files/un/der/thrd +FILE(opam) Read ${BASEDIR}/OPAM/repo/default-strict/packages/not/no-n-nv.1/opam in 0.000s +[ERROR] In ${BASEDIR}/OPAM/repo/default-strict/packages/not-same-nv-in/not-same-nv-in.2/opam: + This file is for package 'not-same-nv-in.2' but has mismatching fields 'name:different 'version:1. +[ERROR] Strict mode: aborting +[ERROR] Could not update repository "default-strict": OpamStd.OpamSys.Exit(30) +# Return code 40 # +### OPAMDEBUGSECTIONS="FILE(opam) opam-file RSTATE UPDATE" OPAMDEBUG=-3 opam update default | unordered +FILE(config) Read ${BASEDIR}/OPAM/config in 0.000s +RSTATE LOAD-REPOSITORY-STATE @ ${BASEDIR}/OPAM +RSTATE Cache found + +<><> Updating package repositories ><><><><><><><><><><><><><><><><><><><><><><> +[default] synchronised from file://${BASEDIR}/REPO +UPDATE Repository has new changes +FILE(opam) Read ${BASEDIR}/OPAM/repo/default/packages/ba/baz/n-nv-not-root.1/opam in 0.000s +FILE(opam) Read ${BASEDIR}/OPAM/repo/default/packages/direct-root.1/opam in 0.000s +FILE(opam) Read ${BASEDIR}/OPAM/repo/default/packages/good/good.1/opam in 0.000s +FILE(opam) Read ${BASEDIR}/OPAM/repo/default/packages/i/n/e/r/very-inned-n-nv/very-inner-n-nv.1/opam in 0.000s +RSTATE ERR: file name not a valid package: ignored packages/no-nv/files/un/der/thrd +FILE(opam) Read ${BASEDIR}/OPAM/repo/default/packages/not/no-n-nv.1/opam in 0.000s +FILE(opam) Read ${BASEDIR}/OPAM/repo/default/packages/not-same-nv-in/not-same-nv-in.2/opam in 0.000s +FILE(opam) Read ${BASEDIR}/OPAM/repo/default/packages/v/e/r/y/very-inner.1/opam in 0.000s +RSTATE ERR: file name not a valid package: ignored pkg/z-ba/z-baz/z-n-nv-not-root.1/files/un/der/thrd +RSTATE ERR: file name not a valid package: ignored pkg/z-direct-root.1/files/un/der/thrd +RSTATE ERR: file name not a valid package: ignored pkg/z-good/z-good.1/files/un/der/thrd +RSTATE ERR: file name not a valid package: ignored pkg/z-i/z-n/z-e/z-r/z-very-inned-n-nv/z-very-inner-n-nv.1/files/un/der/thrd +RSTATE ERR: file name not a valid package: ignored pkg/z-no-nv/files/un/der/thrd +RSTATE ERR: file name not a valid package: ignored pkg/z-not/z-no-n-nv.1/files/un/der/thrd +RSTATE ERR: file name not a valid package: ignored pkg/z-v/z-e/z-r/z-y/z-very-inner.1/files/un/der/thrd +RSTATE ERR: file name not a valid package: ignored root-no-nv/files/un/der/thrd +### :III:3: list all +### opam switch create xfiles --empty +### opam list -A +# Packages matching: any +# Name # Installed # Synopsis +direct-root -- +good -- +n-nv-not-root -- +no-n-nv -- +not-same-nv-in -- +very-inner -- +very-inner-n-nv -- +### :III:4: install all +### opam install good.1 +The following actions will be performed: +=== install 1 package + - install good 1 + +<><> Processing actions <><><><><><><><><><><><><><><><><><><><><><><><><><><><> +-> installed good.1 +Done. +### opam install no-n-nv.1 +The following actions will be performed: +=== install 1 package + - install no-n-nv 1 + +<><> Processing actions <><><><><><><><><><><><><><><><><><><><><><><><><><><><> +-> installed no-n-nv.1 +Done. +### opam install n-nv-not-root.1 +The following actions will be performed: +=== install 1 package + - install n-nv-not-root 1 + +<><> Processing actions <><><><><><><><><><><><><><><><><><><><><><><><><><><><> +-> installed n-nv-not-root.1 +Done. +### opam install very-inner.1 +The following actions will be performed: +=== install 1 package + - install very-inner 1 + +<><> Processing actions <><><><><><><><><><><><><><><><><><><><><><><><><><><><> +-> installed very-inner.1 +Done. +### opam install very-inner-n-nv.1 +The following actions will be performed: +=== install 1 package + - install very-inner-n-nv 1 + +<><> Processing actions <><><><><><><><><><><><><><><><><><><><><><><><><><><><> +-> installed very-inner-n-nv.1 +Done. +### opam install direct-root.1 +The following actions will be performed: +=== install 1 package + - install direct-root 1 + +<><> Processing actions <><><><><><><><><><><><><><><><><><><><><><><><><><><><> +-> installed direct-root.1 +Done. +### opam install no-nv +[ERROR] No package named no-nv found. +# Return code 5 # +### opam install root-no-nv +[ERROR] No package named root-no-nv found. +# Return code 5 # +### opam install not-same-nv-in.2 +The following actions will be performed: +=== install 1 package + - install not-same-nv-in 2 + +<><> Processing actions <><><><><><><><><><><><><><><><><><><><><><><><><><><><> +-> installed not-same-nv-in.2 +Done. +### opam install z-good.1 +[ERROR] No package named z-good found. +# Return code 5 # +### opam install z-no-n-nv.1 +[ERROR] No package named z-no-n-nv found. +# Return code 5 # +### opam install z-n-nv-not-root.1 +[ERROR] No package named z-n-nv-not-root found. +# Return code 5 # +### opam install z-very-inner.1 +[ERROR] No package named z-very-inner found. +# Return code 5 # +### opam install z-very-inner-n-nv.1 +[ERROR] No package named z-very-inner-n-nv found. +# Return code 5 # +### opam install z-direct-root.1 +[ERROR] No package named z-direct-root found. +# Return code 5 # +### opam install z-no-nv +[ERROR] No package named z-no-nv found. +# Return code 5 # +### :X: opam admin +### mv REPO REPO.bak +### sh -c "mv REPO.bak/* ." +### OPAMDEBUGSECTIONS="FILE(opam) opam-file RSTATE" OPAMDEBUG=-3 opam admin list | unordered +FILE(config) Read ${BASEDIR}/OPAM/config in 0.000s +FILE(opam) Read ${BASEDIR}/packages/not-same-nv-in/not-same-nv-in.2/opam in 0.000s +FILE(opam) Read ${BASEDIR}/packages/direct-root.1/opam in 0.000s +FILE(opam) Read ${BASEDIR}/packages/i/n/e/r/very-inned-n-nv/very-inner-n-nv.1/opam in 0.000s +FILE(opam) Read ${BASEDIR}/packages/v/e/r/y/very-inner.1/opam in 0.000s +FILE(opam) Read ${BASEDIR}/packages/ba/baz/n-nv-not-root.1/opam in 0.000s +FILE(opam) Read ${BASEDIR}/packages/not/no-n-nv.1/opam in 0.000s +FILE(opam) Read ${BASEDIR}/packages/good/good.1/opam in 0.000s +# Packages matching: available +# Name # Installed # Synopsis +direct-root -- +good -- +n-nv-not-root -- +no-n-nv -- +not-same-nv-in -- +very-inner -- +very-inner-n-nv --