From 82a1fbfd7982cbd7d480dc38db65e95455cff546 Mon Sep 17 00:00:00 2001 From: Raja Boujbel Date: Thu, 7 May 2026 12:41:48 +0200 Subject: [PATCH 01/24] reftest: add repo set-url test --- master_changes.md | 1 + tests/reftests/repository-http.test | 28 ++++++++++++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/master_changes.md b/master_changes.md index 420b14c0565..f1f5985b5dc 100644 --- a/master_changes.md +++ b/master_changes.md @@ -189,6 +189,7 @@ users) * Add a lock test for undefined variables in a lock file [#6947 @rjbou - fix #6946] * Add a test showing the behaviour of `opam repo add` and `opam update` when faced with a repository containing an `opam` directory [#6995 @kit-ty-kate] * Add a tests for the several layouts of packages in a repository [#6941 @rjbou] + * Add a `opam repo set-url` case in repository-http [#6625 @rjbou] ### Engine * Add `http-server` to launch a minimal http server [#6939 @rjbou] diff --git a/tests/reftests/repository-http.test b/tests/reftests/repository-http.test index aa93c1e11e6..5019f47f339 100644 --- a/tests/reftests/repository-http.test +++ b/tests/reftests/repository-http.test @@ -187,4 +187,32 @@ enam -- A tautological synopsis. lima -- satu -- tiga -- +### :V: Update url of an already set repository with set-url +### mkdir SETREPO +### cp -R packages SETREPO/ +### cp repo SETREPO/ +### opam repository add set-repo ./SETREPO --set-default +[set-repo] Initialised +### opam list --all --repo set-repo +# Packages matching: any +# Name # Installed # Synopsis +dua -- +empat -- +enam -- A tautological synopsis. +lima -- +satu -- +tiga -- +### opam repo set-url set-repo http://localhost:$HTTPSERVERPORT --set-default | sed-cmd curl tar | grep -v "^+-" | ".*\(curl\|wget\).* \"--\"" -> 'curl-or-wget --' | "${HTTPSERVERPORT}" -> "port" +[set-repo] Initialised +### opam list --all --repo set-repo +# Packages matching: any +# Name # Installed # Synopsis +dua -- +empat -- +enam -- A tautological synopsis. +lima -- +satu -- +tiga -- +### opam repository remove set-repo --all +### rm -r SETREPO [[[Killing micro_httpd]]] From 4e8113aca0eae680a6da9216e36bb81df86df3b9 Mon Sep 17 00:00:00 2001 From: Kate Date: Tue, 28 Apr 2026 11:01:40 +0200 Subject: [PATCH 02/24] OpamSystem.directories_with_links: add argument to remove VCS directories Co-authored-by: Raja Boujbel --- master_changes.md | 2 +- src/core/opamFilename.ml | 4 ++-- src/core/opamFilename.mli | 6 ++++-- src/core/opamSystem.ml | 20 ++++++++++++++------ src/core/opamSystem.mli | 12 ++++++++---- 5 files changed, 29 insertions(+), 15 deletions(-) diff --git a/master_changes.md b/master_changes.md index f1f5985b5dc..d1c01296edf 100644 --- a/master_changes.md +++ b/master_changes.md @@ -316,5 +316,5 @@ users) * `OpamSystem.{command,commands,read_command_output}`: add a `?dir: dirname` optional arg to launch the command in a specific directory [#6910 @NathanReb] * `OpamFilename.Unix`: add `starts_with` [#6945 @rjbou] * `OpamCompat.Seq`: add `to_dispenser` [#6945 @kit-ty-kate] - * `OpamSystem.directories_with_links`, `OpamSystem.rec_files`, `OpamFilename.rec_files`: add optional `?except_vcs` that default to false to exclude VCS directories [#6945 @kit-ty-kate @rjbou] + * `OpamSystem.directories_with_links`, `OpamSystem.rec_files`, `OpamFilename.rec_files`: add optional `?except_vcs` that default to false to exclude VCS directories [#6625 @kit-ty-kate @rjbou] * `OpamFilename.make_tar_gz{_job}`: rename `make_tar_gz_job` into `make_tar_gz` as it no longer need an external process call [#6945 @kit-ty-kate] diff --git a/src/core/opamFilename.ml b/src/core/opamFilename.ml index 358ba30cb5b..8a49be38f8c 100644 --- a/src/core/opamFilename.ml +++ b/src/core/opamFilename.ml @@ -288,8 +288,8 @@ let add_extension filename suffix = let chop_extension filename = of_string (Filename.chop_extension (to_string filename)) -let rec_files d = - let fs = OpamSystem.rec_files (Dir.to_string d) in +let rec_files ?except_vcs d = + let fs = OpamSystem.rec_files ?except_vcs (Dir.to_string d) in List.rev_map of_string fs let files d = diff --git a/src/core/opamFilename.mli b/src/core/opamFilename.mli index 204fcd80c80..19415a1b35b 100644 --- a/src/core/opamFilename.mli +++ b/src/core/opamFilename.mli @@ -192,8 +192,10 @@ val add_extension: t -> string -> t (** Remove the file extension *) val chop_extension: t -> t -(** List all the filenames, recursively *) -val rec_files: Dir.t -> t list +(** List all the filenames, recursively. + Exclude VCS directories from selection if [except_vcs] is set to true. Keep + them otherwise. *) +val rec_files: ?except_vcs:bool -> Dir.t -> t list (** List all the filename. Do not recurse. *) val files: Dir.t -> t list diff --git a/src/core/opamSystem.ml b/src/core/opamSystem.ml index 5d3bc2745ba..f986523e9b4 100644 --- a/src/core/opamSystem.ml +++ b/src/core/opamSystem.ml @@ -118,13 +118,19 @@ let mkdir dir = end in aux dir +let is_vcs = function + | ".git" | ".hg" | "_darcs" -> true + | _ -> false + let get_files_t ~except_vcs dirname = let dir = Unix.opendir dirname in let rec aux files = match Unix.readdir dir with | "." | ".." -> aux files - | ".git" | ".hg" | "_darcs" when except_vcs -> aux files - | file -> aux (file :: files) + | file -> + if except_vcs && is_vcs file then aux files + else + aux (file :: files) | exception End_of_file -> files in let files = aux [] in @@ -360,12 +366,14 @@ let files_all_not_dir = let directories_strict = list (fun f -> try Sys2.is_directory f with Sys_error _ -> false) -let directories_with_links = - list (fun f -> try Sys.is_directory f with Sys_error _ -> false) +let directories_with_links ?(except_vcs=false) = + list (fun f -> + if except_vcs && is_vcs (Filename.basename f) then false else + try Sys.is_directory f with Sys_error _ -> false) -let rec_files dir = +let rec_files ?except_vcs dir = let rec aux accu dir = - let d = directories_with_links dir in + let d = directories_with_links ?except_vcs dir in let f = files_with_links dir in List.fold_left aux (f @ accu) d in aux [] dir diff --git a/src/core/opamSystem.mli b/src/core/opamSystem.mli index 3c9e82a9cf7..07adb65c73a 100644 --- a/src/core/opamSystem.mli +++ b/src/core/opamSystem.mli @@ -171,8 +171,10 @@ val files_with_links: string -> string list (** [rec_files dir] returns the list of all files in [dir], recursively. - Links behaving like directory are crossed. *) -val rec_files: string -> string list + Links behaving like directory are crossed. + Exclude VCS directories from selection if [except_vcs] is set to true. Keep + them otherwise. *) +val rec_files: ?except_vcs:bool -> string -> string list (** Return the list of files in the current directory. *) val files: string -> string list @@ -193,8 +195,10 @@ val dirs: string -> string list val dir_is_empty: string -> bool option (** [directories_with_links dir] returns the directories in the directory [dir]. - Links pointing to directory are also returned. *) -val directories_with_links: string -> string list + Links pointing to directory are also returned. + Exclude VCS directories from selection if [except_vcs] is set to true. Keep + them otherwise. *) +val directories_with_links: ?except_vcs:bool -> string -> string list (** Make a comman suitable for OpamProcess.Job. if [verbose], is set, command and output will be displayed (at command end for the From 5aa231b7c38e8837a9827d7418f255470345416e Mon Sep 17 00:00:00 2001 From: Raja Boujbel Date: Thu, 30 Apr 2026 19:45:35 +0200 Subject: [PATCH 03/24] OpamFilename.Unix: expose basename & dirname --- master_changes.md | 3 +++ src/core/opamFilename.mli | 6 ++++++ 2 files changed, 9 insertions(+) diff --git a/master_changes.md b/master_changes.md index d1c01296edf..b829edbdca3 100644 --- a/master_changes.md +++ b/master_changes.md @@ -318,3 +318,6 @@ users) * `OpamCompat.Seq`: add `to_dispenser` [#6945 @kit-ty-kate] * `OpamSystem.directories_with_links`, `OpamSystem.rec_files`, `OpamFilename.rec_files`: add optional `?except_vcs` that default to false to exclude VCS directories [#6625 @kit-ty-kate @rjbou] * `OpamFilename.make_tar_gz{_job}`: rename `make_tar_gz_job` into `make_tar_gz` as it no longer need an external process call [#6945 @kit-ty-kate] + * `OpamSystem`: add `open_in` and `open_in_bin` that checks is the file is a directory and raise `Sys_error` in that case [#6941 @rjbou] + * `OpamFilename.{open_in,open_in_bin}`: now errors when the filename is a directory, in all platforms [#6941 @rjbou] + * `OpamFilename.Unix`: add `basename` and `dirname` [#6625 @rjbou] diff --git a/src/core/opamFilename.mli b/src/core/opamFilename.mli index 19415a1b35b..7afa4e0bf47 100644 --- a/src/core/opamFilename.mli +++ b/src/core/opamFilename.mli @@ -427,4 +427,10 @@ module Unix : sig (** Check whether a filename starts by a given Dir.t *) val starts_with: Dir.t -> t -> bool + (** Return the base name *) + val basename: t -> Base.t + + (** Return the directory name *) + val dirname: t -> Dir.t + end From 088dce562465bf899350a616738de953e6547786 Mon Sep 17 00:00:00 2001 From: Raja Boujbel Date: Wed, 27 May 2026 18:17:30 +0200 Subject: [PATCH 04/24] OpamFilename.Unix.Dir: add basename & dirname --- master_changes.md | 1 + src/core/opamFilename.ml | 17 ++++++++++------- src/core/opamFilename.mli | 19 +++++++++++-------- 3 files changed, 22 insertions(+), 15 deletions(-) diff --git a/master_changes.md b/master_changes.md index b829edbdca3..594734d2eb7 100644 --- a/master_changes.md +++ b/master_changes.md @@ -321,3 +321,4 @@ users) * `OpamSystem`: add `open_in` and `open_in_bin` that checks is the file is a directory and raise `Sys_error` in that case [#6941 @rjbou] * `OpamFilename.{open_in,open_in_bin}`: now errors when the filename is a directory, in all platforms [#6941 @rjbou] * `OpamFilename.Unix`: add `basename` and `dirname` [#6625 @rjbou] + * `OpamFilename.Unix.Dir`: add `basename` and `dirname` [#6625 @rjbou] diff --git a/src/core/opamFilename.ml b/src/core/opamFilename.ml index 8a49be38f8c..1e2b726c668 100644 --- a/src/core/opamFilename.ml +++ b/src/core/opamFilename.ml @@ -737,13 +737,6 @@ module Unix = struct let to_base = Fun.id end - module Dir = struct - include Internal - - let of_dir = OpamSystem.back_to_forward - let to_dir = Fun.id - end - (* Copied from the OCaml Stdlib Filename module *) (* Copyright 1996 Institut National de Recherche en Informatique et en Automatique. *) @@ -800,6 +793,16 @@ module Unix = struct else find_end (String.length name - 1) let basename = generic_basename is_dir_sep current_dir_name + module Dir = struct + include Internal + + let of_dir = OpamSystem.back_to_forward + let to_dir = Fun.id + let dirname = dirname + let basename = basename + end + + module Op = struct let (/) = concat let (//) = concat diff --git a/src/core/opamFilename.mli b/src/core/opamFilename.mli index 7afa4e0bf47..39328046d57 100644 --- a/src/core/opamFilename.mli +++ b/src/core/opamFilename.mli @@ -391,26 +391,29 @@ module Unix : sig (** [of_string] will translate filesystem dir sep to slashes '/'. *) include OpamStd.ABSTRACT - module Dir : sig + module Base : sig (** [of_string] will translate filesystem dir sep to slashes '/'. *) include OpamStd.ABSTRACT - (** Convert dirname to a raw dirname. + (** Convert basename to a raw basename. Translates filesystem dir sep to slashes '/'. *) - val of_dir : Dir.t -> t + val of_base : Base.t -> t - val to_dir : t -> Dir.t + val to_base : t -> Base.t end - module Base : sig + module Dir : sig (** [of_string] will translate filesystem dir sep to slashes '/'. *) include OpamStd.ABSTRACT - (** Convert basename to a raw basename. + (** Convert dirname to a raw dirname. Translates filesystem dir sep to slashes '/'. *) - val of_base : Base.t -> t + val of_dir : Dir.t -> t - val to_base : t -> Base.t + val to_dir : t -> Dir.t + + val dirname : t -> t + val basename : t -> Base.t end module Op : sig From 81f3a5859b23f5bbcbb363bdc2702edd629e30ae Mon Sep 17 00:00:00 2001 From: Raja Boujbel Date: Thu, 30 Apr 2026 20:13:58 +0200 Subject: [PATCH 05/24] OpamFilename.Unix: add remove_prefix --- master_changes.md | 1 + src/core/opamFilename.ml | 5 +++++ src/core/opamFilename.mli | 3 +++ 3 files changed, 9 insertions(+) diff --git a/master_changes.md b/master_changes.md index 594734d2eb7..8459f434991 100644 --- a/master_changes.md +++ b/master_changes.md @@ -321,4 +321,5 @@ users) * `OpamSystem`: add `open_in` and `open_in_bin` that checks is the file is a directory and raise `Sys_error` in that case [#6941 @rjbou] * `OpamFilename.{open_in,open_in_bin}`: now errors when the filename is a directory, in all platforms [#6941 @rjbou] * `OpamFilename.Unix`: add `basename` and `dirname` [#6625 @rjbou] + * `OpamFilename.Unix`: add `basename`, `dirname` and `remove_prefix` [#6625 @rjbou] * `OpamFilename.Unix.Dir`: add `basename` and `dirname` [#6625 @rjbou] diff --git a/src/core/opamFilename.ml b/src/core/opamFilename.ml index 1e2b726c668..a76789571f3 100644 --- a/src/core/opamFilename.ml +++ b/src/core/opamFilename.ml @@ -817,4 +817,9 @@ module Unix = struct let prefix = concat prefix "" in OpamCompat.String.starts_with ~prefix filename + let remove_prefix prefix filename = + if prefix = "" then filename + else + OpamStd.String.remove_prefix ~prefix:(concat prefix "") filename + end diff --git a/src/core/opamFilename.mli b/src/core/opamFilename.mli index 39328046d57..a2d6353310b 100644 --- a/src/core/opamFilename.mli +++ b/src/core/opamFilename.mli @@ -430,6 +430,9 @@ module Unix : sig (** Check whether a filename starts by a given Dir.t *) val starts_with: Dir.t -> t -> bool + (** Remove a prefix from a file name *) + val remove_prefix: Dir.t -> t -> string + (** Return the base name *) val basename: t -> Base.t From 6943194d69689164fa093ce09f5f814bdff62a12 Mon Sep 17 00:00:00 2001 From: Raja Boujbel Date: Thu, 30 Apr 2026 19:45:35 +0200 Subject: [PATCH 06/24] OpamFilename.Unix: add add_extension --- master_changes.md | 1 + src/core/opamFilename.ml | 3 +++ src/core/opamFilename.mli | 3 +++ 3 files changed, 7 insertions(+) diff --git a/master_changes.md b/master_changes.md index 8459f434991..07ade288d29 100644 --- a/master_changes.md +++ b/master_changes.md @@ -322,4 +322,5 @@ users) * `OpamFilename.{open_in,open_in_bin}`: now errors when the filename is a directory, in all platforms [#6941 @rjbou] * `OpamFilename.Unix`: add `basename` and `dirname` [#6625 @rjbou] * `OpamFilename.Unix`: add `basename`, `dirname` and `remove_prefix` [#6625 @rjbou] + * `OpamFilename.Unix`: add `basename`, `dirname`, `remove_prefix` and `add_extension` [#6625 @rjbou] * `OpamFilename.Unix.Dir`: add `basename` and `dirname` [#6625 @rjbou] diff --git a/src/core/opamFilename.ml b/src/core/opamFilename.ml index a76789571f3..d4d4026f4a3 100644 --- a/src/core/opamFilename.ml +++ b/src/core/opamFilename.ml @@ -822,4 +822,7 @@ module Unix = struct else OpamStd.String.remove_prefix ~prefix:(concat prefix "") filename + let add_extension filename suffix = + filename ^ "." ^ suffix + end diff --git a/src/core/opamFilename.mli b/src/core/opamFilename.mli index a2d6353310b..806fa4eea3c 100644 --- a/src/core/opamFilename.mli +++ b/src/core/opamFilename.mli @@ -439,4 +439,7 @@ module Unix : sig (** Return the directory name *) val dirname: t -> Dir.t + (** Adds a dot and the given file extension *) + val add_extension: t -> string -> t + end From 718628f8b602f51e49e81a0bdf2461f8c97d4e51 Mon Sep 17 00:00:00 2001 From: Raja Boujbel Date: Tue, 9 Jun 2026 16:38:45 +0200 Subject: [PATCH 07/24] OpamFilename.Unix: add check_canonical, to rename --- master_changes.md | 1 + src/core/opamFilename.ml | 33 +++++++++++++++++++++++++++++++++ src/core/opamFilename.mli | 4 ++++ 3 files changed, 38 insertions(+) diff --git a/master_changes.md b/master_changes.md index 07ade288d29..1ac8b8fb689 100644 --- a/master_changes.md +++ b/master_changes.md @@ -323,4 +323,5 @@ users) * `OpamFilename.Unix`: add `basename` and `dirname` [#6625 @rjbou] * `OpamFilename.Unix`: add `basename`, `dirname` and `remove_prefix` [#6625 @rjbou] * `OpamFilename.Unix`: add `basename`, `dirname`, `remove_prefix` and `add_extension` [#6625 @rjbou] + * `OpamFilename.Unix`: add `basename`, `dirname`, `remove_prefix`, `add_extension`, `check_canonical` [#6625 @rjbou] * `OpamFilename.Unix.Dir`: add `basename` and `dirname` [#6625 @rjbou] diff --git a/src/core/opamFilename.ml b/src/core/opamFilename.ml index d4d4026f4a3..b9980c54321 100644 --- a/src/core/opamFilename.ml +++ b/src/core/opamFilename.ml @@ -825,4 +825,37 @@ module Unix = struct let add_extension filename suffix = filename ^ "." ^ suffix + let check_canonical filename = + let check_parent_dir_and_remove_trailing_slashes elems = + (* .. at any place : fail *) + if List.exists (String.equal "..") elems then Error "contains '..'" else + match elems with + | [] -> assert false + | [x] -> Ok x + | elems -> + let end_trailing_slash = + match List.rev elems with + | ""::_ -> true + | _ -> false + in + (* remove trailing slashes *) + let elems = List.filter (Fun.negate @@ String.equal "") elems in + match elems with + | [] -> Error "results in an empty path" + | elems -> + let core = String.concat dir_sep elems in + let res = + if end_trailing_slash then core ^ dir_sep else core + in + Ok res + in + match String.split_on_char dir_sep.[0] filename with + | [] -> assert false + (* ^/ : fail *) + | ""::_ -> Error "begins with '/'" + (* ^./ : delete the ./ *) + | "."::elements -> check_parent_dir_and_remove_trailing_slashes elements + | [_] -> Ok filename + | elements -> check_parent_dir_and_remove_trailing_slashes elements + end diff --git a/src/core/opamFilename.mli b/src/core/opamFilename.mli index 806fa4eea3c..118ada58c8b 100644 --- a/src/core/opamFilename.mli +++ b/src/core/opamFilename.mli @@ -442,4 +442,8 @@ module Unix : sig (** Adds a dot and the given file extension *) val add_extension: t -> string -> t + (** Return [Error err] if path is absolute or contains '..' + Return [Ok filename] where trailing '/' are removed and './' at the + beginning *) + val check_canonical: t -> (t, string) result end From 52f0b95d083b0b8ebe8e444f2eb911787ff85a20 Mon Sep 17 00:00:00 2001 From: Raja Boujbel Date: Tue, 9 Jun 2026 19:03:45 +0200 Subject: [PATCH 08/24] OpamFilename.Unix: when converting to filename or dir, put back windows dir sep --- master_changes.md | 1 + src/core/opamFilename.ml | 7 +++++-- src/core/opamFilename.mli | 4 ++++ 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/master_changes.md b/master_changes.md index 1ac8b8fb689..3ce8a066ef9 100644 --- a/master_changes.md +++ b/master_changes.md @@ -325,3 +325,4 @@ users) * `OpamFilename.Unix`: add `basename`, `dirname`, `remove_prefix` and `add_extension` [#6625 @rjbou] * `OpamFilename.Unix`: add `basename`, `dirname`, `remove_prefix`, `add_extension`, `check_canonical` [#6625 @rjbou] * `OpamFilename.Unix.Dir`: add `basename` and `dirname` [#6625 @rjbou] + * `OpamFilename.Unix.{to_dir,to_filename}`: now translate `/` into filesystem directory separator [#6625 @rjbou] diff --git a/src/core/opamFilename.ml b/src/core/opamFilename.ml index b9980c54321..496a0db283d 100644 --- a/src/core/opamFilename.ml +++ b/src/core/opamFilename.ml @@ -797,7 +797,7 @@ module Unix = struct include Internal let of_dir = OpamSystem.back_to_forward - let to_dir = Fun.id + let to_dir = OpamSystem.forward_to_back let dirname = dirname let basename = basename end @@ -809,7 +809,10 @@ module Unix = struct end 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_filename x = { + dirname = OpamSystem.forward_to_back (dirname x); + basename = basename x; + } let starts_with prefix filename = if prefix = (filename : string) then true diff --git a/src/core/opamFilename.mli b/src/core/opamFilename.mli index 118ada58c8b..95f8a4af340 100644 --- a/src/core/opamFilename.mli +++ b/src/core/opamFilename.mli @@ -410,6 +410,8 @@ module Unix : sig Translates filesystem dir sep to slashes '/'. *) val of_dir : Dir.t -> t + (** Convert raw dirname to a [dirname]. + Translates slashes '/' to filesystem dir sep. *) val to_dir : t -> Dir.t val dirname : t -> t @@ -425,6 +427,8 @@ module Unix : sig Translates filesystem dir sep to slashes '/'. *) val of_filename : filename -> t + (** Convert raw filename to a [filename]. + Translates slashes '/' to filesystem dir sep. *) val to_filename : t -> filename (** Check whether a filename starts by a given Dir.t *) From bfc4785f35eaf8f760ec9380682d5cb67dcc0147 Mon Sep 17 00:00:00 2001 From: Raja Boujbel Date: Thu, 7 May 2026 13:22:35 +0200 Subject: [PATCH 09/24] OpamFilename.Unix: add root_dir --- master_changes.md | 1 + src/core/opamFilename.ml | 11 +++++++++++ src/core/opamFilename.mli | 4 ++++ 3 files changed, 16 insertions(+) diff --git a/master_changes.md b/master_changes.md index 3ce8a066ef9..997e633fa6d 100644 --- a/master_changes.md +++ b/master_changes.md @@ -324,5 +324,6 @@ users) * `OpamFilename.Unix`: add `basename`, `dirname` and `remove_prefix` [#6625 @rjbou] * `OpamFilename.Unix`: add `basename`, `dirname`, `remove_prefix` and `add_extension` [#6625 @rjbou] * `OpamFilename.Unix`: add `basename`, `dirname`, `remove_prefix`, `add_extension`, `check_canonical` [#6625 @rjbou] + * `OpamFilename.Unix`: add `basename`, `dirname`, `remove_prefix`, `add_extension`, `check_canonical`, `root_dir` [#6625 @rjbou] * `OpamFilename.Unix.Dir`: add `basename` and `dirname` [#6625 @rjbou] * `OpamFilename.Unix.{to_dir,to_filename}`: now translate `/` into filesystem directory separator [#6625 @rjbou] diff --git a/src/core/opamFilename.ml b/src/core/opamFilename.ml index 496a0db283d..fbc8f917920 100644 --- a/src/core/opamFilename.ml +++ b/src/core/opamFilename.ml @@ -861,4 +861,15 @@ module Unix = struct | [_] -> Ok filename | elements -> check_parent_dir_and_remove_trailing_slashes elements + let rec root_dir filename = + if Char.equal filename.[0] dir_sep.[0] then + let filename = + String.sub filename 1 (String.length filename - 2) + in + Option.map ((^) dir_sep) (root_dir filename) + else + match OpamStd.String.cut_at filename dir_sep.[0] with + | Some (root, _rest) -> Some root + | None -> None + end diff --git a/src/core/opamFilename.mli b/src/core/opamFilename.mli index 95f8a4af340..31a300f1b4c 100644 --- a/src/core/opamFilename.mli +++ b/src/core/opamFilename.mli @@ -450,4 +450,8 @@ module Unix : sig Return [Ok filename] where trailing '/' are removed and './' at the beginning *) val check_canonical: t -> (t, string) result + + (** Return the first element of the path, if not empty *) + val root_dir: t -> string option + end From 0af370cab80b6b31aab304c2fd887ceff2124aa6 Mon Sep 17 00:00:00 2001 From: Raja Boujbel Date: Wed, 27 May 2026 20:47:27 +0200 Subject: [PATCH 10/24] OpamFile: add location information for 'read_from_string' functions Add also debug logging with level 3, that uses that new location information --- master_changes.md | 1 + src/format/opamFile.ml | 21 +++++++++++++++------ src/format/opamFile.mli | 8 +++++--- 3 files changed, 21 insertions(+), 9 deletions(-) diff --git a/master_changes.md b/master_changes.md index 997e633fa6d..d8391d90206 100644 --- a/master_changes.md +++ b/master_changes.md @@ -290,6 +290,7 @@ users) * `OpamRepositoryPath.{root,repo,packages_dir,packages,opam,files,descr,url}: have been moved to a new `OpamRepositoryPath.Make` functor [#6680 @rjbou @kit-ty-kate] * `OpamFilter.expand_interpolations_in_file`: changed argument type from `basename` to `filename` [#6910 @NathanReb] * `OpamFile.OPAM.print_errors`: now prints the repository if the informations is available [#6971 @rjbou] + * `OpamFile.*.read_from_string`: add optional `?loc` string argument to propagate location information when available (path on disk, archive, etc.), and add logging with level 3 that displays it [#6625 @rjbou] ## opam-core * `OpamCmdliner` was added. It is accessible through a new `opam-core.cmdliner` sub-library [#6755 @kit-ty-kate] diff --git a/src/format/opamFile.ml b/src/format/opamFile.ml index ff90ad1a44b..bcbd9fde474 100644 --- a/src/format/opamFile.ml +++ b/src/format/opamFile.ml @@ -69,7 +69,7 @@ module type IO_FILE = sig val read_opt: 'a typed_file -> t option val safe_read: 'a typed_file -> t val read_from_channel: ?filename:'a typed_file -> in_channel -> t - val read_from_string: ?filename:'a typed_file -> string -> t + val read_from_string: ?loc:string -> ?filename:'a typed_file -> string -> t val write_to_channel: ?filename:'a typed_file -> out_channel -> t -> unit val write_to_string: ?filename:'a typed_file -> t -> string end @@ -153,8 +153,17 @@ module MakeIO (F : IO_Arg) = struct let read_from_channel ?(filename=dummy_file) ic = read_from_f (F.of_channel filename) ic - let read_from_string ?(filename=dummy_file) str = - read_from_f (F.of_string filename) str + let read_from_string ?loc ?(filename=dummy_file) str = + let of_string str = + let chrono = OpamConsole.timer () in + let r = F.of_string filename str in + log ~level:3 "Read %s%s in %.3fs" + (OpamFilename.to_string filename) + (OpamStd.Option.to_string (Printf.sprintf " (out of %s)") loc) + (chrono ()); + r + in + read_from_f of_string str let write_to_channel ?(filename=dummy_file) oc t = F.to_channel filename oc t @@ -711,8 +720,8 @@ module Environment = struct include LineFile(struct open_env_updates (safe_read file) let read_from_channel ?filename ch = open_env_updates (read_from_channel ?filename ch) - let read_from_string ?filename s = - open_env_updates (read_from_string ?filename s) + let read_from_string ?loc ?filename s = + open_env_updates (read_from_string ?loc ?filename s) end (** (2) Part of the public repository format *) @@ -1244,7 +1253,7 @@ module type BestEffortRead = sig val read_opt: t typed_file -> t option val safe_read: t typed_file -> t val read_from_channel: ?filename:t typed_file -> in_channel -> t - val read_from_string: ?filename:t typed_file -> string -> t + val read_from_string: ?loc:string -> ?filename:t typed_file -> string -> t end module MakeBestEffort (S: BestEffortArg) : BestEffortRead diff --git a/src/format/opamFile.mli b/src/format/opamFile.mli index 4e4098ae254..d67f1ebe5a6 100644 --- a/src/format/opamFile.mli +++ b/src/format/opamFile.mli @@ -53,7 +53,7 @@ module type IO_FILE = sig val read_from_channel: ?filename:t typed_file -> in_channel -> t - val read_from_string: ?filename:t typed_file -> string -> t + val read_from_string: ?loc:string -> ?filename:t typed_file -> string -> t val write_to_channel: ?filename:t typed_file -> out_channel -> t -> unit @@ -68,7 +68,7 @@ module type BestEffortRead = sig val read_opt: t typed_file -> t option val safe_read: t typed_file -> t val read_from_channel: ?filename:t typed_file -> in_channel -> t - val read_from_string: ?filename:t typed_file -> string -> t + val read_from_string: ?loc:string -> ?filename:t typed_file -> string -> t end (** Lines of space-separated words. *) @@ -848,7 +848,9 @@ module Environment : sig val read_opt: t typed_file -> (spf_resolved, [> euok_writeable ]) env_update list option val safe_read: t typed_file -> (spf_resolved, [> euok_writeable ]) env_update list val read_from_channel: ?filename:t typed_file -> in_channel -> (spf_resolved, [> euok_writeable ]) env_update list - val read_from_string: ?filename:t typed_file -> string -> (spf_resolved, [> euok_writeable ]) env_update list + val read_from_string: + ?loc:string -> ?filename:t typed_file -> string + -> (spf_resolved, [> euok_writeable ]) env_update list end (** Compiler version [$opam/compilers/]. Deprecated, only used to upgrade old From 0e3a83af2d6ef43b9e97f1cdb4a985aa8435a690 Mon Sep 17 00:00:00 2001 From: Raja Boujbel Date: Tue, 28 Apr 2026 10:32:12 +0200 Subject: [PATCH 11/24] OpamFile: add safe_read_from_string --- master_changes.md | 1 + src/format/opamFile.ml | 29 ++++++++++++++++++++--------- src/format/opamFile.mli | 8 ++++++++ 3 files changed, 29 insertions(+), 9 deletions(-) diff --git a/master_changes.md b/master_changes.md index d8391d90206..e5cc84e78db 100644 --- a/master_changes.md +++ b/master_changes.md @@ -291,6 +291,7 @@ users) * `OpamFilter.expand_interpolations_in_file`: changed argument type from `basename` to `filename` [#6910 @NathanReb] * `OpamFile.OPAM.print_errors`: now prints the repository if the informations is available [#6971 @rjbou] * `OpamFile.*.read_from_string`: add optional `?loc` string argument to propagate location information when available (path on disk, archive, etc.), and add logging with level 3 that displays it [#6625 @rjbou] + * `OpamFile.*`: add `safe_read_from_string` [#6625 @rjbou] ## opam-core * `OpamCmdliner` was added. It is accessible through a new `opam-core.cmdliner` sub-library [#6755 @kit-ty-kate] diff --git a/src/format/opamFile.ml b/src/format/opamFile.ml index bcbd9fde474..84145a1d67e 100644 --- a/src/format/opamFile.ml +++ b/src/format/opamFile.ml @@ -70,6 +70,7 @@ module type IO_FILE = sig val safe_read: 'a typed_file -> t val read_from_channel: ?filename:'a typed_file -> in_channel -> t val read_from_string: ?loc:string -> ?filename:'a typed_file -> string -> t + val safe_read_from_string: ?loc:string -> ?filename:'a typed_file -> string -> t val write_to_channel: ?filename:'a typed_file -> out_channel -> t -> unit val write_to_string: ?filename:'a typed_file -> t -> string end @@ -129,17 +130,19 @@ module MakeIO (F : IO_Arg) = struct OpamSystem.internal_error "File %s does not exist or can't be read" (OpamFilename.to_string f) - let safe_read f = - try - match read_opt f with - | Some f -> f - | None -> - log ~level:2 "Cannot find %a" (slog OpamFilename.to_string) f; - F.empty - with + let safe_wrapper ~file rd = + try rd () with | (Pp.Bad_version _ | Pp.Bad_format _) as e-> OpamConsole.error "%s [skipped]\n" - (Pp.string_of_bad_format ~file:(OpamFilename.to_string f) e); + (Pp.string_of_bad_format ~file:(OpamFilename.to_string file) e); + F.empty + + let safe_read f = + safe_wrapper ~file:f @@ fun () -> + match read_opt f with + | Some f -> f + | None -> + log ~level:2 "Cannot find %a" (slog OpamFilename.to_string) f; F.empty let read_from_f f input = @@ -165,6 +168,10 @@ module MakeIO (F : IO_Arg) = struct in read_from_f of_string str + let safe_read_from_string ?loc ?(filename=dummy_file) str = + safe_wrapper ~file:filename @@ fun () -> + read_from_string ?loc ~filename str + let write_to_channel ?(filename=dummy_file) oc t = F.to_channel filename oc t @@ -722,6 +729,8 @@ module Environment = struct include LineFile(struct open_env_updates (read_from_channel ?filename ch) let read_from_string ?loc ?filename s = open_env_updates (read_from_string ?loc ?filename s) + let safe_read_from_string ?loc ?filename s = + open_env_updates (safe_read_from_string ?loc ?filename s) end (** (2) Part of the public repository format *) @@ -1254,6 +1263,8 @@ module type BestEffortRead = sig val safe_read: t typed_file -> t val read_from_channel: ?filename:t typed_file -> in_channel -> t val read_from_string: ?loc:string -> ?filename:t typed_file -> string -> t + val safe_read_from_string: + ?loc:string -> ?filename:t typed_file -> string -> t end module MakeBestEffort (S: BestEffortArg) : BestEffortRead diff --git a/src/format/opamFile.mli b/src/format/opamFile.mli index d67f1ebe5a6..4dfb2b3de99 100644 --- a/src/format/opamFile.mli +++ b/src/format/opamFile.mli @@ -55,6 +55,9 @@ module type IO_FILE = sig val read_from_string: ?loc:string -> ?filename:t typed_file -> string -> t + val safe_read_from_string: + ?loc:string -> ?filename:t typed_file -> string -> t + val write_to_channel: ?filename:t typed_file -> out_channel -> t -> unit val write_to_string: ?filename:t typed_file -> t -> string @@ -69,6 +72,8 @@ module type BestEffortRead = sig val safe_read: t typed_file -> t val read_from_channel: ?filename:t typed_file -> in_channel -> t val read_from_string: ?loc:string -> ?filename:t typed_file -> string -> t + val safe_read_from_string: + ?loc:string -> ?filename:t typed_file -> string -> t end (** Lines of space-separated words. *) @@ -851,6 +856,9 @@ module Environment : sig val read_from_string: ?loc:string -> ?filename:t typed_file -> string -> (spf_resolved, [> euok_writeable ]) env_update list + val safe_read_from_string: + ?loc:string -> ?filename:t typed_file -> string + -> (spf_resolved, [> euok_writeable ]) env_update list end (** Compiler version [$opam/compilers/]. Deprecated, only used to upgrade old From 96cabf24c610b2f1664475ba789693728a6a6d62 Mon Sep 17 00:00:00 2001 From: Raja Boujbel Date: Tue, 28 Apr 2026 19:27:57 +0200 Subject: [PATCH 12/24] OpamPatch: Add a configurator to be able to patch either on system files or in tar files --- master_changes.md | 3 + src/core/opamFilename.ml | 55 +++++++++----- src/core/opamPatch.ml | 142 ++++++++++++++++++++++++++++--------- src/core/opamPatch.mli | 95 ++++++++++++++++++++++--- src/repository/opamTar.ml | 33 +++++++++ src/repository/opamTar.mli | 6 ++ 6 files changed, 274 insertions(+), 60 deletions(-) diff --git a/master_changes.md b/master_changes.md index e5cc84e78db..17f0a11b68d 100644 --- a/master_changes.md +++ b/master_changes.md @@ -248,6 +248,7 @@ users) * `OpamRepositoryRoot` was added [#6680 @kit-ty-kate @rjbou] * `OpamTar`: add module to manipulate tar gz archive. It handles only files, not directories [#6945 @kit-ty-kate @rjbou] * `OpamRepositoryCommand.update_with_auto_upgrade`, `OpamUpdate.repository`: no longer call an external process to create an archive [#6945 @kit-ty-kate] + * `OpamTar`: add `patch` function to patch files in an tar gz archive [#6625 @rjbou] ## opam-state * `OpamStateConfig.t`: replace `no_depexts` fields that contains disabling informations by `depexts` field that returns if the depexts mechanism is enabled. This field is automatically update by global config value in `OpamStateConfig.load_defaults` [#6489 @rjbou] @@ -329,3 +330,5 @@ users) * `OpamFilename.Unix`: add `basename`, `dirname`, `remove_prefix`, `add_extension`, `check_canonical`, `root_dir` [#6625 @rjbou] * `OpamFilename.Unix.Dir`: add `basename` and `dirname` [#6625 @rjbou] * `OpamFilename.Unix.{to_dir,to_filename}`: now translate `/` into filesystem directory separator [#6625 @rjbou] + * `OpamPatch.patch`: no longer patch a file on disk, but take as argument a filesystem abstraction `FS_ABSTR` that delivers the needed functions [#6625 @rjbou] + * `OpamPatch.parse_patch`: no longer take `~dir` the directory to translate the patch in as argument, it now takes `~translate` argument that is a string option (directory option), if we want to perform a translation in that directory [#6625 @rjbou] diff --git a/src/core/opamFilename.ml b/src/core/opamFilename.ml index fbc8f917920..39a0a19beb7 100644 --- a/src/core/opamFilename.ml +++ b/src/core/opamFilename.ml @@ -450,25 +450,48 @@ let link ?(relative=false) ~target ~link = [@@ocaml.warning "-16"] let parse_patch ~dir patch_file = - OpamPatch.parse_patch ~dir:(Dir.to_string dir) ~file:(to_string patch_file) + OpamPatch.parse_patch ~translate:(Some (Dir.to_string dir)) (to_string patch_file) + +module PatchFS = struct + type root = string + type file = string + type target = unit + let root_label = "directory" + let translate_patch = true + let root_to_string root = root + let file_to_string file = file + let end_slash dir = Filename.concat (OpamSystem.real_path dir) "" + let get_path ~fail dir file = + let file = OpamSystem.real_path (Filename.concat dir file) in + if not (OpamStd.String.is_prefix_of ~from:0 ~full:file dir) then + fail (); + file + let ext file ext = file ^ ext + let write file content _target = OpamSystem.write file content + let on_rejection file content diff = + Option.iter (fun c -> write (file^".orig") c ()) content; + write (file^".rej") (Format.asprintf "%a" Patch.pp diff) () + let exists file _target = Sys.file_exists file + let exists_dir file _target = + let dir = Filename.dirname file in + Sys.file_exists dir && Sys.is_directory dir + let read file _target = OpamSystem.read file + let remove file _target = OpamSystem.remove_file file + let remove_dir file _target = OpamSystem.rmdir_cleanup (Filename.dirname file) + let same_dirname ~src ~dst = + Filename.dirname src <> (Filename.dirname dst : string) + let mv ~src ~dst _target = OpamSystem.mv src dst + let open_ _target f = f () + let save _target = () +end let patch ~allow_unclean patch_source dir = - let operations_result diffs = - Ok (List.map (fun d -> d.Patch.operation) diffs) - in - let patch ?patch_filename diffs = - OpamPatch.patch ~allow_unclean ?patch_filename ~dir:(Dir.to_string dir) - diffs - in - try + let patch_source = match patch_source with - | `Patch_diffs diffs -> patch diffs; - operations_result diffs - | `Patch_file p -> - let diffs = parse_patch ~dir:(Dir.to_string dir) p in - patch ~patch_filename:(to_string p) diffs; - operations_result diffs - with exn -> Error exn + | `Patch_file f -> `Patch_file (to_string f) + | `Patch_diffs _ as d -> d + in + OpamPatch.patch (module PatchFS) ~allow_unclean patch_source dir let flock flag ?dontblock file = OpamSystem.flock flag ?dontblock (to_string file) diff --git a/src/core/opamPatch.ml b/src/core/opamPatch.ml index ecae69bb6df..1b730e8a503 100644 --- a/src/core/opamPatch.ml +++ b/src/core/opamPatch.ml @@ -322,31 +322,59 @@ let translate_patch ~dir orig corrected = end; close_in ch +(* Patch configurator *) + +module type FS_ABSTR = sig + type root + type file + type target + val root_label : string + val translate_patch : bool + val root_to_string : root -> string + val file_to_string : file -> string + val end_slash : root -> root + val get_path : fail:(unit -> unit) -> root -> string -> file + val ext : file -> string -> file + val write : file -> string -> target -> target + val on_rejection : file -> string option -> Patch.t -> unit + val exists : file -> target -> bool + val exists_dir : file -> target -> bool + val read : file -> target -> string + val remove : file -> target -> target + val remove_dir : file -> target -> target + val same_dirname : src:file -> dst:file -> bool + val mv : src:file -> dst:file -> target -> target + val open_ : root -> (target -> unit) -> unit + val save : target -> unit +end + exception Internal_patch_error of string -let patch ~allow_unclean ?patch_filename ~dir diffs = +let patch_t (type a) (module FS : FS_ABSTR with type root = a) + ~allow_unclean ?patch_filename (to_patch:a) diffs = + if diffs = [] then () else let internal_patch_error fmt = Printf.ksprintf (fun str -> raise (Internal_patch_error str)) fmt in let patch_info_path = - OpamStd.Option.default ("in directory "^dir) patch_filename + OpamStd.Option.default + (Printf.sprintf "in %s %s" FS.root_label (FS.root_to_string to_patch)) + patch_filename in - (* NOTE: It is important to keep this `concat dir ""` to ensure the - is_prefix_of below doesn't match another similarly named directory *) - let dir = Filename.concat (OpamSystem.real_path dir) "" in + let to_patch = FS.end_slash to_patch in let get_path file = - let file = OpamSystem.real_path (Filename.concat dir file) in - if not (OpamStd.String.is_prefix_of ~from:0 ~full:file dir) then + let fail () = internal_patch_error "Patch %S tried to escape its scope." - patch_info_path; - file + patch_info_path + in + FS.get_path ~fail to_patch file in - let patch ~file content diff = + let patch file content diff patching = (* NOTE: The None case returned by [Patch.patch] is only returned if [diff = Patch.Delete _]. This sub-function is not called in this case so we [assert false] instead. *) match Patch.patch ~cleanly:true content diff with - | Some x -> x + | Some x -> patching, x | None -> assert false (* See NOTE above *) | exception _ when not allow_unclean -> internal_patch_error "Patch %S does not apply cleanly." @@ -354,55 +382,99 @@ let patch ~allow_unclean ?patch_filename ~dir diffs = | exception _ -> match Patch.patch ~cleanly:false content diff with | Some x -> - Option.iter (OpamSystem.write (file^".orig")) content; - x + let patching = + OpamStd.Option.map_default (fun content -> + FS.write (FS.ext file ".orig") content patching) + patching content + in + patching, x | None -> assert false (* See NOTE above *) | exception _ -> - Option.iter (OpamSystem.write (file^".orig")) content; - OpamSystem.write (file^".rej") (Format.asprintf "%a" Patch.pp diff); + FS.on_rejection file content diff; internal_patch_error "Patch %S does not apply cleanly." patch_info_path in - let apply diff = match diff.Patch.operation with + let apply patching diff = + match diff.Patch.operation with | Patch.Edit (file1, file2) -> let file1 = get_path file1 in let file2 = get_path file2 in - let file1_exists = Sys.file_exists file1 in + let file1_exists = FS.exists file1 patching in (* That seems to be the GNU patch behaviour *) let file = if file1_exists then file1 else file2 in - let content = OpamSystem.read file in - let content = patch ~file:file (Some content) diff in - OpamSystem.write file content; - if file1_exists && file1 <> (file2 : string) then - OpamSystem.rmdir_cleanup (Filename.dirname file1) + let content = FS.read file patching in + let patching, content = patch file (Some content) diff patching in + let patching = FS.write file content patching in + let patching = + if file1_exists && file1 <> (file2 : FS.file) then + FS.remove_dir file1 patching + else + patching + in + patching | Patch.Delete file | Patch.Git_ext (file, _, Patch.Delete_only) -> let file = get_path file in - OpamSystem.remove_file file; - OpamSystem.rmdir_cleanup (Filename.dirname file) + let patching = FS.remove file patching in + let patching = FS.remove_dir file patching in + patching | Patch.Create file | Patch.Git_ext (_, file, Patch.Create_only) -> let file = get_path file in - let content = patch ~file None diff in - OpamSystem.write file content + let patching, content = patch file None diff patching in + let patching = FS.write file content patching in + patching | Patch.Git_ext (_, _, Patch.Rename_only (src, dst)) -> let src = get_path src in let dst = get_path dst in - OpamSystem.mv src dst; - let dirname_src = Filename.dirname src in - if dirname_src <> (Filename.dirname dst : string) then - OpamSystem.rmdir_cleanup dirname_src + let patching = FS.mv ~src ~dst patching in + let patching = + if FS.same_dirname ~src ~dst then + FS.remove_dir src patching + else + patching + in + patching in - List.iter apply diffs + FS.open_ to_patch (fun patching -> + let patched : FS.target = List.fold_left apply patching diffs in + FS.save patched) -let parse_patch ~dir ~file = +let parse_patch ~translate file = if not (Sys.file_exists file) then (OpamConsole.error "Patch file %S not found." file; raise Not_found); let file' = - let file' = OpamSystem.temp_file ~auto_clean:false "processed-patch" in - translate_patch ~dir file file'; - file' + match translate with + | Some dir -> + let file' = OpamSystem.temp_file ~auto_clean:false "processed-patch" in + translate_patch ~dir file file'; + file' + | None -> file in let content = OpamSystem.read file' in Fun.protect (fun () -> Patch.parse ~p:1 content) ~finally:(fun () -> if not (OpamConsole.debug ()) then Sys.remove file') +let patch (type a) (module FS : FS_ABSTR with type root = a) + ~allow_unclean patch_source (to_patch:a) = + let operations_result diffs = + Ok (List.map (fun d -> d.Patch.operation) diffs) + in + let patch ?patch_filename diffs = + patch_t (module FS) ~allow_unclean ?patch_filename to_patch diffs + in + try + match patch_source with + | `Patch_diffs diffs -> + patch diffs; + operations_result diffs + | `Patch_file p -> + let diffs = + let translate = + if FS.translate_patch then Some (FS.root_to_string to_patch) + else None + in + parse_patch ~translate p + in + patch ~patch_filename:p diffs; + operations_result diffs + with exn -> Error exn diff --git a/src/core/opamPatch.mli b/src/core/opamPatch.mli index 07cbc1518d3..57a12cb9ba2 100644 --- a/src/core/opamPatch.mli +++ b/src/core/opamPatch.mli @@ -19,18 +19,95 @@ *) val translate_patch: dir:string -> string -> string -> unit -(** [patch ~allow_unclean ?patch_filename ~dir diffs] applies a patch to - directory [dir]. +module type FS_ABSTR = sig + (** The [root] is the type of the element that we want to patch: a directory, + an archive, etc. *) + type root - @param allow_unclean decides if applying a patch on a directory which + (** The [file] is the type of internal files that we manipulate *) + type file + + (** The [target] is the inner type of the element that we are patching *) + type target + + (* The name of [root] *) + val root_label : string + + (* Do we need to translate the patch file for this [root] *) + val translate_patch : bool + + val root_to_string : root -> string + val file_to_string : file -> string + + (* For directories, we need to add an end slash *) + val end_slash : root -> root + + (* Identity unless some checks need to be done. Take a [fail] function. *) + val get_path : fail:(unit -> unit) -> root -> string -> file + + (* [file] extension *) + val ext : file -> string -> file + + (* Write a [file] *) + val write : file -> string -> target -> target + + (* Function called when a patch application fails + + @param file is the filename on which the patch was rejected + @param content is the file content, if it exists + @param diff is the patch that failed to apply + *) + val on_rejection : file -> string option -> Patch.t -> unit + + (* Return true is [file] exists *) + val exists : file -> target -> bool + + (* Return true if dirname of [file] exists and is a directory *) + val exists_dir : file -> target -> bool + + (* Read a [file] *) + val read : file -> target -> string + + (* Remove a [file] *) + val remove : file -> target -> target + + (* Remove dirname of [file] if it exists *) + val remove_dir : file -> target -> target + + (* Return true if [src] and [dst] are in the same directory *) + val same_dirname : src:file -> dst:file -> bool + + (* Move [src] into [dst] *) + val mv : src:file -> dst:file -> target -> target + + (* [open_ root f] opens [root] and apply function [f] on its + [target] content *) + val open_ : root -> (target -> unit) -> unit + + (* Save the target (e.g. on disk) *) + val save : target -> unit +end + +(** [patch FS_ABSTR ~allow_unclean ?patch_filename ~dir diffs] applies a + patch to given element by [FS_ABSTRACTION]. + + @param FS_ABSTR is a module that defines the element that we are + patching and define all needed functions + + @param ~allow_unclean decides if applying a patch on a directory which differs slightly from the one described in the patch file is allowed. Allowing unclean applications imitates the default behaviour of GNU Patch. *) val patch: - allow_unclean:bool -> ?patch_filename:string -> dir:string - -> Patch.t list -> unit + (module FS_ABSTR with type root = 'a) -> + allow_unclean:bool -> + [`Patch_file of string | `Patch_diffs of Patch.t list ] -> 'a + -> (Patch.operation list, exn) result - -(** [parse_patch ~dir patch_file] processes and parses a patch file. +(** [parse_patch ~translate patch_file] processes and parses a patch file. Returns the parsed patch diffs or raises [Not_found] if the patch file - doesn't exist or can't be parsed. *) -val parse_patch: dir:string -> file:string -> Patch.t list + doesn't exist or can't be parsed. + + @param translate if [Some dir], launch {translate_patch} on [dir]. + Otherwise, no translation done. +*) +val parse_patch: translate:string option -> string -> Patch.t list diff --git a/src/repository/opamTar.ml b/src/repository/opamTar.ml index 691787b5a1f..6db0f338610 100644 --- a/src/repository/opamTar.ml +++ b/src/repository/opamTar.ml @@ -204,3 +204,36 @@ let create tar dir = Inplace.Map.empty files in Inplace.write { archive = tar; fd; content } + +module PatchFS = struct + type root = OpamFilename.t + module Tar = Inplace + type file = OpamFilename.Unix.t + type target = Tar.t + let root_label = "archive" + let translate_patch = false + let root_to_string = OpamFilename.to_string + let file_to_string = OpamFilename.Unix.to_string + let end_slash = Fun.id + let get_path ~fail:_ _target = + (* check if escapable ? *) + OpamFilename.Unix.of_string + let on_rejection _ _ _ = () + let ext file ext = OpamFilename.Unix.add_extension file ext + let write file content target = Tar.add file content target + let exists file = Tar.exists file + let exists_dir _file _target = false + let read file = Tar.read file + let remove file = Tar.remove file + let remove_dir file target = + Tar.remove_dir (OpamFilename.Unix.dirname file) target + let same_dirname ~src ~dst = + OpamFilename.Unix.dirname src + <> (OpamFilename.Unix.dirname dst : OpamFilename.Unix.Dir.t) + let mv = Tar.mv + let open_ = Tar.with_open_out + let save = Tar.write +end + +let patch ~allow_unclean patch_source tar = + OpamPatch.patch (module PatchFS) ~allow_unclean patch_source tar diff --git a/src/repository/opamTar.mli b/src/repository/opamTar.mli index 2a3998c77c0..d1ee10c2fc2 100644 --- a/src/repository/opamTar.mli +++ b/src/repository/opamTar.mli @@ -34,6 +34,12 @@ val fold_reg_files : archive. *) val create : archive -> dirname -> unit +(* Apply a patch on an archive *) +val patch: + allow_unclean:bool -> + [`Patch_file of string | `Patch_diffs of Patch.t list ] -> archive -> + (Patch.operation list, exn) result + (* This module contains helpers to act on the archive once openned *) module Inplace : sig type t From 17df66a57710a9e7250d823e1bbc7e4cf64b10ca Mon Sep 17 00:00:00 2001 From: Raja Boujbel Date: Tue, 28 Apr 2026 10:58:19 +0200 Subject: [PATCH 13/24] OpamTar: update create to permit to create flat directory archives --- master_changes.md | 2 +- src/repository/opamRepositoryRoot.ml | 2 +- src/repository/opamTar.ml | 9 +++++++-- src/repository/opamTar.mli | 10 ++++++---- 4 files changed, 15 insertions(+), 8 deletions(-) diff --git a/master_changes.md b/master_changes.md index 17f0a11b68d..bd0d20f5a62 100644 --- a/master_changes.md +++ b/master_changes.md @@ -249,6 +249,7 @@ users) * `OpamTar`: add module to manipulate tar gz archive. It handles only files, not directories [#6945 @kit-ty-kate @rjbou] * `OpamRepositoryCommand.update_with_auto_upgrade`, `OpamUpdate.repository`: no longer call an external process to create an archive [#6945 @kit-ty-kate] * `OpamTar`: add `patch` function to patch files in an tar gz archive [#6625 @rjbou] + * `OpamTar.create`: add `?flat` argument to do not integrate the target root directory in the archive [#6625 @rjbou] ## opam-state * `OpamStateConfig.t`: replace `no_depexts` fields that contains disabling informations by `depexts` field that returns if the depexts mechanism is enabled. This field is automatically update by global config value in `OpamStateConfig.load_defaults` [#6489 @rjbou] @@ -273,7 +274,6 @@ users) * `OpamSysInteract`: add `available_packages_and_family` that returns availability status and the os family [#6489 @rjbou] * `OpamRepositoryState.load_opams_from_dir`: now sorts files and directories read from disk before processing them [#6941 @rjbou] - ## opam-solver ## opam-format diff --git a/src/repository/opamRepositoryRoot.ml b/src/repository/opamRepositoryRoot.ml index f770ac4d9f5..b2724559fc4 100644 --- a/src/repository/opamRepositoryRoot.ml +++ b/src/repository/opamRepositoryRoot.ml @@ -55,7 +55,7 @@ module Dir = struct end) end -let make_tar_gz = OpamTar.create +let make_tar_gz = OpamTar.create ~flat:false let extract_in_job = OpamFilename.extract_in_job type t = diff --git a/src/repository/opamTar.ml b/src/repository/opamTar.ml index 6db0f338610..3850ef1972e 100644 --- a/src/repository/opamTar.ml +++ b/src/repository/opamTar.ml @@ -186,7 +186,7 @@ module Inplace = struct end -let create tar dir = +let create ?(flat=false) tar dir = log "creating archive %s from %s" (OpamFilename.to_string tar) (OpamFilename.Dir.to_string dir); @@ -197,7 +197,12 @@ let create tar dir = Fun.protect ~finally:(fun () -> Unix.close fd) @@ fun () -> let files = OpamFilename.rec_files dir in let content = - let remove_prefix = OpamFilename.remove_prefix (OpamFilename.dirname_dir dir) in + let remove_prefix = + let dir = + if flat then dir else OpamFilename.dirname_dir dir + in + OpamFilename.remove_prefix dir + in List.fold_left (fun map f -> let k = OpamFilename.Unix.of_string (remove_prefix f) in Inplace.Map.add k (OpamFilename.read f) map) diff --git a/src/repository/opamTar.mli b/src/repository/opamTar.mli index d1ee10c2fc2..0bf386121ba 100644 --- a/src/repository/opamTar.mli +++ b/src/repository/opamTar.mli @@ -28,11 +28,13 @@ val fold_reg_files : ('acc -> archived_file -> archived_file_content -> 'acc) -> 'acc -> archive -> 'acc -(* [create archive dir] Creates an compressed archive [archive] containing the - [dir] at root. +(* [create ?flat archive dir] Creates an compressed archive [archive] + containing the [dir]. If the directory contains a VCS directory, it is not integrated in the - archive. *) -val create : archive -> dirname -> unit + archive. + If [flat] is set to true, the archive contains the flat content of [dir], + otherwise, the root directory in the archive is [dir]. *) +val create : ?flat:bool -> archive -> dirname -> unit (* Apply a patch on an archive *) val patch: From f7fc840e853165d75282741dad5117755a0efcd1 Mon Sep 17 00:00:00 2001 From: Raja Boujbel Date: Mon, 8 Jun 2026 19:46:33 +0200 Subject: [PATCH 14/24] OpamTar: update create to permit not embedding VCS files --- master_changes.md | 1 + src/repository/opamRepositoryRoot.ml | 2 +- src/repository/opamTar.ml | 4 ++-- src/repository/opamTar.mli | 10 ++++++---- 4 files changed, 10 insertions(+), 7 deletions(-) diff --git a/master_changes.md b/master_changes.md index bd0d20f5a62..370d2f2bd9f 100644 --- a/master_changes.md +++ b/master_changes.md @@ -250,6 +250,7 @@ users) * `OpamRepositoryCommand.update_with_auto_upgrade`, `OpamUpdate.repository`: no longer call an external process to create an archive [#6945 @kit-ty-kate] * `OpamTar`: add `patch` function to patch files in an tar gz archive [#6625 @rjbou] * `OpamTar.create`: add `?flat` argument to do not integrate the target root directory in the archive [#6625 @rjbou] + * `OpamTar.create`: add `?except_vcs` argument exclude VCS files from archive creation [#6625 @rjbou] ## opam-state * `OpamStateConfig.t`: replace `no_depexts` fields that contains disabling informations by `depexts` field that returns if the depexts mechanism is enabled. This field is automatically update by global config value in `OpamStateConfig.load_defaults` [#6489 @rjbou] diff --git a/src/repository/opamRepositoryRoot.ml b/src/repository/opamRepositoryRoot.ml index b2724559fc4..12a305c2508 100644 --- a/src/repository/opamRepositoryRoot.ml +++ b/src/repository/opamRepositoryRoot.ml @@ -55,7 +55,7 @@ module Dir = struct end) end -let make_tar_gz = OpamTar.create ~flat:false +let make_tar_gz = OpamTar.create ~flat:false ~except_vcs:false let extract_in_job = OpamFilename.extract_in_job type t = diff --git a/src/repository/opamTar.ml b/src/repository/opamTar.ml index 3850ef1972e..ccdc7bd54d4 100644 --- a/src/repository/opamTar.ml +++ b/src/repository/opamTar.ml @@ -186,7 +186,7 @@ module Inplace = struct end -let create ?(flat=false) tar dir = +let create ?(flat=false) ?(except_vcs=false) tar dir = log "creating archive %s from %s" (OpamFilename.to_string tar) (OpamFilename.Dir.to_string dir); @@ -195,7 +195,7 @@ let create ?(flat=false) tar dir = [Unix.O_CREAT; Unix.O_TRUNC; Unix.O_WRONLY] 0o640 in Fun.protect ~finally:(fun () -> Unix.close fd) @@ fun () -> - let files = OpamFilename.rec_files dir in + let files = OpamFilename.rec_files ~except_vcs dir in let content = let remove_prefix = let dir = diff --git a/src/repository/opamTar.mli b/src/repository/opamTar.mli index 0bf386121ba..074c2706324 100644 --- a/src/repository/opamTar.mli +++ b/src/repository/opamTar.mli @@ -28,13 +28,15 @@ val fold_reg_files : ('acc -> archived_file -> archived_file_content -> 'acc) -> 'acc -> archive -> 'acc -(* [create ?flat archive dir] Creates an compressed archive [archive] - containing the [dir]. +(* [create ?flat ?except_vcs archive dir] Creates an compressed archive + [archive] containing the [dir]. If the directory contains a VCS directory, it is not integrated in the archive. If [flat] is set to true, the archive contains the flat content of [dir], - otherwise, the root directory in the archive is [dir]. *) -val create : ?flat:bool -> archive -> dirname -> unit + otherwise, the root directory in the archive is [dir]. + if [except_vcs] is set to true, VCS directories and files are not embed in + the archive. The default is set to false. *) +val create : ?flat:bool -> ?except_vcs:bool -> archive -> dirname -> unit (* Apply a patch on an archive *) val patch: From 97e67c1b42c0d27e1c9fe9119b88ada094e25d3d Mon Sep 17 00:00:00 2001 From: Raja Boujbel Date: Tue, 9 Jun 2026 16:39:41 +0200 Subject: [PATCH 15/24] OpamTar: when opening an archive, check paths internally --- master_changes.md | 1 + src/repository/opamTar.ml | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/master_changes.md b/master_changes.md index 370d2f2bd9f..e32fbbc50e0 100644 --- a/master_changes.md +++ b/master_changes.md @@ -251,6 +251,7 @@ users) * `OpamTar`: add `patch` function to patch files in an tar gz archive [#6625 @rjbou] * `OpamTar.create`: add `?flat` argument to do not integrate the target root directory in the archive [#6625 @rjbou] * `OpamTar.create`: add `?except_vcs` argument exclude VCS files from archive creation [#6625 @rjbou] + * `OpamTar`: when an archive is opened, the first step is to check and normalise canonical paths (no `/../`, remove `./`, etc.) [#6625 @rjbou] ## opam-state * `OpamStateConfig.t`: replace `no_depexts` fields that contains disabling informations by `depexts` field that returns if the depexts mechanism is enabled. This field is automatically update by global config value in `OpamStateConfig.load_defaults` [#6489 @rjbou] diff --git a/src/repository/opamTar.ml b/src/repository/opamTar.ml index ccdc7bd54d4..fbca4bd27db 100644 --- a/src/repository/opamTar.ml +++ b/src/repository/opamTar.ml @@ -64,6 +64,16 @@ let run archive = in run let fold_reg_files_aux archive f acc fd = + let f acc filename content = + let filename = + match OpamFilename.Unix.check_canonical filename with + | Ok filename -> filename + | Error err -> + raise_error archive "Path '%s' not allowed: %s" + (OpamFilename.Unix.to_string filename) err + in + f acc filename content + in let go ?global:_ hdr acc = match hdr.Tar.Header.link_indicator with | Normal -> From ba2f53887917fac8127e5cce12b5b526122e55e7 Mon Sep 17 00:00:00 2001 From: Raja Boujbel Date: Wed, 27 May 2026 18:18:41 +0200 Subject: [PATCH 16/24] OpamRepositoryRoot: add remove_prefix & remove_prefix_dir --- master_changes.md | 1 + src/repository/opamRepositoryRoot.ml | 11 +++++++++++ src/repository/opamRepositoryRoot.mli | 4 ++++ 3 files changed, 16 insertions(+) diff --git a/master_changes.md b/master_changes.md index e32fbbc50e0..1280e027898 100644 --- a/master_changes.md +++ b/master_changes.md @@ -252,6 +252,7 @@ users) * `OpamTar.create`: add `?flat` argument to do not integrate the target root directory in the archive [#6625 @rjbou] * `OpamTar.create`: add `?except_vcs` argument exclude VCS files from archive creation [#6625 @rjbou] * `OpamTar`: when an archive is opened, the first step is to check and normalise canonical paths (no `/../`, remove `./`, etc.) [#6625 @rjbou] + * `OpamRepositoryRoot`: add `remove_prefix` and `remove_prefix_dir` [#6625 @rjbou] ## opam-state * `OpamStateConfig.t`: replace `no_depexts` fields that contains disabling informations by `depexts` field that returns if the depexts mechanism is enabled. This field is automatically update by global config value in `OpamStateConfig.load_defaults` [#6489 @rjbou] diff --git a/src/repository/opamRepositoryRoot.ml b/src/repository/opamRepositoryRoot.ml index 12a305c2508..618cddae8fe 100644 --- a/src/repository/opamRepositoryRoot.ml +++ b/src/repository/opamRepositoryRoot.ml @@ -53,6 +53,7 @@ module Dir = struct let to_typed_file = OpamFile.make module Op = Op end) + end let make_tar_gz = OpamTar.create ~flat:false ~except_vcs:false @@ -85,6 +86,16 @@ let basename = function let to_string = function | Dir dir -> Dir.to_string dir +let remove_prefix file = function + | Dir dir -> + OpamFilename.remove_prefix dir file + |> OpamFilename.raw + +let remove_prefix_dir d = function + | Dir dir -> + OpamFilename.remove_prefix_dir dir d + |> OpamFilename.raw_dir + let copy ~src ~dst = match src, dst with | Dir src, Dir dst -> Dir.copy ~src ~dst diff --git a/src/repository/opamRepositoryRoot.mli b/src/repository/opamRepositoryRoot.mli index 363ddbec83a..54f722ed7a9 100644 --- a/src/repository/opamRepositoryRoot.mli +++ b/src/repository/opamRepositoryRoot.mli @@ -52,6 +52,7 @@ module Dir : sig with type repo_root = t and type repo_dirname = dirname and type 'a typed_file = 'a OpamFile.t + end val make_tar_gz : filename -> Dir.t -> unit @@ -76,6 +77,9 @@ val dirname : t -> dirname val basename : t -> basename val to_string : t -> string +val remove_prefix: filename -> t -> filename +val remove_prefix_dir: dirname -> t -> dirname + val copy : src:t -> dst:t -> unit val move : src:t -> dst:t -> unit From fef8509c0bac126f07427fb485949e915d2d344a Mon Sep 17 00:00:00 2001 From: Raja Boujbel Date: Thu, 30 Apr 2026 20:14:10 +0200 Subject: [PATCH 17/24] OpamRepositoryRoot: add read_file --- master_changes.md | 1 + src/repository/opamRepositoryRoot.ml | 9 +++++++++ src/repository/opamRepositoryRoot.mli | 7 +++++++ 3 files changed, 17 insertions(+) diff --git a/master_changes.md b/master_changes.md index 1280e027898..a26f6bc34f6 100644 --- a/master_changes.md +++ b/master_changes.md @@ -253,6 +253,7 @@ users) * `OpamTar.create`: add `?except_vcs` argument exclude VCS files from archive creation [#6625 @rjbou] * `OpamTar`: when an archive is opened, the first step is to check and normalise canonical paths (no `/../`, remove `./`, etc.) [#6625 @rjbou] * `OpamRepositoryRoot`: add `remove_prefix` and `remove_prefix_dir` [#6625 @rjbou] + * `OpamRepositoryRoot`: add `read_file` that reads an `OpamFile.t` using its pp from the archive [#6625 @rjbou] ## opam-state * `OpamStateConfig.t`: replace `no_depexts` fields that contains disabling informations by `depexts` field that returns if the depexts mechanism is enabled. This field is automatically update by global config value in `OpamStateConfig.load_defaults` [#6489 @rjbou] diff --git a/src/repository/opamRepositoryRoot.ml b/src/repository/opamRepositoryRoot.ml index 618cddae8fe..3646b49eeef 100644 --- a/src/repository/opamRepositoryRoot.ml +++ b/src/repository/opamRepositoryRoot.ml @@ -113,6 +113,15 @@ let is_symlink = function let patch ~allow_unclean patch = function | Dir dir -> Dir.patch ~allow_unclean patch dir +let read_file (type a) (module R : OpamFile.IO_FILE with type t = a) + ?(safe=false) repo_root + : ?filename:a OpamFile.t -> string -> a = + let rd = + if safe then R.safe_read_from_string + else R.read_from_string + in + rd ~loc:(to_string repo_root) + let delayed_read_repo = function | Dir dir -> let repo_file_path = diff --git a/src/repository/opamRepositoryRoot.mli b/src/repository/opamRepositoryRoot.mli index 54f722ed7a9..a1c2259d89f 100644 --- a/src/repository/opamRepositoryRoot.mli +++ b/src/repository/opamRepositoryRoot.mli @@ -86,6 +86,13 @@ val move : src:t -> dst:t -> unit val exists : t -> bool val is_symlink : t -> bool +(* [read_file IO_FILE ?safe t ?filename content] reads [content] using + [IO_FILE.read_from_string]. Is [safe] is true, uses + [IO_FILE.safe_read_from_string]. *) +val read_file: + (module OpamFile.IO_FILE with type t = 'a) -> + ?safe:bool -> t -> ?filename:'a OpamFile.t -> string -> 'a + val patch : allow_unclean:bool -> [`Patch_file of filename | `Patch_diffs of Patch.t list ] -> t -> From 2f006619abbbb785221d5862b23307fb5a5045db Mon Sep 17 00:00:00 2001 From: Raja Boujbel Date: Wed, 1 Jul 2026 16:11:43 +0200 Subject: [PATCH 18/24] OpamRepositoryRoot: add documentation for patch --- src/repository/opamRepositoryRoot.mli | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/repository/opamRepositoryRoot.mli b/src/repository/opamRepositoryRoot.mli index a1c2259d89f..83a8d39c374 100644 --- a/src/repository/opamRepositoryRoot.mli +++ b/src/repository/opamRepositoryRoot.mli @@ -93,6 +93,13 @@ val read_file: (module OpamFile.IO_FILE with type t = 'a) -> ?safe:bool -> t -> ?filename:'a OpamFile.t -> string -> 'a +(* [patch ~allow_unclean patch_source arch] applies a patch to an archive + [arch]. The patch source can be either [`Patch_file filename] for a patch + file, or [`Patch_diffs diffs] for a list of file-level changes. + + @param allow_unclean decides if applying a patch on a directory which + differs slightly from the one described in the patch file is allowed. + Allowing unclean applications imitates the default behaviour of GNU Patch. *) val patch : allow_unclean:bool -> [`Patch_file of filename | `Patch_diffs of Patch.t list ] -> t -> From 837232ca52db4e15bb1a1a0ae50203436d2f6dc3 Mon Sep 17 00:00:00 2001 From: Raja Boujbel Date: Tue, 30 Jun 2026 19:11:30 +0200 Subject: [PATCH 19/24] Change internal storage of repositories in opam root from only directories to directories and tar gz archives By default, http repositories will be stored as archives. It is possible to enable non-VCS repositories as archive by setting `OPAMREPOSITORYTARRING`. --- master_changes.md | 8 + src/client/opamAdminCommand.ml | 5 - src/client/opamArg.ml | 8 +- src/client/opamCommands.ml | 78 ++-- src/client/opamListCommand.ml | 8 +- src/client/opamRepositoryCommand.ml | 39 +- src/format/opamRepositoryPath.ml | 2 +- src/format/opamRepositoryPath.mli | 3 +- src/repository/opamHTTP.ml | 10 +- src/repository/opamLocal.ml | 70 ++-- src/repository/opamRepositoryBackend.ml | 13 +- src/repository/opamRepositoryBackend.mli | 6 +- src/repository/opamRepositoryRoot.ml | 132 ++++++- src/repository/opamRepositoryRoot.mli | 55 ++- src/repository/opamVCS.ml | 4 + src/state/opamFileTools.ml | 236 +++++++++--- src/state/opamFileTools.mli | 27 ++ src/state/opamPinned.ml | 64 ++-- src/state/opamRepositoryState.ml | 262 +++++++++---- src/state/opamRepositoryState.mli | 19 +- src/state/opamStateTypes.mli | 3 - src/state/opamUpdate.ml | 116 +++--- tests/reftests/action-disk.test | 30 +- tests/reftests/extrafile.test | 18 +- tests/reftests/extrasource.test | 6 +- tests/reftests/rec-pin.test | 2 +- tests/reftests/repository-http.test | 26 +- tests/reftests/repository-layout.test | 454 +++++++++++++---------- tests/reftests/repository.test | 51 ++- tests/reftests/update.test | 36 +- 30 files changed, 1209 insertions(+), 582 deletions(-) diff --git a/master_changes.md b/master_changes.md index a26f6bc34f6..b5182197e04 100644 --- a/master_changes.md +++ b/master_changes.md @@ -71,6 +71,7 @@ users) ## Repository * No longer call tar tool to create archives, use tar library instead [#6945 @kit-ty-kate] * [BUG] Do not fail on directories named `opam` when scanning the `packages` directory of a repository during `opam repo add` or `opam init` (worked on subsequent `opam update`) [#6941 @kit-ty-kate @rjbou] + * Speedup repository operations on Windows & BSD by changing its storage in the opam root from plain directory to archive, for HTTP repositories, or non-VCS one if `OPAMREPOSITORYTARRING` is enabled [#6625 @rjbou @kit-ty-kate @arozovyk - fix #5741 #5648 #5484 #5559 #3050] ## Lock * [BUG] Fix `undefined variable` error when a lock file filter contains an undefined variables: fail gracefully with strict mode, continue and default the variable to false on normal mode [#6947 @rjbou - fix #6946] @@ -254,6 +255,8 @@ users) * `OpamTar`: when an archive is opened, the first step is to check and normalise canonical paths (no `/../`, remove `./`, etc.) [#6625 @rjbou] * `OpamRepositoryRoot`: add `remove_prefix` and `remove_prefix_dir` [#6625 @rjbou] * `OpamRepositoryRoot`: add `read_file` that reads an `OpamFile.t` using its pp from the archive [#6625 @rjbou] + * `OpamRepositoryBackend.get_diff`: now computes the diff between two repository roots (dir, archive), instead of only dirs [#6625 @rjbou] + * `OpamRepositoryRoot`: add `Tgz` module for tar gz archive repository root support [#6625 @rjbou @kit-ty-kate] ## opam-state * `OpamStateConfig.t`: replace `no_depexts` fields that contains disabling informations by `depexts` field that returns if the depexts mechanism is enabled. This field is automatically update by global config value in `OpamStateConfig.load_defaults` [#6489 @rjbou] @@ -277,6 +280,10 @@ users) * `OpamRepositoryState`: add `syspkgs_available` that returns the stored depext availability status in repository state [#6489 @rjbou] * `OpamSysInteract`: add `available_packages_and_family` that returns availability status and the os family [#6489 @rjbou] * `OpamRepositoryState.load_opams_from_dir`: now sorts files and directories read from disk before processing them [#6941 @rjbou] + * `OpamFileTools`: add new `lint_repo_package` that lints a file from a repository root [#6625 @rjbou] + * `OpamRepositoryState`: add `load_opams_from_tgz` [#6625 @rjbou] + * `OpamRepositoryState`: add `load_opams` that operates from a repository root [#6625 @rjbou] + * `OpamStateTypes.repos_state`: remove `repos_tmp` field [#6625 @kit-ty-kate @rjbou] ## opam-solver @@ -297,6 +304,7 @@ users) * `OpamFile.OPAM.print_errors`: now prints the repository if the informations is available [#6971 @rjbou] * `OpamFile.*.read_from_string`: add optional `?loc` string argument to propagate location information when available (path on disk, archive, etc.), and add logging with level 3 that displays it [#6625 @rjbou] * `OpamFile.*`: add `safe_read_from_string` [#6625 @rjbou] + * `OpamRepositoryPath.tar`: renamed to `repo_tarring`, deprecated, no longer used [#6625 @rjbou] ## opam-core * `OpamCmdliner` was added. It is accessible through a new `opam-core.cmdliner` sub-library [#6755 @kit-ty-kate] diff --git a/src/client/opamAdminCommand.ml b/src/client/opamAdminCommand.ml index 7870f6ae6d6..76f526ec4f2 100644 --- a/src/client/opamAdminCommand.ml +++ b/src/client/opamAdminCommand.ml @@ -1112,17 +1112,12 @@ let get_virtual_switch_state repo_root env = global_state_to_upgrade = { gtc_repo = false; gtc_switch = false; }; } in let singl x = OpamRepositoryName.Map.singleton repo.repo_name x in - let repos_tmp = - let t = Hashtbl.create 1 in - Hashtbl.add t repo.repo_name (lazy repo_root); t - in let rt = { repos_global = gt; repos_lock = OpamSystem.lock_none; repositories = singl repo; repos_definitions = singl repo_def; repo_opams = singl opams; - repos_tmp; repos_syspkgs_available = None; } in let gt = diff --git a/src/client/opamArg.ml b/src/client/opamArg.ml index a2783006409..7516b4831f7 100644 --- a/src/client/opamArg.ml +++ b/src/client/opamArg.ml @@ -224,10 +224,10 @@ let environment_variables = "enables option --no-checksums when available."; "REPOSITORYTARRING", cli_from cli2_2, (fun b -> REPOSITORYTARRING (env_bool b)), - "internally store the repositories as tar.gz files. This can be much \ - faster on filesystems that don't cope well with scanning large trees \ - but have good caching in /tmp. However this is slower in the \ - general case."; + "internally store all non-vcs repositories as tar.gz files (by default, \ + http repositories are stored as archive).This can be much faster on \ + filesystems that don't cope well with scanning large trees. All \ + operation are done in-memory, no I/O for scanning the repository."; "REQUIRECHECKSUMS", cli_original, (fun v -> REQUIRECHECKSUMS (env_bool v)), "Enables option `--require-checksums' when available \ diff --git a/src/client/opamCommands.ml b/src/client/opamCommands.ml index 4fa2adb2ce2..fe0d72a348a 100644 --- a/src/client/opamCommands.ml +++ b/src/client/opamCommands.ml @@ -2524,32 +2524,31 @@ let repository cli = in OpamGlobalState.with_ `Lock_none @@ fun gt -> OpamRepositoryState.with_ `Lock_write gt @@ fun rt -> - OpamFilename.with_tmp_dir @@ fun tmp_dir -> + OpamFilename.with_tmp_dir @@ fun inn -> + let repo_root = + OpamRepositoryState.get_repo_root rt + (OpamRepositoryState.get_repo rt name) + in + if not (OpamRepositoryRoot.exists repo_root) then + OpamConsole.error_and_exit `Internal_error + "Repository not found, consider running 'opam update %s' \ + to retrieve a consistent state." + (OpamRepositoryName.to_string name); let rt0 = rt in - let backup = - let tar = OpamRepositoryPath.tar gt.root name in - if OpamFilename.exists tar then - (let target = OpamFilename.create tmp_dir (OpamFilename.basename tar) in - OpamFilename.copy ~src:tar ~dst:target; - fun () -> OpamFilename.copy ~src:target ~dst:tar) - else - (let dir = OpamRepositoryRoot.Dir.Path.root gt.root name in - if not (OpamRepositoryRoot.Dir.exists dir) then - OpamConsole.error_and_exit `Internal_error - "Repository not found, consider running 'opam update %s' \ - to retrieve a consistent state." - (OpamRepositoryName.to_string name); - let target = OpamRepositoryRoot.Dir.backup ~inn:tmp_dir dir in - OpamRepositoryRoot.Dir.copy ~src:dir ~dst:target; - fun () -> OpamRepositoryRoot.Dir.copy ~src:target ~dst:dir) + let backup = OpamRepositoryRoot.backup ~inn repo_root in + OpamRepositoryRoot.copy ~src:repo_root ~dst:backup; + let restore_backup () = + OpamRepositoryRoot.copy ~src:backup ~dst:repo_root in let rt = OpamRepositoryCommand.set_url rt name url trust_anchors in let failed, rt = OpamRepositoryCommand.update_with_auto_upgrade rt [name] in OpamRepositoryState.drop rt; - if failed <> [] then - (let repo = OpamRepositoryState.get_repo rt0 name in + (match failed with + | [] -> `Ok () + | _ -> + let repo = OpamRepositoryState.get_repo rt0 name in OpamConsole.error "Fetching repository %s with %s fails, reverting to %s" (OpamRepositoryName.to_string name) @@ -2558,10 +2557,9 @@ let repository cli = let rt = OpamRepositoryCommand.set_url rt0 name repo.repo_url repo.repo_trust in - backup (); + restore_backup (); OpamRepositoryState.drop rt; - OpamStd.Sys.exit_because `Sync_error); - `Ok () + OpamStd.Sys.exit_because `Sync_error) | Some `set_repos, names -> let names = List.map OpamRepositoryName.of_string names in OpamGlobalState.with_ `Lock_none @@ fun gt -> @@ -2740,7 +2738,7 @@ let switch cli = lists installed switches, with one switch argument, defaults to \ $(b,set)."; `P (Printf.sprintf - "Switch handles $(i,SWITCH) can be either a plain name, for switches \ + "Switch handles $(i,SWITCH) can be either a plain name, for switches \ that will be held inside $(i,~%s.opam), or a directory name, which in \ that case is the directory where the switch prefix will be installed, as \ %s. Opam will automatically select a switch by that name found in the \ @@ -2764,7 +2762,7 @@ let switch cli = mk_subdoc ~cli ~defaults:["","list";"SWITCH","set"] ~extra_defaults:[ cli_from cli2_2, "-", - "Switches back to the previous non-local switch (similar to $(b,git switch -)). \ + "Switches back to the previous non-local switch (similar to $(b,git switch -)). \ To set the current switch to a switch named $(i,-) use $(b,--cli=2.1) \ or lower, or use $(b,opam switch set -)" ] commands @@ -3999,19 +3997,26 @@ let lint cli = | None -> raise Not_found else let opam = OpamSwitchState.opam st nv in - match OpamPinned.orig_opam_file st (OpamPackage.name nv) opam with + match OpamPinned.orig_opam_file st name opam with | None -> raise Not_found | Some file -> - let label = - let reponame = + let repo, label = + let repo, reponame = match OpamFile.OPAM.metadata_dir opam with - | None | Some (None, _) -> "repo" - | Some (Some repo, _) -> OpamRepositoryName.to_string repo + | None | Some (None, _) -> None, "repo" + | Some (Some repo, _) -> + Some repo, + OpamRepositoryName.to_string repo in + repo, Printf.sprintf "<%s>/%s" reponame (OpamPackage.to_string nv) in - [`pkg (file, label)] + match repo with + | None -> [`pkg (file, label)] + | Some repo -> + let repo_root = OpamRepositoryState.get_root st.switch_repos repo in + [`repopkg (repo_root, file, label)] with Not_found -> OpamConsole.error_and_exit `Not_found "No opam file found for %s%s" (OpamPackage.Name.to_string (fst pkg)) @@ -4045,6 +4050,10 @@ let lint cli = OpamFileTools.lint_file ~check_upstream ~handle_dirname:false file, Some label + | `repopkg (repo_root, file, label) -> + OpamFileTools.lint_repo_package repo_root ~check_upstream + ~handle_dirname:false file, + Some label | `stdin -> OpamFileTools.lint_channel ~check_upstream ~handle_dirname:false stdin_f stdin, @@ -4129,9 +4138,9 @@ let clean cli = let download_cache = mk_flag ~cli cli_original ["c"; "download-cache"] (Printf.sprintf - "Clear the cache of downloaded files (\\$OPAMROOT%sdownload-cache), as \ - well as the obsolete \\$OPAMROOT%sarchives, if that exists." - OpamArg.dir_sep OpamArg.dir_sep) + "Clear the cache of downloaded files (\\$OPAMROOT%sdownload-cache), as \ + well as the obsolete \\$OPAMROOT%sarchives, if that exists." + OpamArg.dir_sep OpamArg.dir_sep) in let repos = mk_flag ~cli cli_original ["unused-repositories"] @@ -4364,7 +4373,8 @@ let clean cli = rmdir (OpamRepositoryRoot.Dir.to_dir (OpamRepositoryRoot.Dir.Path.root root r)); - rm (OpamRepositoryPath.tar root r)) + rm (OpamRepositoryRoot.Tgz.to_file + (OpamRepositoryRoot.Tgz.Path.root root r))) unused_repos; let repos_config = OpamRepositoryName.Map.filter diff --git a/src/client/opamListCommand.ml b/src/client/opamListCommand.ml index fa4dacb3f1a..917d932d5af 100644 --- a/src/client/opamListCommand.ml +++ b/src/client/opamListCommand.ml @@ -875,11 +875,13 @@ let info st ~fields ~raw ~where ?normalise ?(show_empty=false) let repo_dir = OpamRepositoryRoot.Dir.Path.root st.switch_global.root repo in - let tar = OpamRepositoryPath.tar st.switch_global.root repo in - if OpamFilename.exists tar && + let tgz = + OpamRepositoryRoot.Tgz.Path.root st.switch_global.root repo + in + if OpamRepositoryRoot.Tgz.exists tgz && not (OpamRepositoryRoot.Dir.exists repo_dir) then Printf.sprintf "<%s>%s%s" - (OpamFilename.to_string tar) + (OpamRepositoryRoot.Tgz.to_string tgz) Filename.dir_sep rdir else diff --git a/src/client/opamRepositoryCommand.ml b/src/client/opamRepositoryCommand.ml index 1bf33288894..4aad4341784 100644 --- a/src/client/opamRepositoryCommand.ml +++ b/src/client/opamRepositoryCommand.ml @@ -81,13 +81,10 @@ let add rt name url trust_anchors = let repo = { repo_name = name; repo_url = url; repo_trust = trust_anchors; } in - let repo_root = OpamRepositoryRoot.Dir.Path.root root name in - if OpamRepositoryRoot.Dir.exists repo_root || - OpamFilename.exists (OpamRepositoryPath.tar root name) - then + if OpamRepositoryRoot.root_exists root name then OpamConsole.error_and_exit `Bad_arguments "Invalid repository name, %s exists" - (OpamRepositoryRoot.Dir.to_string repo_root); + (OpamRepositoryName.to_string name); if url.OpamUrl.backend = `rsync && OpamUrl.local_dir url <> None && OpamUrl.local_dir (OpamRepositoryPath.Remote.packages_url url) @@ -106,10 +103,7 @@ let remove rt name = update_repos_config rt (OpamRepositoryName.Map.remove name rt.repositories) in OpamRepositoryState.Cache.save rt; - OpamRepositoryRoot.Dir.remove - (OpamRepositoryRoot.Dir.Path.root rt.repos_global.root name); - OpamFilename.remove - (OpamRepositoryPath.tar rt.repos_global.root name); + OpamRepositoryRoot.remove_both rt.repos_global.root name; rt let set_url rt name url trust_anchors = @@ -120,12 +114,8 @@ let set_url rt name url trust_anchors = OpamConsole.error_and_exit `Not_found "No repository %s found" (OpamRepositoryName.to_string name); in - OpamRepositoryRoot.Dir.remove - (OpamRepositoryRoot.Dir.Path.root rt.repos_global.root name); - OpamFilename.remove - (OpamRepositoryPath.tar rt.repos_global.root name); + OpamRepositoryRoot.remove_both rt.repos_global.root name; let repo = { repo with repo_url = url; repo_trust = trust_anchors; } in - OpamRepositoryState.remove_from_repos_tmp rt name; update_repos_config rt (OpamRepositoryName.Map.add name repo rt.repositories) let print_selection rt ~short repos_list = @@ -259,22 +249,15 @@ let update_with_auto_upgrade rt repo_names = OpamRepositoryState.Cache.remove ()); OpamConsole.msg "Upgrading repository \"%s\"...\n" (OpamRepositoryName.to_string r.repo_name); - let repo_root = - match OpamRepositoryState.get_repo_root rt r with - | OpamRepositoryRoot.Dir x -> x + let repo_root = OpamRepositoryState.get_repo_root rt r in + OpamRepositoryRoot.on_dir (fun dir -> + OpamAdminRepoUpgrade.do_upgrade (OpamRepositoryRoot.Dir.of_dir dir)) + repo_root; + let def, opams = + OpamRepositoryState.load_repo r repo_root in - OpamAdminRepoUpgrade.do_upgrade repo_root; - if OpamRepositoryConfig.(!r.repo_tarring) then - OpamRepositoryRoot.make_tar_gz - (OpamRepositoryPath.tar rt.repos_global.root r.repo_name) - repo_root; let def = - OpamRepositoryRoot.Dir.Path.repo repo_root - |> OpamFile.Repo.safe_read - |> OpamFile.Repo.with_root_url r.repo_url - in - let opams = - OpamRepositoryState.load_opams_from_dir r.repo_name repo_root + OpamFile.Repo.with_root_url r.repo_url def in let rt = { rt with diff --git a/src/format/opamRepositoryPath.ml b/src/format/opamRepositoryPath.ml index 711c65d0874..45911309cce 100644 --- a/src/format/opamRepositoryPath.ml +++ b/src/format/opamRepositoryPath.ml @@ -87,7 +87,7 @@ end (* Other paths *) -let tar root name = +let repo_tarring root name = root / OpamRepositoryPathName.repo_d // (OpamRepositoryName.to_string name ^ ".tar.gz") diff --git a/src/format/opamRepositoryPath.mli b/src/format/opamRepositoryPath.mli index 5433ab80425..2d837fc9e1f 100644 --- a/src/format/opamRepositoryPath.mli +++ b/src/format/opamRepositoryPath.mli @@ -104,7 +104,8 @@ module Make (I : PATH_REPR) : PATH (* {2} Other paths *) -val tar: dirname -> repository_name -> filename +(** obsolete, no longer used *) +val repo_tarring: dirname -> repository_name -> filename (** Prefix where to store the downloaded files cache: {i $opam/download-cache}. Warning, this is relative to the opam root, not a repository root. *) diff --git a/src/repository/opamHTTP.ml b/src/repository/opamHTTP.ml index caa3b62dff5..dab12c47cca 100644 --- a/src/repository/opamHTTP.ml +++ b/src/repository/opamHTTP.ml @@ -21,12 +21,18 @@ let remote_index_archive url = OpamUrl.Op.(url / index_archive_name) let sync_state name repo_root url = OpamFilename.with_tmp_dir_job @@ fun dir -> - let local_index_archive = OpamFilename.Op.(dir // index_archive_name) in - OpamDownload.download_as ~quiet:true ~overwrite:true + let local_index_archive = + OpamRepositoryRoot.Tgz.of_file + OpamFilename.Op.(dir // index_archive_name) + in + OpamRepositoryRoot.Tgz.download_as ~quiet:true ~overwrite:true (remote_index_archive url) local_index_archive @@+ fun () -> match repo_root with + | OpamRepositoryRoot.Tgz repo_root -> + OpamRepositoryRoot.Tgz.copy ~src:local_index_archive ~dst:repo_root; + Done () | OpamRepositoryRoot.Dir repo_root -> List.iter OpamFilename.rmdir (OpamRepositoryRoot.Dir.dirs repo_root); OpamProcess.Job.with_text diff --git a/src/repository/opamLocal.ml b/src/repository/opamLocal.ml index 036857360d5..450d3cd15ac 100644 --- a/src/repository/opamLocal.ml +++ b/src/repository/opamLocal.ml @@ -146,15 +146,24 @@ module B = struct let fetch_repo_update repo_name ?cache_dir:_ repo_root url = log "pull-repo-update"; - match repo_root with - | OpamRepositoryRoot.Dir repo_root -> - let quarantine = OpamRepositoryRoot.Dir.quarantine repo_root in - let finalise () = OpamRepositoryRoot.Dir.remove quarantine in - OpamProcess.Job.catch (fun e -> - finalise (); - Done (OpamRepositoryBackend.Update_err e)) - @@ fun () -> - OpamRepositoryBackend.job_text repo_name "sync" + let quarantine = OpamRepositoryRoot.quarantine repo_root in + let finalise () = OpamRepositoryRoot.remove quarantine in + let populate_quarantine () = + match repo_root, quarantine with + | OpamRepositoryRoot.Tgz _, OpamRepositoryRoot.Tgz quarantine -> + (let to_archive dir = + OpamRepositoryRoot.make_tar_gz quarantine + (OpamRepositoryRoot.Dir.of_dir dir); + Done (Result ()) + in + match OpamUrl.local_dir url with + | Some dir -> to_archive dir + | None -> + OpamFilename.with_tmp_dir_job @@ fun dir -> + pull_dir_quiet dir url @@+ function + | Result () -> to_archive dir + | exn -> Done exn) + | OpamRepositoryRoot.Dir dir, OpamRepositoryRoot.Dir quarantine -> (match OpamUrl.local_dir url with | Some dir -> let dir = OpamRepositoryRoot.Dir.of_dir dir in @@ -164,30 +173,33 @@ module B = struct OpamFilename.link_dir ~target:dir ~link:quarantine; *) Done (Result ()) | None -> - if OpamRepositoryRoot.Dir.exists repo_root then - OpamRepositoryRoot.Dir.copy_except_vcs - ~src:repo_root ~dst:quarantine + if OpamRepositoryRoot.Dir.exists dir then + OpamRepositoryRoot.Dir.copy_except_vcs ~src:dir ~dst:quarantine else OpamRepositoryRoot.Dir.make_empty quarantine; pull_dir_quiet (OpamRepositoryRoot.Dir.to_dir quarantine) url) - @@+ function - | Not_available (_, msg) -> + (* we have the guarantee that repo root and quarantine have the same kind *) + | _, _ -> assert false + in + OpamProcess.Job.catch (fun e -> finalise (); - Done (OpamRepositoryBackend.Update_err (Failure ("rsync error: " ^ msg))) - | Up_to_date () -> - finalise (); Done OpamRepositoryBackend.Update_empty - | Result () -> - if OpamRepositoryRoot.Dir.is_empty repo_root <> Some false then - Done (OpamRepositoryBackend.Update_full - (OpamRepositoryRoot.Dir quarantine)) - else - OpamStd.Exn.finally finalise @@ fun () -> - OpamRepositoryBackend.get_diff - (OpamRepositoryRoot.Dir repo_root) - (OpamRepositoryRoot.Dir quarantine) - |> function - | None -> Done OpamRepositoryBackend.Update_empty - | Some p -> Done (OpamRepositoryBackend.Update_patch p) + Done (OpamRepositoryBackend.Update_err e)) @@ fun () -> + OpamRepositoryBackend.job_text repo_name "sync" + (populate_quarantine ()) @@| function + | Not_available (_, msg) -> + finalise (); + OpamRepositoryBackend.Update_err (Failure ("rsync error: " ^ msg)) + | Up_to_date () -> + finalise (); OpamRepositoryBackend.Update_empty + | Result () -> + if OpamRepositoryRoot.is_empty repo_root <> Some false then + OpamRepositoryBackend.Update_full quarantine + else + OpamStd.Exn.finally finalise @@ fun () -> + OpamRepositoryBackend.get_diff repo_root quarantine + |> function + | None -> OpamRepositoryBackend.Update_empty + | Some p -> OpamRepositoryBackend.Update_patch p let repo_update_complete _ _ = Done () diff --git a/src/repository/opamRepositoryBackend.ml b/src/repository/opamRepositoryBackend.ml index fdbc35eb14b..44b885c195b 100644 --- a/src/repository/opamRepositoryBackend.ml +++ b/src/repository/opamRepositoryBackend.ml @@ -103,11 +103,20 @@ let get_diff repo1 repo2 = (OpamFilename.Base.to_string (OpamRepositoryRoot.basename repo1)) (OpamFilename.Base.to_string (OpamRepositoryRoot.basename repo2)) else - Format.fprintf fmt "%s vs %s" + let prefix r = if OpamRepositoryRoot.is_tgz r then "tgz" else "dir" in + Format.fprintf fmt "%s %s vs %s %s" + (prefix repo1) (OpamRepositoryRoot.to_string repo1) + (prefix repo2) (OpamRepositoryRoot.to_string repo2)) (); let get_contents = + let get_tgz_contents tgz = + OpamRepositoryRoot.Tgz.fold (fun acc filename content -> + OpamStd.String.Map.add + (OpamFilename.Unix.to_string filename) content acc) + OpamStd.String.Map.empty tgz + in let read_dir_contents dir = let fail s = failwith (s ^ " are unsupported") in (* Recursively read directory contents into a string map. @@ -140,6 +149,8 @@ let get_diff repo1 repo2 = function | OpamRepositoryRoot.Dir dir -> read_dir_contents (OpamRepositoryRoot.Dir.to_string dir) + | OpamRepositoryRoot.Tgz tgz -> + get_tgz_contents tgz in let contents1 = get_contents repo1 in let contents2 = get_contents repo2 in diff --git a/src/repository/opamRepositoryBackend.mli b/src/repository/opamRepositoryBackend.mli index 04c5b9a1e7b..c50b4f315dc 100644 --- a/src/repository/opamRepositoryBackend.mli +++ b/src/repository/opamRepositoryBackend.mli @@ -108,9 +108,9 @@ val check_digest: filename -> OpamHash.t option -> bool val job_text: repository_name -> string -> 'a OpamProcess.job -> 'a OpamProcess.job -(** [get_diff dir1 dir2] computes the diff between the two directories, - returns None if they are equal, and the corresponding patch and the list of - file-changes otherwise. +(** [get_diff dir1 dir2] computes the diff between the two repository root + (directory or tar gz archive), returns None if they are equal, and the + corresponding patch and the list of file-changes otherwise. @raise Stdlib.Failure if an unsupported file type or comparison is detected in any of [subdir1] or [subdir2]. diff --git a/src/repository/opamRepositoryRoot.ml b/src/repository/opamRepositoryRoot.ml index 3646b49eeef..d3407724c8a 100644 --- a/src/repository/opamRepositoryRoot.ml +++ b/src/repository/opamRepositoryRoot.ml @@ -56,62 +56,154 @@ module Dir = struct end -let make_tar_gz = OpamTar.create ~flat:false ~except_vcs:false +module Tgz = struct + type t = OpamFilename.t + + let of_file = Fun.id + let to_file = Fun.id + let to_string = OpamFilename.to_string + + let quarantine tar = OpamFilename.raw (to_string tar ^ ".new") + let backup ~inn tar = + OpamFilename.create inn (OpamFilename.basename tar) + + let exists = OpamFilename.exists + let remove = OpamFilename.remove + let extract_in = OpamFilename.extract_in + let download_as = OpamDownload.download_as + let copy = OpamFilename.copy + let move = OpamFilename.move + let is_symlink = OpamFilename.is_symlink + + let fold = OpamTar.fold_reg_files + + let patch ~allow_unclean patch_source tar = + let patch_source = + match patch_source with + | `Patch_file f -> `Patch_file (OpamFilename.to_string f) + | `Patch_diffs _ as d -> d + in + OpamTar.patch ~allow_unclean patch_source tar + + let filter_files cond t = + fold (fun acc file content -> + if cond file then (file,content)::acc else acc) + [] t + + let is_empty t = + if exists t then + let empty = + try + fold (fun _ _ _ -> raise Exit) true t + with Exit -> false + in + Some empty + else None + + module Path = OpamRepositoryPath.Make (struct + type root = t + type file = unix_filename + type dir = unix_dirname + type 'a typed_file = 'a OpamFile.t + module Op = OpamFilename.Unix.Op + let root root name = + let open OpamFilename.Op in + of_file (root / OpamRepositoryPathName.repo_d + // (OpamRepositoryName.to_string name ^ ".tar.gz")) + let absolute _root f = OpamFilename.Unix.of_string f + let absolute_dir _root d = d + let dir_of_string = OpamFilename.Unix.Dir.of_string + let to_typed_file f = OpamFile.make (OpamFilename.Unix.to_filename f) + end) + +end + +let make_tar_gz = OpamTar.create ~flat:true ~except_vcs:true let extract_in_job = OpamFilename.extract_in_job type t = | Dir of Dir.t + | Tgz of Tgz.t let quarantine = function | Dir dir -> Dir (Dir.quarantine dir) + | Tgz tgz -> Tgz (Tgz.quarantine tgz) let backup ~inn = function | Dir dir -> Dir (Dir.backup ~inn dir) + | Tgz tgz -> Tgz (Tgz.backup ~inn tgz) let remove = function | Dir dir -> Dir.remove dir + | Tgz tgz -> Tgz.remove tgz let is_empty = function | Dir dir -> Dir.is_empty dir + | Tgz tgz -> Tgz.is_empty tgz let make_empty = function | Dir dir -> Dir.make_empty dir + | Tgz _tar -> () (* Creating an empty tgz file doesn't make sense *) let dirname = function | Dir dir -> OpamFilename.dirname_dir (Dir.to_dir dir) + | Tgz tgz -> OpamFilename.dirname (Tgz.to_file tgz) let basename = function | Dir dir -> OpamFilename.basename_dir (Dir.to_dir dir) + | Tgz tgz -> OpamFilename.basename (Tgz.to_file tgz) let to_string = function | Dir dir -> Dir.to_string dir + | Tgz tgz -> Tgz.to_string tgz let remove_prefix file = function | Dir dir -> OpamFilename.remove_prefix dir file |> OpamFilename.raw + | Tgz _ -> file let remove_prefix_dir d = function | Dir dir -> OpamFilename.remove_prefix_dir dir d |> OpamFilename.raw_dir + | Tgz _ -> d + +let is_tgz = function + | Dir _ -> false + | Tgz _ -> true + +let is_dir = function + | Dir _ -> true + | Tgz _ -> false let copy ~src ~dst = match src, dst with | Dir src, Dir dst -> Dir.copy ~src ~dst + | Tgz src, Tgz dst -> Tgz.copy ~src ~dst + | Tgz src, Dir dst -> OpamFilename.extract_in src dst + | Dir src, Tgz dst -> make_tar_gz dst src let move ~src ~dst = match src, dst with | Dir src, Dir dst -> Dir.move ~src ~dst + | Tgz src, Tgz dst -> Tgz.move ~src ~dst + | Tgz _, Dir _ + | Dir _, Tgz _ -> + copy ~src ~dst; + remove src let exists = function | Dir dir -> Dir.exists dir + | Tgz tgz -> Tgz.exists tgz let is_symlink = function | Dir dir -> Dir.is_symlink dir + | Tgz tgz -> Tgz.is_symlink tgz let patch ~allow_unclean patch = function | Dir dir -> Dir.patch ~allow_unclean patch dir + | Tgz tgz -> Tgz.patch ~allow_unclean patch tgz let read_file (type a) (module R : OpamFile.IO_FILE with type t = a) ?(safe=false) repo_root @@ -130,3 +222,41 @@ let delayed_read_repo = function in let read () = OpamFile.Repo.safe_read repo_file_path in (OpamFile.exists repo_file_path, read) + | Tgz tgz -> + let repo_content = + let exception Found of string in + let repo = OpamFilename.Unix.of_string OpamRepositoryPathName.repo_f in + try + Tgz.fold (fun () fname content -> + if OpamFilename.Unix.equal fname repo then + raise (Found content)) + () (Tgz.to_file tgz); + None + with Found content -> Some content + in + let read () = + match repo_content with + | None -> OpamFile.Repo.empty + | Some content -> + try OpamFile.Repo.read_from_string content + with _ -> OpamFile.Repo.empty + in + (Option.is_some repo_content, read) + +let remove_both root name = + remove (Tgz (Tgz.Path.root root name)); + remove (Dir (Dir.Path.root root name)) + +let on_dir f = function + | Dir dir -> f dir + | Tgz tgz -> + OpamFilename.with_tmp_dir (fun dir -> + Tgz.extract_in tgz dir; + let repo_dir = Dir.of_dir dir in + let res = f repo_dir in + make_tar_gz tgz repo_dir; + res) + +let root_exists root name = + exists (Tgz (Tgz.Path.root root name)) + || exists (Dir (Dir.Path.root root name)) diff --git a/src/repository/opamRepositoryRoot.mli b/src/repository/opamRepositoryRoot.mli index 83a8d39c374..29c683b4ec8 100644 --- a/src/repository/opamRepositoryRoot.mli +++ b/src/repository/opamRepositoryRoot.mli @@ -55,11 +55,49 @@ module Dir : sig end -val make_tar_gz : filename -> Dir.t -> unit -val extract_in_job : filename -> Dir.t -> exn option OpamProcess.job +module Tgz : sig + type t + + val of_file : filename -> t + val to_file : t -> filename + val to_string : t -> string + + val quarantine : t -> t + val backup : inn:dirname -> t -> t + + val exists : t -> bool + val remove : t -> unit + val extract_in : t -> dirname -> unit + val download_as : + ?quiet:bool -> + ?validate:bool -> + overwrite:bool -> + ?compress:bool -> + ?checksum:OpamHash.t -> + OpamUrl.t -> t -> unit OpamProcess.job + val copy : src:t -> dst:t -> unit + val move : src:t -> dst:t -> unit + + val filter_files: + (OpamTar.archived_file -> bool) -> t -> + (OpamTar.archived_file * OpamTar.archived_file_content) list + val fold: + ('a -> OpamTar.archived_file -> OpamTar.archived_file_content -> 'a) -> + 'a -> t -> 'a + + (* Repository paths *) + module Path : OpamRepositoryPath.PATH + with type repo_root = t + and type repo_dirname = unix_dirname + and type 'a typed_file = 'a OpamFile.t +end + +val make_tar_gz : Tgz.t -> Dir.t -> unit +val extract_in_job : Tgz.t -> Dir.t -> exn option OpamProcess.job type t = | Dir of Dir.t + | Tgz of Tgz.t (** [quarantine repo_root] returns a temporary repository root dedicated to [repo_root]. the returned repository is not created on disk and @@ -80,6 +118,9 @@ val to_string : t -> string val remove_prefix: filename -> t -> filename val remove_prefix_dir: dirname -> t -> dirname +val is_tgz: t -> bool +val is_dir: t -> bool + val copy : src:t -> dst:t -> unit val move : src:t -> dst:t -> unit @@ -108,3 +149,13 @@ val patch : (** Returns a pair [(exists, f)] where [exists] tells whether the [repo] file exists in the repository and [f] reads it *) val delayed_read_repo : t -> bool * (unit -> OpamFile.Repo.t) + +(** TAR TODOC remove directory and archive, if present *) +val remove_both : dirname -> repository_name -> unit + +(** Applies the function in the repository root directory. If repository root + is an archive, it uncompress it, applies the function and update archive + with the changed directory. *) +val on_dir: (dirname -> 'a) -> t -> 'a + +val root_exists : dirname -> repository_name -> bool diff --git a/src/repository/opamVCS.ml b/src/repository/opamVCS.ml index a6bf64c2969..03b85f3cfcd 100644 --- a/src/repository/opamVCS.ml +++ b/src/repository/opamVCS.ml @@ -81,6 +81,8 @@ module Make (VCS: VCS) = struct VCS.reset_tree (OpamRepositoryRoot.Dir.to_dir tmpdir) repo_url @@| fun () -> OpamRepositoryBackend.Update_full (OpamRepositoryRoot.Dir tmpdir) + | OpamRepositoryRoot.Tgz _ -> + assert false (* VCS repository are always repositories *) let repo_update_complete repo_root url = match repo_root with @@ -88,6 +90,8 @@ module Make (VCS: VCS) = struct VCS.patch_applied (OpamRepositoryRoot.Dir.to_dir repo_root) url @@+ fun () -> Done () + | OpamRepositoryRoot.Tgz _ -> + assert false (* VCS repository are always repositories *) let pull_url ?full_fetch ?cache_dir ?subpath dirname checksum url = if checksum <> None then invalid_arg "VC pull_url doesn't allow checksums"; diff --git a/src/state/opamFileTools.ml b/src/state/opamFileTools.ml index 0a00d7e8622..deb4f0b2ccc 100644 --- a/src/state/opamFileTools.ml +++ b/src/state/opamFileTools.ml @@ -1127,7 +1127,7 @@ let t_lint ?check_extra_files ?(check_upstream=false) ?(all=false) t = let lint = t_lint ~all:false -let extra_files_default filename = +let extra_files_default_dir filename = let dir = OpamFilename.Op.(OpamFilename.dirname (OpamFile.filename filename) / OpamPathName.files_d) @@ -1138,6 +1138,35 @@ let extra_files_default filename = OpamHash.check_file (OpamFilename.to_string f)) (OpamFilename.rec_files dir) +let extra_files_default_tgz tar filename = + (* As [OpamPinned.orig_opam_file] writes the package in [TMPDIR], we need to + remove the temp_file prefix *) + let filename = + let rec aux filename = + match OpamFilename.Unix.root_dir filename with + | Some p when String.equal p OpamRepositoryPathName.packages_d -> filename + | None -> filename + | Some dir -> + let filename = + (OpamFilename.Unix.of_string + (OpamFilename.Unix.remove_prefix + (OpamFilename.Unix.Dir.of_string dir) filename)) + in + aux filename + in + aux (OpamFilename.Unix.of_filename (OpamFile.filename filename)) + in + let dir = + OpamFilename.Unix.Op.(OpamFilename.Unix.dirname filename + / OpamRepositoryPathName.files_d) + in + List.map + (fun (f,c) -> + OpamFilename.Base.of_string (OpamFilename.Unix.remove_prefix dir f), + OpamHash.check_string c) + (OpamRepositoryRoot.Tgz.filter_files + (OpamFilename.Unix.starts_with dir) tar) + let lint_gen ?check_extra_files ?check_upstream ?(handle_dirname=false) reader filename = let warnings, t = @@ -1208,7 +1237,9 @@ let lint_gen ?check_extra_files ?check_upstream ?(handle_dirname=false) | OpamPp.Bad_format_list bfl -> List.map warn_of_bad_format bfl, None in let check_extra_files = match check_extra_files with - | None -> extra_files_default filename + | None -> extra_files_default_dir filename + (* We keep with directory call bc it is not called via [lint_repo_package], + so it doesn't need to handle another layout than dir *) | Some f -> f in warnings @ (match t with Some t -> lint ~check_extra_files ?check_upstream t | None -> []), @@ -1228,6 +1259,21 @@ let lint_file ?check_extra_files ?check_upstream ?handle_dirname filename = in lint_gen ?check_extra_files ?check_upstream ?handle_dirname reader filename +let lint_repo_package repo_root ?check_extra_files ?check_upstream ?handle_dirname + filename = + let check_extra_files = + match check_extra_files with + | Some cef -> cef + | None -> + let extra_files = + match repo_root with + | OpamRepositoryRoot.Dir _ -> extra_files_default_dir + | OpamRepositoryRoot.Tgz tgz -> extra_files_default_tgz tgz + in + extra_files filename + in + lint_file ~check_extra_files ?check_upstream ?handle_dirname filename + let lint_channel ?check_extra_files ?check_upstream ?handle_dirname filename ic = let reader filename = OpamFile.Syntax.of_channel filename ic in @@ -1284,8 +1330,6 @@ let warns_to_json ?filename ws = (* Package definition loading *) open OpamFilename.Op -open OpamStd.Option.Op - let try_read rd f = try rd f, None with @@ -1307,7 +1351,7 @@ let try_read rd f = let f = OpamFile.filename f in Some (OpamFilename.(Base.to_string (basename f)), bf) -let add_aux_files ?dir ?(files_subdir_hashes=false) opam = +let add_aux_files_t ?dir_label ?dir ?(files_subdir_hashes=false) opam xfs = let dir = match dir with | None -> (match OpamFile.OPAM.metadata_dir opam with @@ -1321,17 +1365,40 @@ let add_aux_files ?dir ?(files_subdir_hashes=false) opam = match dir with | None -> opam | Some dir -> - let (url_file: OpamFile.URL_legacy.t OpamFile.t) = + let string_of_dir = + match dir_label with + | Some repo_root -> + fun d -> + Printf.sprintf "%s (out of %s)" + (OpamFilename.Dir.to_string d) + (OpamRepositoryRoot.to_string repo_root) + | None -> OpamFilename.Dir.to_string + in + let url_file : OpamFile.URL_legacy.t OpamFile.t = OpamFile.make (dir // "url") in - let (descr_file: OpamFile.Descr_legacy.t OpamFile.t) = + let descr_file : OpamFile.Descr_legacy.t OpamFile.t = OpamFile.make (dir // "descr") in - let files_dir = - OpamFilename.Op.(dir / OpamRepositoryPathName.files_d) + let files_dir = OpamFilename.Op.(dir / "files") in + let try_read (type a) (module R: OpamFile.IO_FILE with type t = a) + : a OpamFile.t -> a option * (string * OpamPp.bad_format) option = + let reader = + match dir_label with + | Some repo_root -> + OpamRepositoryRoot.read_file (module R) ~safe:false repo_root + | None -> R.read_from_string ?loc:None + in + fun f -> + match OpamFilename.Unix.Map.find_opt + (OpamFilename.Unix.of_filename (OpamFile.filename f)) xfs with + | Some content -> + let reader f = Some (reader ~filename:f (Lazy.force content)) in + try_read reader f + | None -> None, None in let opam = - match OpamFile.OPAM.url opam, try_read OpamFile.URL_legacy.read_opt url_file with + match OpamFile.OPAM.url opam, try_read (module OpamFile.URL_legacy) url_file with | None, (Some url, None) -> OpamFile.OPAM.with_url (OpamFile.URL.of_legacy url) opam | Some opam_url, (Some url, errs) -> @@ -1350,7 +1417,7 @@ let add_aux_files ?dir ?(files_subdir_hashes=false) opam = in let opam = match OpamFile.OPAM.descr opam, - try_read OpamFile.Descr_legacy.read_opt descr_file with + try_read (module OpamFile.Descr_legacy) descr_file with | None, (Some descr, None) -> OpamFile.OPAM.with_descr (OpamFile.Descr.of_legacy descr) opam | Some _, (Some _, _) -> @@ -1363,13 +1430,21 @@ let add_aux_files ?dir ?(files_subdir_hashes=false) opam = in let opam = let extra_files = - OpamFilename.opt_dir files_dir >>| fun dir -> - OpamFilename.rec_files dir - |> List.map (fun file -> - file, - OpamFilename.Base.of_string - (OpamSystem.back_to_forward - (OpamFilename.remove_prefix dir file))) + let xfiles = + let files_dir = OpamFilename.Unix.Dir.of_dir files_dir in + OpamFilename.Unix.Map.fold (fun file content ef -> + if OpamFilename.Unix.starts_with files_dir file then + let basename = + file + |> OpamFilename.Unix.remove_prefix files_dir + |> OpamFilename.Base.of_string + in + (basename, Lazy.force content)::ef + else ef) xfs [] + in + match List.rev xfiles with + | [] -> None + | ef -> Some ef in match OpamFile.OPAM.extra_files opam, extra_files with | None, None -> opam @@ -1378,17 +1453,15 @@ let add_aux_files ?dir ?(files_subdir_hashes=false) opam = log ?level "Missing extra-files field for %a for %a, %s them." (slog @@ OpamStd.List.concat_map ", " - (fun (_,f) -> OpamFilename.Base.to_string f)) ef + (fun (f,_) -> OpamFilename.Base.to_string f)) ef OpamStd.Op.(slog @@ OpamPackage.to_string @* OpamFile.OPAM.package) opam act in if files_subdir_hashes then (log ~level:2 "adding"; let ef = - List.map - (fun (file, basename) -> - basename, - OpamHash.compute (OpamFilename.to_string file)) + List.map (fun (basename, content) -> + basename, OpamHash.compute_from_string content) ef in OpamFile.OPAM.with_extra_files ef opam) @@ -1396,30 +1469,30 @@ let add_aux_files ?dir ?(files_subdir_hashes=false) opam = (log "ignoring"; opam) | Some ef, None -> - log "Missing expected extra files %s at %s/files" + log "Missing expected extra files %s at %s" (OpamStd.List.concat_map ", " (fun (f,_) -> OpamFilename.Base.to_string f) ef) - (OpamFilename.Dir.to_string dir); + (string_of_dir files_dir); opam | Some oef, Some ef -> let wr_check, nf_opam, rest = - List.fold_left (fun (wr_check, nf_opam, rest) (file, basename) -> + List.fold_left (fun (wr_check, nf_opam, rest) (basename, content) -> match OpamStd.List.pick_assoc OpamFilename.Base.equal basename rest with | None, rest -> wr_check, (basename::nf_opam), rest | Some ohash, rest -> - (if OpamHash.check_file (OpamFilename.to_string file) ohash then + (if OpamHash.check_string content ohash then wr_check else basename::wr_check), - nf_opam, rest - ) ([], [], oef) ef + nf_opam, rest) + ([], [], oef) ef in let nf_file = List.map fst rest in if nf_file <> [] || wr_check <> [] || nf_opam <> [] then log "Mismatching extra-files at %s: %s" - (OpamFilename.Dir.to_string dir) + (string_of_dir dir) ((if nf_file = [] then None else Some (Printf.sprintf "missing from 'files' directory (%d)" (List.length nf_file))) @@ -1436,16 +1509,72 @@ let add_aux_files ?dir ?(files_subdir_hashes=false) opam = in opam -let read_opam dir = - let (opam_file: OpamFile.OPAM.t OpamFile.t) = - OpamFile.make (dir // OpamPathName.opam_f) +(* get_ extra files data from a system directory *) +let get_extrafiles ~repo_root dir = + let to_key = + match repo_root with + | Some repo_root -> + fun file -> + OpamRepositoryRoot.remove_prefix file repo_root + | None -> Fun.id in - match try_read OpamFile.OPAM.read_opt opam_file with - | Some opam, None -> Some (add_aux_files ~dir ~files_subdir_hashes:false opam) + List.fold_left (fun map file -> + OpamFilename.Unix.Map.add (OpamFilename.Unix.of_filename (to_key file)) + (lazy (OpamFilename.read file)) map) + OpamFilename.Unix.Map.empty (OpamFilename.rec_files dir) + +let get_contents ~repo_root dir = + let file = OpamFilename.Op.(dir // OpamPathName.opam_f) in + let content = lazy (OpamFilename.read file) in + let xfs = get_extrafiles ~repo_root dir in + file, content, xfs + +let add_aux_files ?dir ?files_subdir_hashes opam = + let dir = match dir with + | None -> + (match OpamFile.OPAM.metadata_dir opam with + | None -> None + | Some (None, dir) -> + Some (OpamFilename.Dir.of_string dir) + | Some (Some r, _) -> + failwith ("Repository "^OpamRepositoryName.to_string r^ + " not registered for add_aux_files!")) + | some -> some + in + match dir with + | None -> opam + | Some dir -> + (* We are in the case of an absolute dir here *) + let xfs = get_extrafiles ~repo_root:None dir in + add_aux_files_t ~dir ?files_subdir_hashes opam xfs + +let read_opam_t ?dir_label dir filename content xfs = + let opam_file = OpamFile.make filename in + let filename = OpamFile.make filename in + let rd = + let loc = Option.map OpamRepositoryRoot.to_string dir_label in + fun f -> + try + Some (OpamFile.OPAM.read_from_string + ?loc ?filename:(Some f) (Lazy.force content)) + with OpamSystem.File_not_found _ -> None + in + let string_of_opamfile = + match dir_label with + | Some repo_root -> + fun f -> + Printf.sprintf "%s (out of %s)" + (OpamFile.to_string f) + (OpamRepositoryRoot.to_string repo_root) + | None -> OpamFile.to_string + in + match try_read rd filename with + | Some opam, None -> + Some (add_aux_files_t ?dir_label ~dir ~files_subdir_hashes:false opam xfs) | _, Some err -> OpamConsole.warning "Could not read file %s. skipping:\n%s" - (OpamFile.to_string opam_file) + (string_of_opamfile opam_file) (OpamPp.string_of_bad_format (OpamPp.Bad_format (snd err))); None | None, None -> None @@ -1453,7 +1582,7 @@ let read_opam dir = let sversion = OpamVersion.to_string version in let scurrent = OpamVersion.to_string OpamVersion.current_nopatch in log "opam-version %S unsupported on %s. Added as dummy unavailable package." - sversion (OpamFile.to_string opam_file); + sversion (string_of_opamfile opam_file); Some (OpamFile.OPAM.empty |> OpamFile.OPAM.with_available @@ -1467,13 +1596,34 @@ let read_opam dir = upgrade your opam installation to at least version %s." sversion scurrent sversion)) -let read_repo_opam ~repo_name ~repo_root dir = +let read_opam dir = + let file, content, xfs = get_contents ~repo_root:None dir in + read_opam_t dir file content xfs + +let read_repo_opam_t ~repo_name ~repo_root dir file content xfs = let open OpamStd.Option.Op in - read_opam dir >>| - OpamFile.OPAM.with_metadata_dir - (Some (Some repo_name, - OpamFilename.remove_prefix_dir - (OpamRepositoryRoot.Dir.to_dir repo_root) dir)) + let rel = OpamFilename.Dir.to_string dir in + read_opam_t ~dir_label:repo_root dir file content xfs + >>| OpamFile.OPAM.with_metadata_dir + (Some (Some repo_name, rel)) + +let read_repo_opam_tgz ~repo_name ~repo_root dir file content xfs = + let file = OpamFilename.Unix.to_filename file in + let dir = OpamFilename.Unix.Dir.to_dir dir in + let repo_root = OpamRepositoryRoot.Tgz repo_root in + let xfs = OpamFilename.Unix.Map.map Lazy.from_val xfs in + read_repo_opam_t ~repo_name ~repo_root dir file (lazy content) xfs + +let read_repo_opam_dir ~repo_name ~repo_root dir = + let repo_root = OpamRepositoryRoot.Dir repo_root in + let file, content, xfs = get_contents ~repo_root:(Some repo_root) dir in + let file = OpamRepositoryRoot.remove_prefix file repo_root in + let dir = OpamRepositoryRoot.remove_prefix_dir dir repo_root in + read_repo_opam_t ~repo_name ~repo_root dir file content xfs + +let read_repo_opam ~repo_name ~root dir = + read_repo_opam_dir ~repo_name + ~repo_root:(OpamRepositoryRoot.Dir.of_dir root) dir let dep_formula_to_string f = let pp = diff --git a/src/state/opamFileTools.mli b/src/state/opamFileTools.mli index d3f2e9b5e14..8f7116d64f9 100644 --- a/src/state/opamFileTools.mli +++ b/src/state/opamFileTools.mli @@ -38,6 +38,18 @@ val lint_file: OpamFile.OPAM.t OpamFile.typed_file -> (int * [`Warning|`Error] * string) list * OpamFile.OPAM.t option +(** Same as {!lint}, but operates on an registered repository opam file. + It allows to retrieve extra files accordingly to the repository nature : + archive or directory. +*) +val lint_repo_package: + OpamRepositoryRoot.t -> + ?check_extra_files:(basename * (OpamHash.t -> bool)) list -> + ?check_upstream:bool -> + ?handle_dirname:bool -> + OpamFile.OPAM.t OpamFile.typed_file -> + (int * [`Warning|`Error] * string) list * OpamFile.OPAM.t option + (** Same as {!lint_file}, but taking input from a channel. [check_extra_files] defaults to a function that will look for a [files/] directory besides [filename] *) @@ -93,9 +105,24 @@ val read_opam: dirname -> OpamFile.OPAM.t option (** Like {!read_opam}, but additionally fills in the [metadata_dir] info correctly for the given repository. *) val read_repo_opam: + repo_name:repository_name -> root:dirname -> + dirname -> OpamFile.OPAM.t option + +(** Like {!read_opam}, but additionally fills in the [metadata_dir] info + correctly for the given directory repository root. *) +val read_repo_opam_dir: repo_name:repository_name -> repo_root:OpamRepositoryRoot.Dir.t -> dirname -> OpamFile.OPAM.t option +(** Like {!read_opam}, but additionally fills in the [metadata_dir] info + correctly for the given repository. *) +val read_repo_opam_tgz: + repo_name:repository_name -> repo_root:OpamRepositoryRoot.Tgz.t -> + OpamFilename.Unix.Dir.t -> OpamFilename.Unix.t + -> OpamTar.archived_file_content + -> OpamTar.archived_file_content OpamFilename.Unix.Map.t + -> OpamFile.OPAM.t option + (** Adds data from 'url' and 'descr' files found in the specified dir or the opam file's metadata dir, if not already present in the opam file. if [files_subdir_hashes] is [true], also adds the names and hashes of files diff --git a/src/state/opamPinned.ml b/src/state/opamPinned.ml index 4700b5a7753..fd45fd68220 100644 --- a/src/state/opamPinned.ml +++ b/src/state/opamPinned.ml @@ -283,27 +283,43 @@ let files_in_source_w_target ?locked ?recurse ?subpath (files_in_source ?locked ?recurse ?subpath dir) let orig_opam_file st name opam = - (match OpamFile.OPAM.metadata_dir opam with - | None -> None - | Some (None, abs) -> - Some (OpamFilename.Dir.of_string abs) - | Some (Some r, rel) -> - let dirname = - match OpamRepositoryState.get_root st.switch_repos r with - | OpamRepositoryRoot.Dir r -> OpamRepositoryRoot.Dir.to_dir r - in - Some (dirname / rel)) - >>= fun dir -> - let opam_files = [ - dir // (OpamPackage.Name.to_string name ^ OpamPathName.opam_suffix); - dir // OpamPathName.opam_f - ] in - let locked_files = - match OpamFile.OPAM.locked opam with - | Some locked -> - List.map (fun f -> OpamFilename.add_extension f locked) opam_files - | None -> [] - in - List.find_opt OpamFilename.exists locked_files - ++ List.find_opt OpamFilename.exists opam_files - >>| OpamFile.make + match OpamFile.OPAM.metadata_dir opam with + | None -> None + | Some (None, abs) -> (* Pin case *) + let dir = OpamFilename.Dir.of_string abs in + let opam_files = [ + dir // (OpamPackage.Name.to_string name ^ OpamPathName.opam_suffix); + dir // OpamPathName.opam_f + ] in + let locked_files = + match OpamFile.OPAM.locked opam with + | Some locked -> + List.map (fun f -> OpamFilename.add_extension f locked) opam_files + | None -> [] + in + List.find_opt OpamFilename.exists locked_files + ++ List.find_opt OpamFilename.exists opam_files + >>| OpamFile.make + | Some (Some r, rel) -> (* Repo case *) + match OpamRepositoryState.get_root st.switch_repos r with + | OpamRepositoryRoot.Dir dir -> + let dir = OpamRepositoryRoot.Dir.to_dir dir / rel in + let opam_file = dir // OpamPathName.opam_f in + if OpamFilename.exists opam_file then + Some (OpamFile.make opam_file) + else None + | OpamRepositoryRoot.Tgz tgz -> + let dir = OpamFilename.Unix.Dir.of_string rel in + let opam_file = OpamFilename.Unix.Op.(dir // OpamPathName.opam_f) in + match List.rev (OpamRepositoryRoot.Tgz.filter_files + (OpamFilename.Unix.equal opam_file) tgz) with + | [] -> None + | (opam_file, content)::_ -> + (* we take the last one, there is a non zero possibility that 2 files + have the same name, see -r option of tar *) + let file = OpamFilename.Unix.to_string opam_file in + let tmp = OpamFilename.mk_tmp_dir () in + let filename = tmp // file in + OpamFilename.write filename content; + OpamStd.Sys.at_exit (fun () -> OpamFilename.rmdir tmp); + Some (OpamFile.make filename) diff --git a/src/state/opamRepositoryState.ml b/src/state/opamRepositoryState.ml index 754181da738..9327ef90499 100644 --- a/src/state/opamRepositoryState.ml +++ b/src/state/opamRepositoryState.ml @@ -79,18 +79,20 @@ module Cache = struct end -let get_root_raw root repos_tmp name = - match Hashtbl.find repos_tmp name with - | lazy repo_root -> OpamRepositoryRoot.Dir repo_root - | exception Not_found -> +let get_root_raw root name = + let tgz = OpamRepositoryRoot.Tgz.Path.root root name in + if OpamRepositoryRoot.Tgz.exists tgz then + OpamRepositoryRoot.Tgz tgz + else OpamRepositoryRoot.Dir (OpamRepositoryRoot.Dir.Path.root root name) let get_root rt name = - get_root_raw rt.repos_global.root rt.repos_tmp name + get_root_raw rt.repos_global.root name let get_repo_root rt repo = - get_root_raw rt.repos_global.root rt.repos_tmp repo.repo_name + get_root_raw rt.repos_global.root repo.repo_name +(* it is simpler to keep it as is and not factorise dir & tgz *) let get_repo_files rt name dir = match get_root rt name with | OpamRepositoryRoot.Dir repo_root -> @@ -101,9 +103,22 @@ let get_repo_files rt name dir = (OpamSystem.back_to_forward (OpamFilename.remove_prefix dir file)), lazy (OpamFilename.read file)) files + | OpamRepositoryRoot.Tgz tgz -> + let xfiles_dir = OpamFilename.Unix.Dir.of_string dir in + OpamRepositoryRoot.Tgz.fold (fun acc filename content -> + if OpamFilename.Unix.starts_with xfiles_dir filename then + let content = Lazy.from_val content in + let basename = + filename + |> OpamFilename.Unix.remove_prefix xfiles_dir + |> OpamFilename.Base.of_string + in + (basename, content)::acc + else acc) + [] tgz -let read_package_opam ~repo_name ~repo_root package_dir = - match OpamFileTools.read_repo_opam ~repo_name ~repo_root package_dir with +let read_package_opam_dir ~repo_name ~repo_root package_dir = + match OpamFileTools.read_repo_opam_dir ~repo_name ~repo_root package_dir with | Some opam -> (try let nv = @@ -122,6 +137,114 @@ let read_package_opam ~repo_name ~repo_root package_dir = OpamFilename.Op.(package_dir // OpamRepositoryPathName.opam_f)); None +let read_package_opam_tgz ~repo_name ~repo_root package_dir + filename content extrafiles = + match OpamFileTools.read_repo_opam_tgz ~repo_name ~repo_root + package_dir filename content extrafiles with + | Some opam -> + (try + let nv = + OpamPackage.of_string + (OpamFilename.Unix.Base.to_string + (OpamFilename.Unix.Dir.basename package_dir)) + in + Some (nv, opam) + with Failure _ -> + log "ERR: directory name not a valid package: ignored %s" + (OpamFilename.Unix.to_string + OpamFilename.Unix.Op.(package_dir // OpamRepositoryPathName.opam_f)); + None) + | None -> + log "ERR: Could not load %s, ignored" + (OpamFilename.Unix.to_string + OpamFilename.Unix.Op.(package_dir // OpamRepositoryPathName.opam_f)); + None + +let load_raw_opams_and_aux_from_tgz _repo_name tgz = + (* We first retrieve the content of the repository *) + let raw_repository = + OpamRepositoryRoot.Tgz.fold (fun acc filename content -> + (filename, content) :: acc) + [] tgz + in + (* we extract the repo file, the repository definition *) + let repo_def = + let filename = OpamFilename.Unix.of_string OpamRepositoryPathName.repo_f in + match List.assoc_opt filename raw_repository with + | Some content -> + let unix_filename = filename in + let filename = OpamFile.make (OpamFilename.Unix.to_filename filename) in + log ~level:5 "read %s" + (OpamFilename.Unix.to_string unix_filename); + OpamRepositoryRoot.read_file ~safe:true (module OpamFile.Repo) + (OpamRepositoryRoot.Tgz tgz) ~filename content + | None -> OpamFile.Repo.empty + in + (* Then we begin the construction of the raw opam map. It contains as key the + dirname, and as value the opam filename, content, and a map of (filename, + content) for extrafiles. *) + (* We extract the opam files and their content *) + let opams_map = + List.fold_left (fun acc (filename, content) -> + if OpamFilename.Unix.starts_with + (OpamFilename.Unix.Dir.of_string OpamRepositoryPathName.packages_d) + filename + && String.equal OpamPathName.opam_f + OpamFilename.Unix.(Base.to_string (basename filename)) then + let key = OpamFilename.Unix.dirname filename in + let value = filename, content, OpamFilename.Unix.Map.empty in + OpamFilename.Unix.Dir.Map.add key value acc + else acc) + OpamFilename.Unix.Dir.Map.empty raw_repository + in + (* Map each opam file to its extrafiles, by comparing packages directories *) + let opams_map = + let exception Found of + OpamFilename.Unix.Dir.t + * (OpamFilename.Unix.t * string * string OpamFilename.Unix.Map.t) + in + List.fold_left (fun acc (filename, content) -> + try + OpamFilename.Unix.Dir.Map.iter (fun dir value -> + if OpamFilename.Unix.starts_with dir filename then + raise (Found (dir, value))) acc; + acc + with Found (key, value) -> + let fo, co, map = value in + let map = OpamFilename.Unix.Map.add filename content map in + OpamFilename.Unix.Dir.Map.add key (fo, co, map) acc) + opams_map raw_repository + in + repo_def, opams_map + +let load_repo_from_tgz repo_name tgz = + if OpamConsole.disp_status_line () || OpamConsole.verbose () then + OpamConsole.status_line "Processing: [%s: loading data]" + (OpamConsole.colorise `blue (OpamRepositoryName.to_string repo_name)); + log ~level:3 "load repo %a from tgz" + (slog OpamRepositoryName.to_string) repo_name; + let repo_root = tgz in + let aux () = + let repo_def, opams_map = + load_raw_opams_and_aux_from_tgz repo_name tgz + in + (* repo_url is added in load_repo to avoid having it as argument *) + let opams = + OpamFilename.Unix.Dir.Map.fold + (fun pkgdir (filename, content, otherfiles) opams -> + match read_package_opam_tgz ~repo_name ~repo_root + pkgdir filename content otherfiles with + | Some (nv, opam) -> OpamPackage.Map.add nv opam opams + | None -> opams) + opams_map OpamPackage.Map.empty + in + repo_def, opams + in + Fun.protect (fun () -> aux ()) ~finally:OpamConsole.clear_status + +let load_opams_from_tgz repo_name tgz = + snd (load_repo_from_tgz repo_name tgz) + let load_opams_from_dir repo_name repo_root = if OpamConsole.disp_status_line () || OpamConsole.verbose () then OpamConsole.status_line "Processing: [%s: loading data]" @@ -137,7 +260,7 @@ let load_opams_from_dir repo_name repo_root = Array.sort String.compare fnames; if Array.exists (fun f -> String.equal f OpamPathName.opam_f && not (Sys.is_directory (dir_str / f))) fnames then - match read_package_opam ~repo_name ~repo_root dir with + match read_package_opam_dir ~repo_name ~repo_root dir with | Some (nv, opam) -> OpamPackage.Map.add nv opam r | None -> r else @@ -151,6 +274,13 @@ let load_opams_from_dir repo_name repo_root = (OpamRepositoryRoot.Dir.Path.packages_dir repo_root)) ~finally:OpamConsole.clear_status +let load_opams repo_name repo_root = + match repo_root with + | OpamRepositoryRoot.Dir dir -> + load_opams_from_dir repo_name dir + | OpamRepositoryRoot.Tgz tgz -> + load_opams_from_tgz repo_name tgz + let load_opams_from_diff repo diffs rt = if OpamConsole.disp_status_line () || OpamConsole.verbose () then OpamConsole.status_line "Processing: [%s: loading data]" @@ -163,42 +293,57 @@ let load_opams_from_diff repo diffs rt = let repo_root = get_repo_root rt repo in let read_package_opam = match repo_root with - | OpamRepositoryRoot.Dir repo_root -> - fun pkg_dir -> - read_package_opam ~repo_name:repo.repo_name ~repo_root pkg_dir + | OpamRepositoryRoot.Dir dir -> + let repo_root = dir in + fun dir -> + let dir = OpamFilename.Unix.Dir.to_dir dir in + let dir = + OpamRepositoryRoot.Dir.Op.(repo_root + / (OpamFilename.Dir.to_string dir)) + in + read_package_opam_dir ~repo_name:repo.repo_name ~repo_root dir + | OpamRepositoryRoot.Tgz tgz -> + let repo_root = tgz in + let _, opams_map = + load_raw_opams_and_aux_from_tgz repo.repo_name tgz + in + fun dir -> + let open OpamStd.Option.Op in + OpamFilename.Unix.Dir.Map.find_opt dir opams_map + >>= fun (filename, content, xfiles) -> + read_package_opam_tgz ~repo_name:repo.repo_name + ~repo_root dir filename content xfiles + in (* 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 - (OpamRepositoryRoot.to_string repo_root) - (OpamFilename.Dir.to_string dirname) - in + let file = OpamFilename.Unix.of_string file in + let dirname = OpamFilename.Unix.dirname file in + let basename = OpamFilename.Unix.Dir.basename dirname in if String.equal OpamRepositoryPathName.files_d - (OpamFilename.Base.to_string basename) then - OpamFilename.Dir.of_string (Filename.dirname full_path) + (OpamFilename.Unix.Base.to_string basename) then + OpamFilename.Unix.Dir.dirname dirname else - OpamFilename.Dir.of_string full_path + dirname in - if OpamFilename.Dir.Set.mem pkg_dir processed_dirs then + if OpamFilename.Unix.Dir.Set.mem pkg_dir processed_dirs then opams, processed_dirs, added_pkgs else - let processed_dirs = OpamFilename.Dir.Set.add pkg_dir processed_dirs in + let processed_dirs = OpamFilename.Unix.Dir.Set.add pkg_dir processed_dirs in match read_package_opam 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 + match + OpamPackage.of_dirname (OpamFilename.Unix.Dir.to_dir pkg_dir) + with | None -> log "ERR: directory name not a valid package: ignored %s" - (OpamFilename.Dir.to_string pkg_dir); + (OpamFilename.Unix.Dir.to_string pkg_dir); opams, processed_dirs, added_pkgs | Some nv -> if OpamPackage.Set.mem nv added_pkgs then @@ -229,7 +374,7 @@ 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) @@ -249,6 +394,15 @@ let load_repo repo repo_root = let t = OpamConsole.timer () in let loaded_repo = match repo_root with + | OpamRepositoryRoot.Tgz tgz -> + let repo_def, opams = + load_repo_from_tgz repo.repo_name tgz + in + let repo_def = + repo_def + |> OpamFile.Repo.with_root_url repo.repo_url + in + repo_def, opams | OpamRepositoryRoot.Dir dir -> load_repo_from_dir repo dir in @@ -257,25 +411,7 @@ let load_repo repo repo_root = (t ()); loaded_repo -(* Cleaning directories follows the repo path pattern: - TMPDIR/opam-tmp-dir/repo-dir, defined in [load]. *) -let clean_repo_tmp tmp_dir = - if Lazy.is_val tmp_dir then - (let dir = Lazy.force tmp_dir in - OpamRepositoryRoot.Dir.remove dir; - let parent = OpamRepositoryRoot.Dir.dirname dir in - if OpamFilename.dir_is_empty parent = Some true then - OpamFilename.rmdir parent) - -let remove_from_repos_tmp rt name = - try - clean_repo_tmp (Hashtbl.find rt.repos_tmp name); - Hashtbl.remove rt.repos_tmp name - with Not_found -> () - -let cleanup rt = - Hashtbl.iter (fun _ tmp_dir -> clean_repo_tmp tmp_dir) rt.repos_tmp; - Hashtbl.clear rt.repos_tmp +let cleanup _rt = () let syspkgs_available ?env = function | None -> None @@ -303,37 +439,10 @@ let load lock_kind gt = repo_trust = ta; } in let repositories = OpamRepositoryName.Map.mapi mk_repo repos_map in - let repos_tmp_root = lazy (OpamFilename.mk_tmp_dir ()) in - let repos_tmp = Hashtbl.create 23 in - OpamRepositoryName.Map.iter (fun name repo -> - let uncompressed_root = - OpamRepositoryRoot.Dir.Path.root gt.root repo.repo_name - in - let tar = OpamRepositoryPath.tar gt.root repo.repo_name in - if not (OpamRepositoryRoot.Dir.exists uncompressed_root) && - OpamFilename.exists tar - then - let tmp = lazy ( - let tmp_root = Lazy.force repos_tmp_root in - try - (* We rely on this path pattern to clean the repo. - cf. [clean_repo_tmp] *) - OpamFilename.extract_in tar tmp_root; - OpamRepositoryRoot.Dir.of_dir - (OpamFilename.Op.(tmp_root / OpamRepositoryName.to_string name)) - with Failure s -> - OpamFilename.remove tar; - OpamConsole.error_and_exit `Aborted - "%s.\nRun `opam update --repositories %s` to fix the issue" - s (OpamRepositoryName.to_string name); - ) in - Hashtbl.add repos_tmp name tmp - ) repositories; let make_rt repos_definitions opams repos_syspkgs_available = let rt = { repos_global = (gt :> unlocked global_state); repos_lock = lock; - repos_tmp; repositories; repos_definitions; repo_opams = opams; @@ -396,7 +505,7 @@ let load lock_kind gt = OpamRepositoryName.Map.fold (fun name url (defs, opams) -> let repo = mk_repo name url in let repo_def, repo_opams = - load_repo repo (get_root_raw gt.root repos_tmp name) + load_repo repo (get_root_raw gt.root name) in OpamRepositoryName.Map.add name repo_def defs, OpamRepositoryName.Map.add name repo_opams opams) @@ -439,7 +548,8 @@ let unlock ?cleanup:(cln=true) rt = (rt :> unlocked repos_state) let drop ?cleanup rt = - let _ = unlock ?cleanup rt in () + let _ = unlock ?cleanup rt in + () let with_write_lock ?dontblock rt f = if OpamStateConfig.is_newer_than_self ~lock_kind:`Lock_write rt.repos_global diff --git a/src/state/opamRepositoryState.mli b/src/state/opamRepositoryState.mli index 7642b8eb535..9733755068d 100644 --- a/src/state/opamRepositoryState.mli +++ b/src/state/opamRepositoryState.mli @@ -54,6 +54,10 @@ val load_opams_from_dir: repository_name -> OpamRepositoryRoot.Dir.t -> OpamFile.OPAM.t OpamPackage.Map.t +val load_opams_from_tgz: + repository_name -> OpamRepositoryRoot.Tgz.t -> + OpamFile.OPAM.t OpamPackage.Map.t + (** [load_opams_from_diff repo diffs rt] incrementally updates package definitions by processing only changed files. @@ -69,6 +73,9 @@ val load_opams_from_diff: repository -> Patch.operation list -> 'a repos_state -> OpamFile.OPAM.t package_map +val load_opams: + repository_name -> OpamRepositoryRoot.t -> OpamFile.OPAM.t package_map + (** Load all the metadata within the local mirror of the given repository, without cache *) val load_repo: @@ -82,7 +89,7 @@ val syspkgs_available: ?env:gt_variables -> repo_syspkgs_available -> OpamSysPkg.availability_mode option -(** Get the (lazily extracted) repository root for the given repository *) +(** Get the repository root for the given repository *) val get_root: 'a repos_state -> repository_name -> OpamRepositoryRoot.t (** Same as {!get_root}, but with a repository rather than just a name as argument *) @@ -107,8 +114,8 @@ val get_repo_files: * 'a global_state -> repository -> * (OpamFilename.Dir.t -> 'b OpamProcess.job) -> 'b OpamProcess.job *) -(** Releases any locks on the given repos_state, and cleans the tmp extracted - tree if any unless [cleanup=false] *) +(** Releases any locks on the given repos_state. + [cleanup] is a no-op *) val unlock: ?cleanup:bool -> 'a repos_state -> unlocked repos_state (** Releases any locks on the given repos_state and then ignores it. @@ -120,11 +127,7 @@ val unlock: ?cleanup:bool -> 'a repos_state -> unlocked repos_state *) val drop: ?cleanup:bool -> 'a repos_state -> unit -(** Cleanup before removing the repository from temporary table *) -val remove_from_repos_tmp: 'a repos_state -> repository_name -> unit - -(** Clears tmp files corresponding to a repo state (uncompressed repository - contents) *) +(** Clears tmp files corresponding to a repo state *) val cleanup: 'a repos_state -> unit (** Calls the provided function, ensuring a temporary write lock on the given diff --git a/src/state/opamStateTypes.mli b/src/state/opamStateTypes.mli index 2731b77c8df..257827fdf62 100644 --- a/src/state/opamStateTypes.mli +++ b/src/state/opamStateTypes.mli @@ -129,9 +129,6 @@ type +'lock repos_state = { (** All available system packages required by the repo's packages. [None] when depext system is disabled or unavailable. *) - repos_tmp: (OpamRepositoryName.t, OpamRepositoryRoot.Dir.t Lazy.t) Hashtbl.t; - (** Temporary directories containing the uncompressed contents of the - repositories *) } constraint 'lock = 'lock lock diff --git a/src/state/opamUpdate.ml b/src/state/opamUpdate.ml index df9d550c58e..bd4299e188b 100644 --- a/src/state/opamUpdate.ml +++ b/src/state/opamUpdate.ml @@ -50,7 +50,61 @@ let repository rt repo = let max_loop = 10 in let gt = rt.repos_global in if repo.repo_url = OpamUrl.empty then Done None else - let repo_root = OpamRepositoryState.get_repo_root rt repo in + let get_repo_root () = + let tgz = + OpamRepositoryRoot.Tgz.Path.root rt.repos_global.root repo.repo_name + in + let dir = + OpamRepositoryRoot.Dir.Path.root rt.repos_global.root repo.repo_name + in + let reporoot_tgz = OpamRepositoryRoot.Tgz tgz in + let reporoot_dir = OpamRepositoryRoot.Dir dir in + let fail kind e = + OpamStd.Exn.fatal e; + Printf.ksprintf failwith + "Failed to regenerate local repository %s: %s" + kind (Printexc.to_string e) + in + let tgz_to_dir () = + log "repository format change: from archive to directory (%s)" + (OpamRepositoryRoot.Dir.to_string dir); + OpamProcess.Job.finally (fun () -> + OpamRepositoryRoot.remove reporoot_tgz) @@ fun () -> + OpamRepositoryRoot.extract_in_job tgz dir @@+ function + | Some e -> fail "directory" e + | None -> Done reporoot_dir + in + let dir_to_tgz () = + log "repository format change: from directory to archive (%s)" + (OpamRepositoryRoot.to_string reporoot_tgz); + OpamRepositoryRoot.make_tar_gz tgz dir; + OpamRepositoryRoot.Dir.remove dir + in + let tgz_exists = OpamRepositoryRoot.exists reporoot_tgz in + let dir_exists = OpamRepositoryRoot.exists reporoot_dir in + let tgz_exists, dir_exists = + (* shouldn't happen, we remove both and do a full update *) + if tgz_exists && dir_exists then + (log "repository exists as directory and archive, removing both"; + OpamRepositoryRoot.remove_both rt.repos_global.root repo.repo_name; + false, false) + else tgz_exists, dir_exists + in + match repo.repo_url.backend with + | `http -> + if dir_exists then dir_to_tgz (); + Done reporoot_tgz + | `rsync when OpamRepositoryConfig.(!r.repo_tarring) -> + if dir_exists then dir_to_tgz (); + Done reporoot_tgz + | `rsync + | #OpamUrl.version_control -> + (* We shouldn't have the case tgz & vcs because it comes from a + 'opam set-url' and it is wiped before update call *) + if tgz_exists then tgz_to_dir () else Done reporoot_dir + in + (* We transform the repository first if needed, then do the update and apply it *) + get_repo_root () @@+ fun repo_root -> (* Recursively traverse redirection links, but stop after 10 steps or if we cycle back to the initial repo. *) let rec job r redirect n = @@ -122,48 +176,24 @@ let repository rt repo = (OpamConsole.colorise `bold (OpamUrl.to_string repo.repo_url)) msg) (OpamFile.Repo.announce repo_file); - let tarred_repo = OpamRepositoryPath.tar gt.root repo.repo_name in - (if OpamRepositoryConfig.(!r.repo_tarring) then - match repo_root with - | Dir dir -> OpamRepositoryRoot.make_tar_gz tarred_repo dir); - Done None - @@+ function - | Some e -> - OpamStd.Exn.fatal e; - Printf.ksprintf failwith - "Failed to regenerate local repository archive: %s" - (Printexc.to_string e) - | None -> - let opams = - match repo_root with - | OpamRepositoryRoot.Dir dir -> - match diffs with - | [] -> - OpamRepositoryState.load_opams_from_dir repo.repo_name dir - | diffs -> OpamRepositoryState.load_opams_from_diff repo diffs rt - in - let local_dir = OpamRepositoryRoot.Dir.Path.root gt.root repo.repo_name in - if OpamRepositoryConfig.(!r.repo_tarring) then - (if OpamRepositoryRoot.Dir.exists local_dir then - (* Mark the obsolete local directory for deletion once we complete: it's - no longer needed once we have a tar.gz *) - Hashtbl.add rt.repos_tmp repo.repo_name (lazy local_dir)) - else if OpamFilename.exists tarred_repo then - (OpamRepositoryRoot.move ~src:repo_root ~dst:(Dir local_dir); - OpamFilename.remove tarred_repo); - Done (Some ( - (* Return an update function to make parallel execution possible *) - fun rt -> - { rt with - repositories = - OpamRepositoryName.Map.add repo.repo_name repo rt.repositories; - repos_definitions = - OpamRepositoryName.Map.add repo.repo_name repo_file - rt.repos_definitions; - repo_opams = - OpamRepositoryName.Map.add repo.repo_name opams rt.repo_opams; - } - )) + let opams = + match diffs with + | [] -> OpamRepositoryState.load_opams repo.repo_name repo_root + | diffs -> OpamRepositoryState.load_opams_from_diff repo diffs rt + in + Done (Some ( + (* Return an update function to make parallel execution possible *) + fun rt -> + { rt with + repositories = + OpamRepositoryName.Map.add repo.repo_name repo rt.repositories; + repos_definitions = + OpamRepositoryName.Map.add repo.repo_name repo_file + rt.repos_definitions; + repo_opams = + OpamRepositoryName.Map.add repo.repo_name opams rt.repo_opams; + } + )) let update_sys_available_cache ?(force=false) rt = if OpamConsole.disp_status_line () then diff --git a/tests/reftests/action-disk.test b/tests/reftests/action-disk.test index 419ac3a3e98..40521f68ff5 100644 --- a/tests/reftests/action-disk.test +++ b/tests/reftests/action-disk.test @@ -110,8 +110,12 @@ SYSTEM mkdir ${BASEDIR}/OPAM/repo/default/packages/main SYSTEM mkdir ${BASEDIR}/OPAM/repo/default/packages/main-repo/main-repo.2/files FILE(repo) Read ${BASEDIR}/OPAM/repo/default/repo in 0.000s Processing: [default: loading data] -FILE(opam) Read ${BASEDIR}/OPAM/repo/default/packages/main-repo/main-repo.2/opam in 0.000s -FILE(opam) Read ${BASEDIR}/OPAM/repo/default/packages/main-repo/main-repo.1/opam in 0.000s +SYSTEM read ${BASEDIR}/OPAM/repo/default/packages/main-repo/main-repo.1/opam +FILE(opam) Read packages/main-repo/main-repo.1/opam (out of ${BASEDIR}/OPAM/repo/default) in 0.000s +SYSTEM read ${BASEDIR}/OPAM/repo/default/packages/main-repo/main-repo.1/files/x-file.main-repo.1 +SYSTEM read ${BASEDIR}/OPAM/repo/default/packages/main-repo/main-repo.2/opam +FILE(opam) Read packages/main-repo/main-repo.2/opam (out of ${BASEDIR}/OPAM/repo/default) in 0.000s +SYSTEM read ${BASEDIR}/OPAM/repo/default/packages/main-repo/main-repo.2/files/x-file.main-repo.2 FILE(repos-config) Wrote ${BASEDIR}/OPAM/repo/repos-config atomically in 0.000s SYSTEM rm ${BASEDIR}/OPAM/repo/state-magicv.cache SYSTEM LOCK ${BASEDIR}/OPAM/repo/state-magicv.cache (none => write) @@ -661,6 +665,7 @@ SYSTEM LOCK ${BASEDIR}/OPAM/repo/state-magicv.cache (re SYSTEM LOCK ${BASEDIR}/OPAM/install-from-path-pin-all/.opam-switch/lock (none => write) FILE(switch-config) Read ${BASEDIR}/OPAM/install-from-path-pin-all/.opam-switch/switch-config in 0.000s FILE(switch-state) Read ${BASEDIR}/OPAM/install-from-path-pin-all/.opam-switch/switch-state in 0.000s +SYSTEM read ${BASEDIR}/OPAM/install-from-path-pin-all/.opam-switch/overlay/main-ppin/opam FILE(opam) Read ${BASEDIR}/OPAM/install-from-path-pin-all/.opam-switch/overlay/main-ppin/opam in 0.000s SYSTEM LOCK ${BASEDIR}/OPAM/install-from-path-pin-all/.opam-switch/packages/cache (none => read) CACHE(installed) Loaded ${BASEDIR}/OPAM/install-from-path-pin-all/.opam-switch/packages/cache in 0.000s @@ -669,6 +674,7 @@ FILE(switch-config) Wrote ${BASEDIR}/OPAM/install-from-path-pin-all/ FILE(switch-state) Wrote ${BASEDIR}/OPAM/install-from-path-pin-all/.opam-switch/backup/state-today.export atomically in 0.000s <><> Synchronising pinned packages ><><><><><><><><><><><><><><><><><><><><><><> +SYSTEM read ${BASEDIR}/OPAM/install-from-path-pin-all/.opam-switch/overlay/main-ppin/opam FILE(opam) Read ${BASEDIR}/OPAM/install-from-path-pin-all/.opam-switch/overlay/main-ppin/opam in 0.000s FILE(opam) Read ${BASEDIR}/OPAM/install-from-path-pin-all/.opam-switch/sources/main-ppin/main-ppin.opam in 0.000s SYSTEM mkdir ${OPAMTMP} @@ -739,6 +745,7 @@ SYSTEM LOCK ${BASEDIR}/OPAM/repo/state-magicv.cache (re SYSTEM LOCK ${BASEDIR}/OPAM/install-from-path-pin-all/.opam-switch/lock (none => write) FILE(switch-config) Read ${BASEDIR}/OPAM/install-from-path-pin-all/.opam-switch/switch-config in 0.000s FILE(switch-state) Read ${BASEDIR}/OPAM/install-from-path-pin-all/.opam-switch/switch-state in 0.000s +SYSTEM read ${BASEDIR}/OPAM/install-from-path-pin-all/.opam-switch/overlay/main-ppin/opam FILE(opam) Read ${BASEDIR}/OPAM/install-from-path-pin-all/.opam-switch/overlay/main-ppin/opam in 0.000s SYSTEM LOCK ${BASEDIR}/OPAM/install-from-path-pin-all/.opam-switch/packages/cache (none => read) CACHE(installed) Loaded ${BASEDIR}/OPAM/install-from-path-pin-all/.opam-switch/packages/cache in 0.000s @@ -747,6 +754,7 @@ FILE(switch-config) Wrote ${BASEDIR}/OPAM/install-from-path-pin-all/ FILE(switch-state) Wrote ${BASEDIR}/OPAM/install-from-path-pin-all/.opam-switch/backup/state-today.export atomically in 0.000s <><> Synchronising pinned packages ><><><><><><><><><><><><><><><><><><><><><><> +SYSTEM read ${BASEDIR}/OPAM/install-from-path-pin-all/.opam-switch/overlay/main-ppin/opam FILE(opam) Read ${BASEDIR}/OPAM/install-from-path-pin-all/.opam-switch/overlay/main-ppin/opam in 0.000s FILE(opam) Read ${BASEDIR}/OPAM/install-from-path-pin-all/.opam-switch/sources/main-ppin/main-ppin.opam in 0.000s SYSTEM mkdir ${OPAMTMP} @@ -837,6 +845,7 @@ SYSTEM LOCK ${BASEDIR}/OPAM/repo/state-magicv.cache (re SYSTEM LOCK ${BASEDIR}/OPAM/install-from-path-pin-all/.opam-switch/lock (none => write) FILE(switch-config) Read ${BASEDIR}/OPAM/install-from-path-pin-all/.opam-switch/switch-config in 0.000s FILE(switch-state) Read ${BASEDIR}/OPAM/install-from-path-pin-all/.opam-switch/switch-state in 0.000s +SYSTEM read ${BASEDIR}/OPAM/install-from-path-pin-all/.opam-switch/overlay/main-ppin/opam FILE(opam) Read ${BASEDIR}/OPAM/install-from-path-pin-all/.opam-switch/overlay/main-ppin/opam in 0.000s SYSTEM LOCK ${BASEDIR}/OPAM/install-from-path-pin-all/.opam-switch/packages/cache (none => read) CACHE(installed) Loaded ${BASEDIR}/OPAM/install-from-path-pin-all/.opam-switch/packages/cache in 0.000s @@ -902,6 +911,7 @@ SYSTEM LOCK ${BASEDIR}/OPAM/repo/state-magicv.cache (re SYSTEM LOCK ${BASEDIR}/OPAM/install-from-path-pin-all/.opam-switch/lock (none => write) FILE(switch-config) Read ${BASEDIR}/OPAM/install-from-path-pin-all/.opam-switch/switch-config in 0.000s FILE(switch-state) Read ${BASEDIR}/OPAM/install-from-path-pin-all/.opam-switch/switch-state in 0.000s +SYSTEM read ${BASEDIR}/OPAM/install-from-path-pin-all/.opam-switch/overlay/main-ppin/opam FILE(opam) Read ${BASEDIR}/OPAM/install-from-path-pin-all/.opam-switch/overlay/main-ppin/opam in 0.000s SYSTEM LOCK ${BASEDIR}/OPAM/install-from-path-pin-all/.opam-switch/packages/cache (none => write) CACHE(installed) Writing the installed cache to ${BASEDIR}/OPAM/install-from-path-pin-all/.opam-switch/packages/cache ... @@ -1023,6 +1033,7 @@ SYSTEM LOCK ${BASEDIR}/OPAM/repo/state-magicv.cache (re SYSTEM LOCK ${BASEDIR}/OPAM/install-from-path-pin-all/.opam-switch/lock (none => write) FILE(switch-config) Read ${BASEDIR}/OPAM/install-from-path-pin-all/.opam-switch/switch-config in 0.000s FILE(switch-state) Read ${BASEDIR}/OPAM/install-from-path-pin-all/.opam-switch/switch-state in 0.000s +SYSTEM read ${BASEDIR}/OPAM/install-from-path-pin-all/.opam-switch/overlay/main-ppin/opam FILE(opam) Read ${BASEDIR}/OPAM/install-from-path-pin-all/.opam-switch/overlay/main-ppin/opam in 0.000s SYSTEM LOCK ${BASEDIR}/OPAM/install-from-path-pin-all/.opam-switch/packages/cache (none => read) CACHE(installed) Loaded ${BASEDIR}/OPAM/install-from-path-pin-all/.opam-switch/packages/cache in 0.000s @@ -1031,6 +1042,7 @@ FILE(switch-config) Wrote ${BASEDIR}/OPAM/install-from-path-pin-all/ FILE(switch-state) Wrote ${BASEDIR}/OPAM/install-from-path-pin-all/.opam-switch/backup/state-today.export atomically in 0.000s <><> Synchronising pinned packages ><><><><><><><><><><><><><><><><><><><><><><> +SYSTEM read ${BASEDIR}/OPAM/install-from-path-pin-all/.opam-switch/overlay/main-ppin/opam FILE(opam) Read ${BASEDIR}/OPAM/install-from-path-pin-all/.opam-switch/overlay/main-ppin/opam in 0.000s FILE(opam) Read ${BASEDIR}/OPAM/install-from-path-pin-all/.opam-switch/sources/main-ppin/main-ppin.opam in 0.000s SYSTEM mkdir ${OPAMTMP} @@ -1120,6 +1132,7 @@ SYSTEM LOCK ${BASEDIR}/OPAM/repo/state-magicv.cache (re SYSTEM LOCK ${BASEDIR}/OPAM/install-from-path-pin-all/.opam-switch/lock (none => write) FILE(switch-config) Read ${BASEDIR}/OPAM/install-from-path-pin-all/.opam-switch/switch-config in 0.000s FILE(switch-state) Read ${BASEDIR}/OPAM/install-from-path-pin-all/.opam-switch/switch-state in 0.000s +SYSTEM read ${BASEDIR}/OPAM/install-from-path-pin-all/.opam-switch/overlay/main-ppin/opam FILE(opam) Read ${BASEDIR}/OPAM/install-from-path-pin-all/.opam-switch/overlay/main-ppin/opam in 0.000s SYSTEM LOCK ${BASEDIR}/OPAM/install-from-path-pin-all/.opam-switch/packages/cache (none => read) CACHE(installed) Loaded ${BASEDIR}/OPAM/install-from-path-pin-all/.opam-switch/packages/cache in 0.000s @@ -1315,6 +1328,7 @@ SYSTEM LOCK ${BASEDIR}/OPAM/repo/state-magicv.cache (re SYSTEM LOCK ${BASEDIR}/OPAM/install-from-git-pin-all/.opam-switch/lock (none => write) FILE(switch-config) Read ${BASEDIR}/OPAM/install-from-git-pin-all/.opam-switch/switch-config in 0.000s FILE(switch-state) Read ${BASEDIR}/OPAM/install-from-git-pin-all/.opam-switch/switch-state in 0.000s +SYSTEM read ${BASEDIR}/OPAM/install-from-git-pin-all/.opam-switch/overlay/main-gpin/opam FILE(opam) Read ${BASEDIR}/OPAM/install-from-git-pin-all/.opam-switch/overlay/main-gpin/opam in 0.000s SYSTEM LOCK ${BASEDIR}/OPAM/install-from-git-pin-all/.opam-switch/packages/cache (none => read) CACHE(installed) Loaded ${BASEDIR}/OPAM/install-from-git-pin-all/.opam-switch/packages/cache in 0.000s @@ -1323,6 +1337,7 @@ FILE(switch-config) Wrote ${BASEDIR}/OPAM/install-from-git-pin-all/. FILE(switch-state) Wrote ${BASEDIR}/OPAM/install-from-git-pin-all/.opam-switch/backup/state-today.export atomically in 0.000s <><> Synchronising pinned packages ><><><><><><><><><><><><><><><><><><><><><><> +SYSTEM read ${BASEDIR}/OPAM/install-from-git-pin-all/.opam-switch/overlay/main-gpin/opam FILE(opam) Read ${BASEDIR}/OPAM/install-from-git-pin-all/.opam-switch/overlay/main-gpin/opam in 0.000s FILE(opam) Read ${BASEDIR}/OPAM/install-from-git-pin-all/.opam-switch/sources/main-gpin/main-gpin.opam in 0.000s Processing 1/1: @@ -1399,6 +1414,7 @@ SYSTEM LOCK ${BASEDIR}/OPAM/repo/state-magicv.cache (re SYSTEM LOCK ${BASEDIR}/OPAM/install-from-git-pin-all/.opam-switch/lock (none => write) FILE(switch-config) Read ${BASEDIR}/OPAM/install-from-git-pin-all/.opam-switch/switch-config in 0.000s FILE(switch-state) Read ${BASEDIR}/OPAM/install-from-git-pin-all/.opam-switch/switch-state in 0.000s +SYSTEM read ${BASEDIR}/OPAM/install-from-git-pin-all/.opam-switch/overlay/main-gpin/opam FILE(opam) Read ${BASEDIR}/OPAM/install-from-git-pin-all/.opam-switch/overlay/main-gpin/opam in 0.000s SYSTEM LOCK ${BASEDIR}/OPAM/install-from-git-pin-all/.opam-switch/packages/cache (none => read) CACHE(installed) Loaded ${BASEDIR}/OPAM/install-from-git-pin-all/.opam-switch/packages/cache in 0.000s @@ -1407,6 +1423,7 @@ FILE(switch-config) Wrote ${BASEDIR}/OPAM/install-from-git-pin-all/. FILE(switch-state) Wrote ${BASEDIR}/OPAM/install-from-git-pin-all/.opam-switch/backup/state-today.export atomically in 0.000s <><> Synchronising pinned packages ><><><><><><><><><><><><><><><><><><><><><><> +SYSTEM read ${BASEDIR}/OPAM/install-from-git-pin-all/.opam-switch/overlay/main-gpin/opam FILE(opam) Read ${BASEDIR}/OPAM/install-from-git-pin-all/.opam-switch/overlay/main-gpin/opam in 0.000s FILE(opam) Read ${BASEDIR}/OPAM/install-from-git-pin-all/.opam-switch/sources/main-gpin/main-gpin.opam in 0.000s Processing 1/1: @@ -1510,6 +1527,7 @@ SYSTEM LOCK ${BASEDIR}/OPAM/repo/state-magicv.cache (re SYSTEM LOCK ${BASEDIR}/OPAM/install-from-git-pin-all/.opam-switch/lock (none => write) FILE(switch-config) Read ${BASEDIR}/OPAM/install-from-git-pin-all/.opam-switch/switch-config in 0.000s FILE(switch-state) Read ${BASEDIR}/OPAM/install-from-git-pin-all/.opam-switch/switch-state in 0.000s +SYSTEM read ${BASEDIR}/OPAM/install-from-git-pin-all/.opam-switch/overlay/main-gpin/opam FILE(opam) Read ${BASEDIR}/OPAM/install-from-git-pin-all/.opam-switch/overlay/main-gpin/opam in 0.000s SYSTEM LOCK ${BASEDIR}/OPAM/install-from-git-pin-all/.opam-switch/packages/cache (none => read) CACHE(installed) Loaded ${BASEDIR}/OPAM/install-from-git-pin-all/.opam-switch/packages/cache in 0.000s @@ -1579,6 +1597,7 @@ SYSTEM LOCK ${BASEDIR}/OPAM/repo/state-magicv.cache (re SYSTEM LOCK ${BASEDIR}/OPAM/install-from-git-pin-all/.opam-switch/lock (none => write) FILE(switch-config) Read ${BASEDIR}/OPAM/install-from-git-pin-all/.opam-switch/switch-config in 0.000s FILE(switch-state) Read ${BASEDIR}/OPAM/install-from-git-pin-all/.opam-switch/switch-state in 0.000s +SYSTEM read ${BASEDIR}/OPAM/install-from-git-pin-all/.opam-switch/overlay/main-gpin/opam FILE(opam) Read ${BASEDIR}/OPAM/install-from-git-pin-all/.opam-switch/overlay/main-gpin/opam in 0.000s SYSTEM LOCK ${BASEDIR}/OPAM/install-from-git-pin-all/.opam-switch/packages/cache (none => write) CACHE(installed) Writing the installed cache to ${BASEDIR}/OPAM/install-from-git-pin-all/.opam-switch/packages/cache ... @@ -1710,6 +1729,7 @@ SYSTEM LOCK ${BASEDIR}/OPAM/repo/state-magicv.cache (re SYSTEM LOCK ${BASEDIR}/OPAM/install-from-git-pin-all/.opam-switch/lock (none => write) FILE(switch-config) Read ${BASEDIR}/OPAM/install-from-git-pin-all/.opam-switch/switch-config in 0.000s FILE(switch-state) Read ${BASEDIR}/OPAM/install-from-git-pin-all/.opam-switch/switch-state in 0.000s +SYSTEM read ${BASEDIR}/OPAM/install-from-git-pin-all/.opam-switch/overlay/main-gpin/opam FILE(opam) Read ${BASEDIR}/OPAM/install-from-git-pin-all/.opam-switch/overlay/main-gpin/opam in 0.000s SYSTEM LOCK ${BASEDIR}/OPAM/install-from-git-pin-all/.opam-switch/packages/cache (none => read) CACHE(installed) Loaded ${BASEDIR}/OPAM/install-from-git-pin-all/.opam-switch/packages/cache in 0.000s @@ -1718,6 +1738,7 @@ FILE(switch-config) Wrote ${BASEDIR}/OPAM/install-from-git-pin-all/. FILE(switch-state) Wrote ${BASEDIR}/OPAM/install-from-git-pin-all/.opam-switch/backup/state-today.export atomically in 0.000s <><> Synchronising pinned packages ><><><><><><><><><><><><><><><><><><><><><><> +SYSTEM read ${BASEDIR}/OPAM/install-from-git-pin-all/.opam-switch/overlay/main-gpin/opam FILE(opam) Read ${BASEDIR}/OPAM/install-from-git-pin-all/.opam-switch/overlay/main-gpin/opam in 0.000s FILE(opam) Read ${BASEDIR}/OPAM/install-from-git-pin-all/.opam-switch/sources/main-gpin/main-gpin.opam in 0.000s Processing 1/1: @@ -1820,6 +1841,7 @@ SYSTEM LOCK ${BASEDIR}/OPAM/repo/state-magicv.cache (re SYSTEM LOCK ${BASEDIR}/OPAM/install-from-git-pin-all/.opam-switch/lock (none => write) FILE(switch-config) Read ${BASEDIR}/OPAM/install-from-git-pin-all/.opam-switch/switch-config in 0.000s FILE(switch-state) Read ${BASEDIR}/OPAM/install-from-git-pin-all/.opam-switch/switch-state in 0.000s +SYSTEM read ${BASEDIR}/OPAM/install-from-git-pin-all/.opam-switch/overlay/main-gpin/opam FILE(opam) Read ${BASEDIR}/OPAM/install-from-git-pin-all/.opam-switch/overlay/main-gpin/opam in 0.000s SYSTEM LOCK ${BASEDIR}/OPAM/install-from-git-pin-all/.opam-switch/packages/cache (none => read) CACHE(installed) Loaded ${BASEDIR}/OPAM/install-from-git-pin-all/.opam-switch/packages/cache in 0.000s @@ -1985,6 +2007,7 @@ SYSTEM LOCK ${BASEDIR}/OPAM/repo/state-magicv.cache (re SYSTEM LOCK ${BASEDIR}/OPAM/install-from-version-pin/.opam-switch/lock (none => write) FILE(switch-config) Read ${BASEDIR}/OPAM/install-from-version-pin/.opam-switch/switch-config in 0.000s FILE(switch-state) Read ${BASEDIR}/OPAM/install-from-version-pin/.opam-switch/switch-state in 0.000s +SYSTEM read ${BASEDIR}/OPAM/install-from-version-pin/.opam-switch/overlay/main-repo/opam SYSTEM LOCK ${BASEDIR}/OPAM/install-from-version-pin/.opam-switch/packages/cache (none => read) CACHE(installed) Loaded ${BASEDIR}/OPAM/install-from-version-pin/.opam-switch/packages/cache in 0.000s SYSTEM LOCK ${BASEDIR}/OPAM/install-from-version-pin/.opam-switch/packages/cache (read => none) @@ -2053,6 +2076,7 @@ SYSTEM LOCK ${BASEDIR}/OPAM/repo/state-magicv.cache (re SYSTEM LOCK ${BASEDIR}/OPAM/install-from-version-pin/.opam-switch/lock (none => write) FILE(switch-config) Read ${BASEDIR}/OPAM/install-from-version-pin/.opam-switch/switch-config in 0.000s FILE(switch-state) Read ${BASEDIR}/OPAM/install-from-version-pin/.opam-switch/switch-state in 0.000s +SYSTEM read ${BASEDIR}/OPAM/install-from-version-pin/.opam-switch/overlay/main-repo/opam SYSTEM LOCK ${BASEDIR}/OPAM/install-from-version-pin/.opam-switch/packages/cache (none => read) CACHE(installed) Loaded ${BASEDIR}/OPAM/install-from-version-pin/.opam-switch/packages/cache in 0.000s SYSTEM LOCK ${BASEDIR}/OPAM/install-from-version-pin/.opam-switch/packages/cache (read => none) @@ -2150,6 +2174,7 @@ SYSTEM LOCK ${BASEDIR}/OPAM/repo/state-magicv.cache (re SYSTEM LOCK ${BASEDIR}/OPAM/install-from-version-pin/.opam-switch/lock (none => write) FILE(switch-config) Read ${BASEDIR}/OPAM/install-from-version-pin/.opam-switch/switch-config in 0.000s FILE(switch-state) Read ${BASEDIR}/OPAM/install-from-version-pin/.opam-switch/switch-state in 0.000s +SYSTEM read ${BASEDIR}/OPAM/install-from-version-pin/.opam-switch/overlay/main-repo/opam SYSTEM LOCK ${BASEDIR}/OPAM/install-from-version-pin/.opam-switch/packages/cache (none => read) CACHE(installed) Loaded ${BASEDIR}/OPAM/install-from-version-pin/.opam-switch/packages/cache in 0.000s SYSTEM LOCK ${BASEDIR}/OPAM/install-from-version-pin/.opam-switch/packages/cache (read => none) @@ -2222,6 +2247,7 @@ SYSTEM LOCK ${BASEDIR}/OPAM/repo/state-magicv.cache (re SYSTEM LOCK ${BASEDIR}/OPAM/install-from-version-pin/.opam-switch/lock (none => write) FILE(switch-config) Read ${BASEDIR}/OPAM/install-from-version-pin/.opam-switch/switch-config in 0.000s FILE(switch-state) Read ${BASEDIR}/OPAM/install-from-version-pin/.opam-switch/switch-state in 0.000s +SYSTEM read ${BASEDIR}/OPAM/install-from-version-pin/.opam-switch/overlay/main-repo/opam SYSTEM LOCK ${BASEDIR}/OPAM/install-from-version-pin/.opam-switch/packages/cache (none => write) CACHE(installed) Writing the installed cache to ${BASEDIR}/OPAM/install-from-version-pin/.opam-switch/packages/cache ... CACHE(installed) ${BASEDIR}/OPAM/install-from-version-pin/.opam-switch/packages/cache written in 0.000s diff --git a/tests/reftests/extrafile.test b/tests/reftests/extrafile.test index 1f78e349593..68e9a2273b2 100644 --- a/tests/reftests/extrafile.test +++ b/tests/reftests/extrafile.test @@ -155,14 +155,14 @@ Now run 'opam upgrade' to apply any package updates. ### ::::::::::::::::: ### sh -c "rm OPAM/repo/state-*.cache" ### OPAMDEBUGSECTIONS="opam-file" OPAMDEBUG=-2 opam list good-md5 -s | unordered +opam-file Missing expected extra files ../../../no-checksum/no-checksum.1/files/p.patch at packages/escape-good-md5/escape-good-md5.1/files (out of ${BASEDIR}/OPAM/repo/default) +opam-file Missing expected extra files /etc/passwdd at packages/escape-absolute/escape-absolute.1/files (out of ${BASEDIR}/OPAM/repo/default) +opam-file Missing expected extra files p.patch at packages/not-present/not-present.1/files (out of ${BASEDIR}/OPAM/repo/default) opam-file Missing extra-files field for p.patch for no-checksum.1, ignoring them. opam-file Missing extra-files field for p.patch for not-mentioned.1, ignoring them. -opam-file Missing expected extra files ../../../no-checksum/no-checksum.1/files/p.patch at ${BASEDIR}/OPAM/repo/default/packages/escape-good-md5/escape-good-md5.1/files -opam-file Missing expected extra files p.patch at ${BASEDIR}/OPAM/repo/default/packages/not-present/not-present.1/files -opam-file Mismatching extra-files at ${BASEDIR}/OPAM/repo/default/packages/good-md5-good-sha256/good-md5-good-sha256.1: missing from 'files' directory (1) -opam-file Missing expected extra files /etc/passwdd at ${BASEDIR}/OPAM/repo/default/packages/escape-absolute/escape-absolute.1/files -opam-file Mismatching extra-files at ${BASEDIR}/OPAM/repo/default/packages/good-md5-bad-sha256/good-md5-bad-sha256.1: missing from 'files' directory (1) -opam-file Mismatching extra-files at ${BASEDIR}/OPAM/repo/default/packages/bad-md5/bad-md5.1: wrong checksum (1) +opam-file Mismatching extra-files at packages/good-md5-bad-sha256/good-md5-bad-sha256.1 (out of ${BASEDIR}/OPAM/repo/default): missing from 'files' directory (1) +opam-file Mismatching extra-files at packages/bad-md5/bad-md5.1 (out of ${BASEDIR}/OPAM/repo/default): wrong checksum (1) +opam-file Mismatching extra-files at packages/good-md5-good-sha256/good-md5-good-sha256.1 (out of ${BASEDIR}/OPAM/repo/default): missing from 'files' directory (1) good-md5.1 ### :I:1: good md5 ### opam lint --package good-md5 @@ -382,7 +382,7 @@ Clearing cache of downloaded files ### # extra files is added with its checksum at repo loading ### opam install no-checksum [ERROR] In the opam file for no-checksum.1 from repository default: - - At ${BASEDIR}/OPAM/repo/default/packages/no-checksum/no-checksum.1/opam:11:2-11:13:: + - At packages/no-checksum/no-checksum.1/opam:11:2-11:13:: expected [file checksum] 'extra-files' has been ignored. The following actions will be performed: @@ -407,7 +407,7 @@ The following actions will be performed: Nothing to do. ### opam install no-checksum --require-checksums [ERROR] In the opam file for no-checksum.1 from repository default: - - At ${BASEDIR}/OPAM/repo/default/packages/no-checksum/no-checksum.1/opam:11:2-11:13:: + - At packages/no-checksum/no-checksum.1/opam:11:2-11:13:: expected [file checksum] 'extra-files' has been ignored. The following actions will be performed: @@ -690,7 +690,7 @@ cp p.patch $pkgpath/files/dir/ <><> Updating package repositories ><><><><><><><><><><><><><><><><><><><><><><> [default] synchronised from file://${BASEDIR}/REPO -opam-file Mismatching extra-files at ${BASEDIR}/OPAM/repo/default/packages/good-md5-good-sha256/good-md5-good-sha256.1: missing from 'files' directory (1) +opam-file Mismatching extra-files at packages/good-md5-good-sha256/good-md5-good-sha256.1 (out of ${BASEDIR}/OPAM/repo/default): missing from 'files' directory (1) Now run 'opam upgrade' to apply any package updates. ### opam install good-nested-md5.1 The following actions will be performed: diff --git a/tests/reftests/extrasource.test b/tests/reftests/extrasource.test index be5954a4007..545626011b0 100644 --- a/tests/reftests/extrasource.test +++ b/tests/reftests/extrasource.test @@ -1094,7 +1094,7 @@ Successfully extracted to ${BASEDIR}/not-mentioned.1 # Return code 1 # ### opam install multiple [ERROR] In the opam file for multiple.1 from repository default: - - In ${BASEDIR}/OPAM/repo/default/packages/multiple/multiple.1/opam: + - In packages/multiple/multiple.1/opam: Duplicate section extra-source 'extra-source' has been ignored. The following actions will be performed: @@ -1107,7 +1107,7 @@ The following actions will be performed: Done. ### opam remove multiple [ERROR] In the opam file for multiple.1 from repository default: - - In ${BASEDIR}/OPAM/repo/default/packages/multiple/multiple.1/opam: + - In packages/multiple/multiple.1/opam: Duplicate section extra-source 'extra-source' has been ignored. The following actions will be performed: @@ -1119,7 +1119,7 @@ The following actions will be performed: Done. ### opam install multiple --require-checksums [ERROR] In the opam file for multiple.1 from repository default: - - In ${BASEDIR}/OPAM/repo/default/packages/multiple/multiple.1/opam: + - In packages/multiple/multiple.1/opam: Duplicate section extra-source 'extra-source' has been ignored. The following actions will be performed: diff --git a/tests/reftests/rec-pin.test b/tests/reftests/rec-pin.test index 4f0f71c9573..bd5cbd558c6 100644 --- a/tests/reftests/rec-pin.test +++ b/tests/reftests/rec-pin.test @@ -1237,7 +1237,7 @@ url { <><> Updating package repositories ><><><><><><><><><><><><><><><><><><><><><><> [default] synchronised from file://${BASEDIR}/REPO -[ERROR] In ${BASEDIR}/OPAM/repo/default/packages/subpath-err/subpath-err.1/opam: +[ERROR] In packages/subpath-err/subpath-err.1/opam: The url.subpath field is not allowed in files with `opam-version` <= 2.0 [ERROR] Strict mode: aborting [ERROR] Could not update repository "default": OpamStd.OpamSys.Exit(30) diff --git a/tests/reftests/repository-http.test b/tests/reftests/repository-http.test index 5019f47f339..69d2397f3fe 100644 --- a/tests/reftests/repository-http.test +++ b/tests/reftests/repository-http.test @@ -38,7 +38,7 @@ Done. ### opam repo remove --all default ### opam repo --all | grep -v '^#' ### :I: First checkout: we add the repository and fetch/load it for the first time friom the http server and check that they are available in opam -### OPAMDEBUGSECTIONS="RSTATE REPOSITORY REPO_BACKEND UPDATE" OPAMDEBUG=-3 OPAMVERBOSE=2 +### OPAMDEBUGSECTIONS="TAR RSTATE REPOSITORY REPO_BACKEND UPDATE" OPAMDEBUG=-3 OPAMVERBOSE=2 ### opam repo add http-repo http://localhost:$HTTPSERVERPORT --set-default | sed-cmd tar | grep -v "^+-" | ".*\(curl\|wget\).* \"--\"" -> 'curl-or-wget --' | "${HTTPSERVERPORT}" -> "port" FILE(config) Read ${BASEDIR}/OPAM/config in 0.000s RSTATE LOAD-REPOSITORY-STATE @ ${BASEDIR}/OPAM @@ -47,12 +47,11 @@ REPOSITORY repository-add REPOSITORY update http-repo from http://localhost:port Processing 1/1: [http-repo: http] curl-or-wget -- "http://localhost:port/index.tar.gz" -+ tar "xfz" "${OPAMTMP}/index.tar.gz" "-C" "${BASEDIR}/OPAM/repo/http-repo.new" -REPOSITORY http-repo: applying update from scratch at ${BASEDIR}/OPAM/repo/http-repo.new +REPOSITORY http-repo: applying update from scratch at ${BASEDIR}/OPAM/repo/http-repo.tar.gz.new [http-repo] Initialised UPDATE Repository has new changes Processing: [http-repo: loading data] -RSTATE load repo http-repo from dir +RSTATE load repo http-repo from tgz ### unset OPAMDEBUGSECTIONS ### unset OPAMDEBUG ### unset OPAMVERBOSE @@ -77,7 +76,7 @@ Generating urls.txt... Generating index.tar.gz... Done. ### sh remove-timestamp.sh -### OPAMDEBUGSECTIONS="RSTATE REPOSITORY REPO_BACKEND UPDATE" OPAMDEBUG=-3 OPAMVERBOSE=2 +### OPAMDEBUGSECTIONS="TAR RSTATE REPOSITORY REPO_BACKEND UPDATE" OPAMDEBUG=-3 OPAMVERBOSE=2 ### opam update http-repo | sed-cmd tar | grep -v "^+-" | ".*\(curl\|wget\).* \"--\"" -> 'curl-or-wget --' | "${HTTPSERVERPORT}" -> "port" FILE(config) Read ${BASEDIR}/OPAM/config in 0.000s RSTATE LOAD-REPOSITORY-STATE @ ${BASEDIR}/OPAM @@ -87,11 +86,11 @@ RSTATE Cache found REPOSITORY update http-repo from http://localhost:port Processing 1/1: [http-repo: http] curl-or-wget -- "http://localhost:port/index.tar.gz" -+ tar "xfz" "${OPAMTMP}/index.tar.gz" "-C" "${BASEDIR}/OPAM/repo/http-repo.new" -REPO_BACKEND diff: ${BASEDIR}/OPAM/repo/{http-repo,http-repo.new} +REPO_BACKEND diff: ${BASEDIR}/OPAM/repo/{http-repo.tar.gz,http-repo.tar.gz.new} REPO_BACKEND Internal diff (non-empty, 3 changed files) done in 0.00s. [http-repo] synchronised from http://localhost:port REPOSITORY http-repo: applying patch update at ${BASEDIR}/OPAM/log/patch-xxx +TAR Writing archive ${BASEDIR}/OPAM/repo/http-repo.tar.gz UPDATE Repository has new changes Processing: [http-repo: loading data] RSTATE load repo http-repo from diff @@ -116,7 +115,7 @@ Generating urls.txt... Generating index.tar.gz... Done. ### sh remove-timestamp.sh -### OPAMDEBUGSECTIONS="RSTATE REPOSITORY REPO_BACKEND UPDATE" OPAMDEBUG=-3 OPAMVERBOSE=2 +### OPAMDEBUGSECTIONS="TAR RSTATE REPOSITORY REPO_BACKEND UPDATE" OPAMDEBUG=-3 OPAMVERBOSE=2 ### opam update http-repo | sed-cmd tar | grep -v "^+-" | ".*\(curl\|wget\).* \"--\"" -> 'curl-or-wget --' | "${HTTPSERVERPORT}" -> "port" FILE(config) Read ${BASEDIR}/OPAM/config in 0.000s RSTATE LOAD-REPOSITORY-STATE @ ${BASEDIR}/OPAM @@ -126,15 +125,14 @@ RSTATE Cache found REPOSITORY update http-repo from http://localhost:port Processing 1/1: [http-repo: http] curl-or-wget -- "http://localhost:port/index.tar.gz" -+ tar "xfz" "${OPAMTMP}/index.tar.gz" "-C" "${BASEDIR}/OPAM/repo/http-repo.new" -REPO_BACKEND diff: ${BASEDIR}/OPAM/repo/{http-repo,http-repo.new} +REPO_BACKEND diff: ${BASEDIR}/OPAM/repo/{http-repo.tar.gz,http-repo.tar.gz.new} REPO_BACKEND Internal diff (non-empty, 1 changed files) done in 0.00s. [http-repo] synchronised from http://localhost:port REPOSITORY http-repo: applying patch update at ${BASEDIR}/OPAM/log/patch-xxx +TAR Writing archive ${BASEDIR}/OPAM/repo/http-repo.tar.gz UPDATE Repository has new changes Processing: [http-repo: loading data] RSTATE load repo http-repo from diff -RSTATE ERR: Could not load ${BASEDIR}/OPAM/repo/http-repo/packages/tujuh/tujuh.7/opam, ignored Now run 'opam upgrade' to apply any package updates. ### unset OPAMDEBUGSECTIONS ### unset OPAMDEBUG @@ -157,7 +155,7 @@ Generating urls.txt... Generating index.tar.gz... Done. ### sh remove-timestamp.sh -### OPAMDEBUGSECTIONS="RSTATE REPOSITORY REPO_BACKEND UPDATE" OPAMDEBUG=-3 OPAMVERBOSE=2 +### OPAMDEBUGSECTIONS="TAR RSTATE REPOSITORY REPO_BACKEND UPDATE" OPAMDEBUG=-3 OPAMVERBOSE=2 ### opam update http-repo | sed-cmd tar | grep -v "^+-" | ".*\(curl\|wget\).* \"--\"" -> 'curl-or-wget --' | "${HTTPSERVERPORT}" -> "port" FILE(config) Read ${BASEDIR}/OPAM/config in 0.000s RSTATE LOAD-REPOSITORY-STATE @ ${BASEDIR}/OPAM @@ -167,11 +165,11 @@ RSTATE Cache found REPOSITORY update http-repo from http://localhost:port Processing 1/1: [http-repo: http] curl-or-wget -- "http://localhost:port/index.tar.gz" -+ tar "xfz" "${OPAMTMP}/index.tar.gz" "-C" "${BASEDIR}/OPAM/repo/http-repo.new" -REPO_BACKEND diff: ${BASEDIR}/OPAM/repo/{http-repo,http-repo.new} +REPO_BACKEND diff: ${BASEDIR}/OPAM/repo/{http-repo.tar.gz,http-repo.tar.gz.new} REPO_BACKEND Internal diff (non-empty, 1 changed files) done in 0.00s. [http-repo] synchronised from http://localhost:port REPOSITORY http-repo: applying patch update at ${BASEDIR}/OPAM/log/patch-xxx +TAR Writing archive ${BASEDIR}/OPAM/repo/http-repo.tar.gz UPDATE Repository has new changes Processing: [http-repo: loading data] RSTATE load repo http-repo from diff diff --git a/tests/reftests/repository-layout.test b/tests/reftests/repository-layout.test index bfcbc78cbc7..7fb8cf6e49e 100644 --- a/tests/reftests/repository-layout.test +++ b/tests/reftests/repository-layout.test @@ -147,7 +147,7 @@ RSTATE Cache found [new-default-strict] Initialised UPDATE Repository has new changes RSTATE load repo new-default-strict from dir -FILE(opam) Read ${BASEDIR}/OPAM/repo/new-default-strict/packages/good/good.1/opam in 0.000s +FILE(opam) Read packages/good/good.1/opam (out of ${BASEDIR}/OPAM/repo/new-default-strict) in 0.000s ### OPAMDEBUGSECTIONS="FILE(opam) opam-file RSTATE UPDATE" OPAMDEBUG=-3 opam repository add new-default ./REPO --this-switch FILE(config) Read ${BASEDIR}/OPAM/config in 0.000s RSTATE LOAD-REPOSITORY-STATE @ ${BASEDIR}/OPAM @@ -155,7 +155,13 @@ RSTATE Cache found [new-default] Initialised UPDATE Repository has new changes RSTATE load repo new-default from dir -FILE(opam) Read ${BASEDIR}/OPAM/repo/new-default/packages/good/good.1/opam in 0.000s +FILE(opam) Read packages/good/good.1/opam (out of ${BASEDIR}/OPAM/repo/new-default) in 0.000s +### OPAMDEBUGSECTIONS="FILE(opam) opam-file RSTATE UPDATE" OPAMDEBUG=-3 opam repository add new-default ./REPO --this-switch | unordered +[new-default] no changes from file://${BASEDIR}/REPO +UPDATE Repository did not change: nothing to do. +FILE(config) Read ${BASEDIR}/OPAM/config in 0.000s +RSTATE LOAD-REPOSITORY-STATE @ ${BASEDIR}/OPAM +RSTATE Cache found ### :I:1:b: List available package ### opam switch create good-sw-from-scratch --empty --repo=new-default,new-default-strict ### opam repository --this-switch @@ -189,7 +195,7 @@ RSTATE Cache found [default-strict] synchronised from file://${BASEDIR}/REPO UPDATE Repository has new changes RSTATE load repo default-strict from diff -FILE(opam) Read ${BASEDIR}/OPAM/repo/default-strict/packages/good/good.1/opam in 0.000s +FILE(opam) Read packages/good/good.1/opam (out of ${BASEDIR}/OPAM/repo/default-strict) in 0.000s RSTATE ERR: Could not load ${BASEDIR}/OPAM/repo/default-strict/packages/good/good.1/files/un/der/opam, ignored Now run 'opam upgrade' to apply any package updates. ### OPAMDEBUGSECTIONS="FILE(opam) opam-file RSTATE UPDATE" OPAMDEBUG=-3 opam update default @@ -201,7 +207,7 @@ RSTATE Cache found [default] synchronised from file://${BASEDIR}/REPO UPDATE Repository has new changes RSTATE load repo default from diff -FILE(opam) Read ${BASEDIR}/OPAM/repo/default/packages/good/good.1/opam in 0.000s +FILE(opam) Read packages/good/good.1/opam (out of ${BASEDIR}/OPAM/repo/default) in 0.000s RSTATE ERR: Could not load ${BASEDIR}/OPAM/repo/default/packages/good/good.1/files/un/der/opam, ignored Now run 'opam upgrade' to apply any package updates. ### :I:2:b List available package @@ -239,8 +245,8 @@ RSTATE Cache found [default-strict] synchronised from file://${BASEDIR}/REPO UPDATE Repository has new changes RSTATE load repo default-strict from diff -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 packages/good/good.1/opam (out of ${BASEDIR}/OPAM/repo/default-strict) in 0.000s +opam-file Mismatching extra-files at packages/good/good.1 (out of ${BASEDIR}/OPAM/repo/default-strict): missing from 'files' directory (1) Now run 'opam upgrade' to apply any package updates. ### OPAMDEBUGSECTIONS="FILE(opam) opam-file RSTATE UPDATE" OPAMDEBUG=-3 opam update default FILE(config) Read ${BASEDIR}/OPAM/config in 0.000s @@ -251,8 +257,8 @@ RSTATE Cache found [default] synchronised from file://${BASEDIR}/REPO UPDATE Repository has new changes RSTATE load repo default from diff -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 packages/good/good.1/opam (out of ${BASEDIR}/OPAM/repo/default) in 0.000s +opam-file Mismatching extra-files at packages/good/good.1 (out of ${BASEDIR}/OPAM/repo/default): missing from 'files' directory (1) Now run 'opam upgrade' to apply any package updates. ### :I:3:b: Add the last extrafile and update ### sh xfile.sh packages/good/good.1 @@ -319,8 +325,8 @@ RSTATE Cache found [new-default-strict] Initialised UPDATE Repository has new changes RSTATE load repo new-default-strict from dir -FILE(opam) Read ${BASEDIR}/OPAM/repo/new-default-strict/packages/good/good.1/opam in 0.000s -FILE(opam) Read ${BASEDIR}/OPAM/repo/new-default-strict/packages/not/no-n-nv.1/opam in 0.000s +FILE(opam) Read packages/good/good.1/opam (out of ${BASEDIR}/OPAM/repo/new-default-strict) in 0.000s +FILE(opam) Read packages/not/no-n-nv.1/opam (out of ${BASEDIR}/OPAM/repo/new-default-strict) in 0.000s ### OPAMDEBUGSECTIONS="FILE(opam) opam-file RSTATE UPDATE" OPAMDEBUG=-3 opam repository add new-default ./REPO --this-switch FILE(config) Read ${BASEDIR}/OPAM/config in 0.000s RSTATE LOAD-REPOSITORY-STATE @ ${BASEDIR}/OPAM @@ -328,8 +334,14 @@ RSTATE Cache found [new-default] Initialised UPDATE Repository has new changes RSTATE load repo new-default from dir -FILE(opam) Read ${BASEDIR}/OPAM/repo/new-default/packages/good/good.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 packages/good/good.1/opam (out of ${BASEDIR}/OPAM/repo/new-default) in 0.000s +FILE(opam) Read packages/not/no-n-nv.1/opam (out of ${BASEDIR}/OPAM/repo/new-default) in 0.000s +### OPAMDEBUGSECTIONS="FILE(opam) opam-file RSTATE UPDATE" OPAMDEBUG=-3 opam repository add new-default ./REPO --this-switch | unordered +[new-default] no changes from file://${BASEDIR}/REPO +UPDATE Repository did not change: nothing to do. +FILE(config) Read ${BASEDIR}/OPAM/config in 0.000s +RSTATE LOAD-REPOSITORY-STATE @ ${BASEDIR}/OPAM +RSTATE Cache found ### :II:1:b: List available package ### opam switch create no-n-nv-sw-from-scratch --empty --repo=new-default,new-default-strict ### opam repository --this-switch @@ -364,7 +376,7 @@ RSTATE Cache found [default-strict] synchronised from file://${BASEDIR}/REPO UPDATE Repository has new changes RSTATE load repo default-strict from diff -FILE(opam) Read ${BASEDIR}/OPAM/repo/default-strict/packages/not/no-n-nv.1/opam in 0.000s +FILE(opam) Read packages/not/no-n-nv.1/opam (out of ${BASEDIR}/OPAM/repo/default-strict) in 0.000s RSTATE ERR: Could not load ${BASEDIR}/OPAM/repo/default-strict/packages/not/no-n-nv.1/files/un/der/opam, ignored Now run 'opam upgrade' to apply any package updates. ### OPAMDEBUGSECTIONS="FILE(opam) opam-file RSTATE UPDATE" OPAMDEBUG=-3 opam update default @@ -376,7 +388,7 @@ RSTATE Cache found [default] synchronised from file://${BASEDIR}/REPO UPDATE Repository has new changes RSTATE load repo default from diff -FILE(opam) Read ${BASEDIR}/OPAM/repo/default/packages/not/no-n-nv.1/opam in 0.000s +FILE(opam) Read packages/not/no-n-nv.1/opam (out of ${BASEDIR}/OPAM/repo/default) in 0.000s RSTATE ERR: Could not load ${BASEDIR}/OPAM/repo/default/packages/not/no-n-nv.1/files/un/der/opam, ignored Now run 'opam upgrade' to apply any package updates. ### :II:2:b List available package @@ -414,8 +426,8 @@ RSTATE Cache found [default-strict] synchronised from file://${BASEDIR}/REPO UPDATE Repository has new changes RSTATE load repo default-strict from diff -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) +FILE(opam) Read packages/not/no-n-nv.1/opam (out of ${BASEDIR}/OPAM/repo/default-strict) in 0.000s +opam-file Mismatching extra-files at packages/not/no-n-nv.1 (out of ${BASEDIR}/OPAM/repo/default-strict): missing from 'files' directory (1) Now run 'opam upgrade' to apply any package updates. ### OPAMDEBUGSECTIONS="FILE(opam) opam-file RSTATE UPDATE" OPAMDEBUG=-3 opam update default FILE(config) Read ${BASEDIR}/OPAM/config in 0.000s @@ -426,8 +438,8 @@ RSTATE Cache found [default] synchronised from file://${BASEDIR}/REPO UPDATE Repository has new changes RSTATE load repo default from diff -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 packages/not/no-n-nv.1/opam (out of ${BASEDIR}/OPAM/repo/default) in 0.000s +opam-file Mismatching extra-files at packages/not/no-n-nv.1 (out of ${BASEDIR}/OPAM/repo/default): missing from 'files' directory (1) Now run 'opam upgrade' to apply any package updates. ### :II:3:b: Add the last extrafile and update ### sh xfile.sh packages/not/no-n-nv.1 @@ -495,9 +507,9 @@ RSTATE Cache found [new-default-strict] Initialised UPDATE Repository has new changes RSTATE load repo new-default-strict from dir -FILE(opam) Read ${BASEDIR}/OPAM/repo/new-default-strict/packages/good/good.1/opam in 0.000s -FILE(opam) Read ${BASEDIR}/OPAM/repo/new-default-strict/packages/not/no-n-nv.1/opam in 0.000s -FILE(opam) Read ${BASEDIR}/OPAM/repo/new-default-strict/packages/v/e/r/y/very-inner-nv.1/opam in 0.000s +FILE(opam) Read packages/good/good.1/opam (out of ${BASEDIR}/OPAM/repo/new-default-strict) in 0.000s +FILE(opam) Read packages/not/no-n-nv.1/opam (out of ${BASEDIR}/OPAM/repo/new-default-strict) in 0.000s +FILE(opam) Read packages/v/e/r/y/very-inner-nv.1/opam (out of ${BASEDIR}/OPAM/repo/new-default-strict) in 0.000s ### OPAMDEBUGSECTIONS="FILE(opam) opam-file RSTATE UPDATE" OPAMDEBUG=-3 opam repository add new-default ./REPO --this-switch FILE(config) Read ${BASEDIR}/OPAM/config in 0.000s RSTATE LOAD-REPOSITORY-STATE @ ${BASEDIR}/OPAM @@ -505,9 +517,15 @@ RSTATE Cache found [new-default] Initialised UPDATE Repository has new changes RSTATE load repo new-default from dir -FILE(opam) Read ${BASEDIR}/OPAM/repo/new-default/packages/good/good.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/v/e/r/y/very-inner-nv.1/opam in 0.000s +FILE(opam) Read packages/good/good.1/opam (out of ${BASEDIR}/OPAM/repo/new-default) in 0.000s +FILE(opam) Read packages/not/no-n-nv.1/opam (out of ${BASEDIR}/OPAM/repo/new-default) in 0.000s +FILE(opam) Read packages/v/e/r/y/very-inner-nv.1/opam (out of ${BASEDIR}/OPAM/repo/new-default) in 0.000s +### OPAMDEBUGSECTIONS="FILE(opam) opam-file RSTATE UPDATE" OPAMDEBUG=-3 opam repository add new-default ./REPO --this-switch | unordered +[new-default] no changes from file://${BASEDIR}/REPO +UPDATE Repository did not change: nothing to do. +FILE(config) Read ${BASEDIR}/OPAM/config in 0.000s +RSTATE LOAD-REPOSITORY-STATE @ ${BASEDIR}/OPAM +RSTATE Cache found ### :III:1:b: List available package ### opam switch create very-inner-nv-sw-from-scratch --empty --repo=new-default,new-default-strict ### opam repository --this-switch @@ -543,7 +561,7 @@ RSTATE Cache found [default-strict] synchronised from file://${BASEDIR}/REPO UPDATE Repository has new changes RSTATE load repo default-strict from diff -FILE(opam) Read ${BASEDIR}/OPAM/repo/default-strict/packages/v/e/r/y/very-inner-nv.1/opam in 0.000s +FILE(opam) Read packages/v/e/r/y/very-inner-nv.1/opam (out of ${BASEDIR}/OPAM/repo/default-strict) in 0.000s RSTATE ERR: Could not load ${BASEDIR}/OPAM/repo/default-strict/packages/v/e/r/y/very-inner-nv.1/files/un/der/opam, ignored Now run 'opam upgrade' to apply any package updates. ### OPAMDEBUGSECTIONS="FILE(opam) opam-file RSTATE UPDATE" OPAMDEBUG=-3 opam update default @@ -555,7 +573,7 @@ RSTATE Cache found [default] synchronised from file://${BASEDIR}/REPO UPDATE Repository has new changes RSTATE load repo default from diff -FILE(opam) Read ${BASEDIR}/OPAM/repo/default/packages/v/e/r/y/very-inner-nv.1/opam in 0.000s +FILE(opam) Read packages/v/e/r/y/very-inner-nv.1/opam (out of ${BASEDIR}/OPAM/repo/default) in 0.000s RSTATE ERR: Could not load ${BASEDIR}/OPAM/repo/default/packages/v/e/r/y/very-inner-nv.1/files/un/der/opam, ignored Now run 'opam upgrade' to apply any package updates. ### :III:2:b List available package @@ -593,8 +611,8 @@ RSTATE Cache found [default-strict] synchronised from file://${BASEDIR}/REPO UPDATE Repository has new changes RSTATE load repo default-strict from diff -FILE(opam) Read ${BASEDIR}/OPAM/repo/default-strict/packages/v/e/r/y/very-inner-nv.1/opam in 0.000s -opam-file Mismatching extra-files at ${BASEDIR}/OPAM/repo/default-strict/packages/v/e/r/y/very-inner-nv.1: missing from 'files' directory (1) +FILE(opam) Read packages/v/e/r/y/very-inner-nv.1/opam (out of ${BASEDIR}/OPAM/repo/default-strict) in 0.000s +opam-file Mismatching extra-files at packages/v/e/r/y/very-inner-nv.1 (out of ${BASEDIR}/OPAM/repo/default-strict): missing from 'files' directory (1) Now run 'opam upgrade' to apply any package updates. ### OPAMDEBUGSECTIONS="FILE(opam) opam-file RSTATE UPDATE" OPAMDEBUG=-3 opam update default FILE(config) Read ${BASEDIR}/OPAM/config in 0.000s @@ -605,8 +623,8 @@ RSTATE Cache found [default] synchronised from file://${BASEDIR}/REPO UPDATE Repository has new changes RSTATE load repo default from diff -FILE(opam) Read ${BASEDIR}/OPAM/repo/default/packages/v/e/r/y/very-inner-nv.1/opam in 0.000s -opam-file Mismatching extra-files at ${BASEDIR}/OPAM/repo/default/packages/v/e/r/y/very-inner-nv.1: missing from 'files' directory (1) +FILE(opam) Read packages/v/e/r/y/very-inner-nv.1/opam (out of ${BASEDIR}/OPAM/repo/default) in 0.000s +opam-file Mismatching extra-files at packages/v/e/r/y/very-inner-nv.1 (out of ${BASEDIR}/OPAM/repo/default): missing from 'files' directory (1) Now run 'opam upgrade' to apply any package updates. ### :III:3:b: Add the last extrafile and update ### sh xfile.sh packages/v/e/r/y/very-inner-nv.1 @@ -675,10 +693,10 @@ RSTATE Cache found [new-default-strict] Initialised UPDATE Repository has new changes RSTATE load repo new-default-strict from dir -FILE(opam) Read ${BASEDIR}/OPAM/repo/new-default-strict/packages/good/good.1/opam in 0.000s -FILE(opam) Read ${BASEDIR}/OPAM/repo/new-default-strict/packages/i/n/e/r/very-inner-n-nv/very-inner-n-nv.1/opam in 0.000s -FILE(opam) Read ${BASEDIR}/OPAM/repo/new-default-strict/packages/not/no-n-nv.1/opam in 0.000s -FILE(opam) Read ${BASEDIR}/OPAM/repo/new-default-strict/packages/v/e/r/y/very-inner-nv.1/opam in 0.000s +FILE(opam) Read packages/good/good.1/opam (out of ${BASEDIR}/OPAM/repo/new-default-strict) in 0.000s +FILE(opam) Read packages/i/n/e/r/very-inner-n-nv/very-inner-n-nv.1/opam (out of ${BASEDIR}/OPAM/repo/new-default-strict) in 0.000s +FILE(opam) Read packages/not/no-n-nv.1/opam (out of ${BASEDIR}/OPAM/repo/new-default-strict) in 0.000s +FILE(opam) Read packages/v/e/r/y/very-inner-nv.1/opam (out of ${BASEDIR}/OPAM/repo/new-default-strict) in 0.000s ### OPAMDEBUGSECTIONS="FILE(opam) opam-file RSTATE UPDATE" OPAMDEBUG=-3 opam repository add new-default ./REPO --this-switch FILE(config) Read ${BASEDIR}/OPAM/config in 0.000s RSTATE LOAD-REPOSITORY-STATE @ ${BASEDIR}/OPAM @@ -686,10 +704,16 @@ RSTATE Cache found [new-default] Initialised UPDATE Repository has new changes RSTATE load repo new-default from dir -FILE(opam) Read ${BASEDIR}/OPAM/repo/new-default/packages/good/good.1/opam in 0.000s -FILE(opam) Read ${BASEDIR}/OPAM/repo/new-default/packages/i/n/e/r/very-inner-n-nv/very-inner-n-nv.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/v/e/r/y/very-inner-nv.1/opam in 0.000s +FILE(opam) Read packages/good/good.1/opam (out of ${BASEDIR}/OPAM/repo/new-default) in 0.000s +FILE(opam) Read packages/i/n/e/r/very-inner-n-nv/very-inner-n-nv.1/opam (out of ${BASEDIR}/OPAM/repo/new-default) in 0.000s +FILE(opam) Read packages/not/no-n-nv.1/opam (out of ${BASEDIR}/OPAM/repo/new-default) in 0.000s +FILE(opam) Read packages/v/e/r/y/very-inner-nv.1/opam (out of ${BASEDIR}/OPAM/repo/new-default) in 0.000s +### OPAMDEBUGSECTIONS="FILE(opam) opam-file RSTATE UPDATE" OPAMDEBUG=-3 opam repository add new-default ./REPO --this-switch | unordered +[new-default] no changes from file://${BASEDIR}/REPO +UPDATE Repository did not change: nothing to do. +FILE(config) Read ${BASEDIR}/OPAM/config in 0.000s +RSTATE LOAD-REPOSITORY-STATE @ ${BASEDIR}/OPAM +RSTATE Cache found ### OPAMDEBUGSECTIONS="FILE(opam) opam-file RSTATE UPDATE" OPAMDEBUG=-3 opam repository add new-default ./REPO --this-switch | unordered [new-default] no changes from file://${BASEDIR}/REPO UPDATE Repository did not change: nothing to do. @@ -732,7 +756,7 @@ RSTATE Cache found [default-strict] synchronised from file://${BASEDIR}/REPO UPDATE Repository has new changes RSTATE load repo default-strict from diff -FILE(opam) Read ${BASEDIR}/OPAM/repo/default-strict/packages/i/n/e/r/very-inner-n-nv/very-inner-n-nv.1/opam in 0.000s +FILE(opam) Read packages/i/n/e/r/very-inner-n-nv/very-inner-n-nv.1/opam (out of ${BASEDIR}/OPAM/repo/default-strict) in 0.000s RSTATE ERR: Could not load ${BASEDIR}/OPAM/repo/default-strict/packages/i/n/e/r/very-inner-n-nv/very-inner-n-nv.1/files/un/der/opam, ignored Now run 'opam upgrade' to apply any package updates. ### OPAMDEBUGSECTIONS="FILE(opam) opam-file RSTATE UPDATE" OPAMDEBUG=-3 opam update default @@ -744,7 +768,7 @@ RSTATE Cache found [default] synchronised from file://${BASEDIR}/REPO UPDATE Repository has new changes RSTATE load repo default from diff -FILE(opam) Read ${BASEDIR}/OPAM/repo/default/packages/i/n/e/r/very-inner-n-nv/very-inner-n-nv.1/opam in 0.000s +FILE(opam) Read packages/i/n/e/r/very-inner-n-nv/very-inner-n-nv.1/opam (out of ${BASEDIR}/OPAM/repo/default) in 0.000s RSTATE ERR: Could not load ${BASEDIR}/OPAM/repo/default/packages/i/n/e/r/very-inner-n-nv/very-inner-n-nv.1/files/un/der/opam, ignored Now run 'opam upgrade' to apply any package updates. ### :IV:2:b List available package @@ -782,8 +806,8 @@ RSTATE Cache found [default-strict] synchronised from file://${BASEDIR}/REPO UPDATE Repository has new changes RSTATE load repo default-strict from diff -FILE(opam) Read ${BASEDIR}/OPAM/repo/default-strict/packages/i/n/e/r/very-inner-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-inner-n-nv/very-inner-n-nv.1: missing from 'files' directory (1) +FILE(opam) Read packages/i/n/e/r/very-inner-n-nv/very-inner-n-nv.1/opam (out of ${BASEDIR}/OPAM/repo/default-strict) in 0.000s +opam-file Mismatching extra-files at packages/i/n/e/r/very-inner-n-nv/very-inner-n-nv.1 (out of ${BASEDIR}/OPAM/repo/default-strict): missing from 'files' directory (1) Now run 'opam upgrade' to apply any package updates. ### OPAMDEBUGSECTIONS="FILE(opam) opam-file RSTATE UPDATE" OPAMDEBUG=-3 opam update default FILE(config) Read ${BASEDIR}/OPAM/config in 0.000s @@ -794,8 +818,8 @@ RSTATE Cache found [default] synchronised from file://${BASEDIR}/REPO UPDATE Repository has new changes RSTATE load repo default from diff -FILE(opam) Read ${BASEDIR}/OPAM/repo/default/packages/i/n/e/r/very-inner-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-inner-n-nv/very-inner-n-nv.1: missing from 'files' directory (1) +FILE(opam) Read packages/i/n/e/r/very-inner-n-nv/very-inner-n-nv.1/opam (out of ${BASEDIR}/OPAM/repo/default) in 0.000s +opam-file Mismatching extra-files at packages/i/n/e/r/very-inner-n-nv/very-inner-n-nv.1 (out of ${BASEDIR}/OPAM/repo/default): missing from 'files' directory (1) Now run 'opam upgrade' to apply any package updates. ### :IV:3:b: Add the last extrafile and update ### sh xfile.sh packages/i/n/e/r/very-inner-n-nv/very-inner-n-nv.1 @@ -865,11 +889,11 @@ RSTATE Cache found [new-default-strict] Initialised UPDATE Repository has new changes RSTATE load repo new-default-strict from dir -FILE(opam) Read ${BASEDIR}/OPAM/repo/new-default-strict/packages/direct-root.1/opam in 0.000s -FILE(opam) Read ${BASEDIR}/OPAM/repo/new-default-strict/packages/good/good.1/opam in 0.000s -FILE(opam) Read ${BASEDIR}/OPAM/repo/new-default-strict/packages/i/n/e/r/very-inner-n-nv/very-inner-n-nv.1/opam in 0.000s -FILE(opam) Read ${BASEDIR}/OPAM/repo/new-default-strict/packages/not/no-n-nv.1/opam in 0.000s -FILE(opam) Read ${BASEDIR}/OPAM/repo/new-default-strict/packages/v/e/r/y/very-inner-nv.1/opam in 0.000s +FILE(opam) Read packages/direct-root.1/opam (out of ${BASEDIR}/OPAM/repo/new-default-strict) in 0.000s +FILE(opam) Read packages/good/good.1/opam (out of ${BASEDIR}/OPAM/repo/new-default-strict) in 0.000s +FILE(opam) Read packages/i/n/e/r/very-inner-n-nv/very-inner-n-nv.1/opam (out of ${BASEDIR}/OPAM/repo/new-default-strict) in 0.000s +FILE(opam) Read packages/not/no-n-nv.1/opam (out of ${BASEDIR}/OPAM/repo/new-default-strict) in 0.000s +FILE(opam) Read packages/v/e/r/y/very-inner-nv.1/opam (out of ${BASEDIR}/OPAM/repo/new-default-strict) in 0.000s ### OPAMDEBUGSECTIONS="FILE(opam) opam-file RSTATE UPDATE" OPAMDEBUG=-3 opam repository add new-default ./REPO --this-switch FILE(config) Read ${BASEDIR}/OPAM/config in 0.000s RSTATE LOAD-REPOSITORY-STATE @ ${BASEDIR}/OPAM @@ -877,11 +901,17 @@ RSTATE Cache found [new-default] Initialised UPDATE Repository has new changes RSTATE load repo new-default from dir -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/good/good.1/opam in 0.000s -FILE(opam) Read ${BASEDIR}/OPAM/repo/new-default/packages/i/n/e/r/very-inner-n-nv/very-inner-n-nv.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/v/e/r/y/very-inner-nv.1/opam in 0.000s +FILE(opam) Read packages/direct-root.1/opam (out of ${BASEDIR}/OPAM/repo/new-default) in 0.000s +FILE(opam) Read packages/good/good.1/opam (out of ${BASEDIR}/OPAM/repo/new-default) in 0.000s +FILE(opam) Read packages/i/n/e/r/very-inner-n-nv/very-inner-n-nv.1/opam (out of ${BASEDIR}/OPAM/repo/new-default) in 0.000s +FILE(opam) Read packages/not/no-n-nv.1/opam (out of ${BASEDIR}/OPAM/repo/new-default) in 0.000s +FILE(opam) Read packages/v/e/r/y/very-inner-nv.1/opam (out of ${BASEDIR}/OPAM/repo/new-default) in 0.000s +### OPAMDEBUGSECTIONS="FILE(opam) opam-file RSTATE UPDATE" OPAMDEBUG=-3 opam repository add new-default ./REPO --this-switch | unordered +[new-default] no changes from file://${BASEDIR}/REPO +UPDATE Repository did not change: nothing to do. +FILE(config) Read ${BASEDIR}/OPAM/config in 0.000s +RSTATE LOAD-REPOSITORY-STATE @ ${BASEDIR}/OPAM +RSTATE Cache found ### :V:1:b: List available package ### opam switch create direct-root-sw-from-scratch --empty --repo=new-default,new-default-strict ### opam repository --this-switch @@ -919,7 +949,7 @@ RSTATE Cache found [default-strict] synchronised from file://${BASEDIR}/REPO UPDATE Repository has new changes RSTATE load repo default-strict from diff -FILE(opam) Read ${BASEDIR}/OPAM/repo/default-strict/packages/direct-root.1/opam in 0.000s +FILE(opam) Read packages/direct-root.1/opam (out of ${BASEDIR}/OPAM/repo/default-strict) in 0.000s RSTATE ERR: Could not load ${BASEDIR}/OPAM/repo/default-strict/packages/direct-root.1/files/un/der/opam, ignored Now run 'opam upgrade' to apply any package updates. ### OPAMDEBUGSECTIONS="FILE(opam) opam-file RSTATE UPDATE" OPAMDEBUG=-3 opam update default @@ -931,7 +961,7 @@ RSTATE Cache found [default] synchronised from file://${BASEDIR}/REPO UPDATE Repository has new changes RSTATE load repo default from diff -FILE(opam) Read ${BASEDIR}/OPAM/repo/default/packages/direct-root.1/opam in 0.000s +FILE(opam) Read packages/direct-root.1/opam (out of ${BASEDIR}/OPAM/repo/default) in 0.000s RSTATE ERR: Could not load ${BASEDIR}/OPAM/repo/default/packages/direct-root.1/files/un/der/opam, ignored Now run 'opam upgrade' to apply any package updates. ### :V:2:b List available package @@ -969,8 +999,8 @@ RSTATE Cache found [default-strict] synchronised from file://${BASEDIR}/REPO UPDATE Repository has new changes RSTATE load repo default-strict from diff -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 packages/direct-root.1/opam (out of ${BASEDIR}/OPAM/repo/default-strict) in 0.000s +opam-file Mismatching extra-files at packages/direct-root.1 (out of ${BASEDIR}/OPAM/repo/default-strict): missing from 'files' directory (1) Now run 'opam upgrade' to apply any package updates. ### OPAMDEBUGSECTIONS="FILE(opam) opam-file RSTATE UPDATE" OPAMDEBUG=-3 opam update default FILE(config) Read ${BASEDIR}/OPAM/config in 0.000s @@ -981,8 +1011,8 @@ RSTATE Cache found [default] synchronised from file://${BASEDIR}/REPO UPDATE Repository has new changes RSTATE load repo default from diff -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 packages/direct-root.1/opam (out of ${BASEDIR}/OPAM/repo/default) in 0.000s +opam-file Mismatching extra-files at packages/direct-root.1 (out of ${BASEDIR}/OPAM/repo/default): missing from 'files' directory (1) Now run 'opam upgrade' to apply any package updates. ### :V:3:b: Add the last extrafile and update ### sh xfile.sh packages/direct-root.1 @@ -1054,13 +1084,13 @@ RSTATE Cache found [new-default-strict] Initialised UPDATE Repository has new changes RSTATE load repo new-default-strict from dir -FILE(opam) Read ${BASEDIR}/OPAM/repo/new-default-strict/packages/direct-root.1/opam in 0.000s -FILE(opam) Read ${BASEDIR}/OPAM/repo/new-default-strict/packages/good/good.1/opam in 0.000s -FILE(opam) Read ${BASEDIR}/OPAM/repo/new-default-strict/packages/i/n/e/r/very-inner-n-nv/very-inner-n-nv.1/opam in 0.000s -FILE(opam) Read ${BASEDIR}/OPAM/repo/new-default-strict/packages/no-nv/opam in 0.000s +FILE(opam) Read packages/direct-root.1/opam (out of ${BASEDIR}/OPAM/repo/new-default-strict) in 0.000s +FILE(opam) Read packages/good/good.1/opam (out of ${BASEDIR}/OPAM/repo/new-default-strict) in 0.000s +FILE(opam) Read packages/i/n/e/r/very-inner-n-nv/very-inner-n-nv.1/opam (out of ${BASEDIR}/OPAM/repo/new-default-strict) in 0.000s +FILE(opam) Read packages/no-nv/opam (out of ${BASEDIR}/OPAM/repo/new-default-strict) in 0.000s RSTATE ERR: directory name not a valid package: ignored ${BASEDIR}/OPAM/repo/new-default-strict/packages/no-nv/opam -FILE(opam) Read ${BASEDIR}/OPAM/repo/new-default-strict/packages/not/no-n-nv.1/opam in 0.000s -FILE(opam) Read ${BASEDIR}/OPAM/repo/new-default-strict/packages/v/e/r/y/very-inner-nv.1/opam in 0.000s +FILE(opam) Read packages/not/no-n-nv.1/opam (out of ${BASEDIR}/OPAM/repo/new-default-strict) in 0.000s +FILE(opam) Read packages/v/e/r/y/very-inner-nv.1/opam (out of ${BASEDIR}/OPAM/repo/new-default-strict) in 0.000s ### OPAMDEBUGSECTIONS="FILE(opam) opam-file RSTATE UPDATE" OPAMDEBUG=-3 opam repository add new-default ./REPO --this-switch FILE(config) Read ${BASEDIR}/OPAM/config in 0.000s RSTATE LOAD-REPOSITORY-STATE @ ${BASEDIR}/OPAM @@ -1068,13 +1098,19 @@ RSTATE Cache found [new-default] Initialised UPDATE Repository has new changes RSTATE load repo new-default from dir -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/good/good.1/opam in 0.000s -FILE(opam) Read ${BASEDIR}/OPAM/repo/new-default/packages/i/n/e/r/very-inner-n-nv/very-inner-n-nv.1/opam in 0.000s -FILE(opam) Read ${BASEDIR}/OPAM/repo/new-default/packages/no-nv/opam in 0.000s +FILE(opam) Read packages/direct-root.1/opam (out of ${BASEDIR}/OPAM/repo/new-default) in 0.000s +FILE(opam) Read packages/good/good.1/opam (out of ${BASEDIR}/OPAM/repo/new-default) in 0.000s +FILE(opam) Read packages/i/n/e/r/very-inner-n-nv/very-inner-n-nv.1/opam (out of ${BASEDIR}/OPAM/repo/new-default) in 0.000s +FILE(opam) Read packages/no-nv/opam (out of ${BASEDIR}/OPAM/repo/new-default) in 0.000s RSTATE ERR: directory name not a valid package: ignored ${BASEDIR}/OPAM/repo/new-default/packages/no-nv/opam -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/v/e/r/y/very-inner-nv.1/opam in 0.000s +FILE(opam) Read packages/not/no-n-nv.1/opam (out of ${BASEDIR}/OPAM/repo/new-default) in 0.000s +FILE(opam) Read packages/v/e/r/y/very-inner-nv.1/opam (out of ${BASEDIR}/OPAM/repo/new-default) in 0.000s +### OPAMDEBUGSECTIONS="FILE(opam) opam-file RSTATE UPDATE" OPAMDEBUG=-3 opam repository add new-default ./REPO --this-switch | unordered +[new-default] no changes from file://${BASEDIR}/REPO +UPDATE Repository did not change: nothing to do. +FILE(config) Read ${BASEDIR}/OPAM/config in 0.000s +RSTATE LOAD-REPOSITORY-STATE @ ${BASEDIR}/OPAM +RSTATE Cache found ### :VI:1:b: List available package ### opam switch create no-nv-sw-from-scratch --empty --repo=new-default,new-default-strict ### opam repository --this-switch @@ -1107,7 +1143,7 @@ RSTATE Cache found [default-strict] synchronised from file://${BASEDIR}/REPO UPDATE Repository has new changes RSTATE load repo default-strict from diff -FILE(opam) Read ${BASEDIR}/OPAM/repo/default-strict/packages/no-nv/opam in 0.000s +FILE(opam) Read packages/no-nv/opam (out of ${BASEDIR}/OPAM/repo/default-strict) in 0.000s RSTATE ERR: directory name not a valid package: ignored ${BASEDIR}/OPAM/repo/default-strict/packages/no-nv/opam RSTATE ERR: Could not load ${BASEDIR}/OPAM/repo/default-strict/packages/no-nv/files/un/der/opam, ignored ### OPAMDEBUGSECTIONS="FILE(opam) opam-file RSTATE UPDATE" OPAMDEBUG=-3 opam update default @@ -1119,7 +1155,7 @@ RSTATE Cache found [default] synchronised from file://${BASEDIR}/REPO UPDATE Repository has new changes RSTATE load repo default from diff -FILE(opam) Read ${BASEDIR}/OPAM/repo/default/packages/no-nv/opam in 0.000s +FILE(opam) Read packages/no-nv/opam (out of ${BASEDIR}/OPAM/repo/default) in 0.000s RSTATE ERR: directory name not a valid package: ignored ${BASEDIR}/OPAM/repo/default/packages/no-nv/opam RSTATE ERR: Could not load ${BASEDIR}/OPAM/repo/default/packages/no-nv/files/un/der/opam, ignored ### :VI:2:b List available package @@ -1153,8 +1189,8 @@ RSTATE Cache found [default-strict] synchronised from file://${BASEDIR}/REPO UPDATE Repository has new changes RSTATE load repo default-strict from diff -FILE(opam) Read ${BASEDIR}/OPAM/repo/default-strict/packages/no-nv/opam in 0.000s -opam-file Mismatching extra-files at ${BASEDIR}/OPAM/repo/default-strict/packages/no-nv: missing from 'files' directory (1) +FILE(opam) Read packages/no-nv/opam (out of ${BASEDIR}/OPAM/repo/default-strict) in 0.000s +opam-file Mismatching extra-files at packages/no-nv (out of ${BASEDIR}/OPAM/repo/default-strict): missing from 'files' directory (1) RSTATE ERR: directory name not a valid package: ignored ${BASEDIR}/OPAM/repo/default-strict/packages/no-nv/opam ### OPAMDEBUGSECTIONS="FILE(opam) opam-file RSTATE UPDATE" OPAMDEBUG=-3 opam update default FILE(config) Read ${BASEDIR}/OPAM/config in 0.000s @@ -1165,8 +1201,8 @@ RSTATE Cache found [default] synchronised from file://${BASEDIR}/REPO UPDATE Repository has new changes RSTATE load repo default from diff -FILE(opam) Read ${BASEDIR}/OPAM/repo/default/packages/no-nv/opam in 0.000s -opam-file Mismatching extra-files at ${BASEDIR}/OPAM/repo/default/packages/no-nv: missing from 'files' directory (1) +FILE(opam) Read packages/no-nv/opam (out of ${BASEDIR}/OPAM/repo/default) in 0.000s +opam-file Mismatching extra-files at packages/no-nv (out of ${BASEDIR}/OPAM/repo/default): missing from 'files' directory (1) RSTATE ERR: directory name not a valid package: ignored ${BASEDIR}/OPAM/repo/default/packages/no-nv/opam ### :VI:3:b: Add the last extrafile and update ### sh xfile.sh packages/no-nv @@ -1233,13 +1269,13 @@ RSTATE Cache found [new-default-strict] Initialised UPDATE Repository has new changes RSTATE load repo new-default-strict from dir -FILE(opam) Read ${BASEDIR}/OPAM/repo/new-default-strict/packages/direct-root.1/opam in 0.000s -FILE(opam) Read ${BASEDIR}/OPAM/repo/new-default-strict/packages/good/good.1/opam in 0.000s -FILE(opam) Read ${BASEDIR}/OPAM/repo/new-default-strict/packages/i/n/e/r/very-inner-n-nv/very-inner-n-nv.1/opam in 0.000s -FILE(opam) Read ${BASEDIR}/OPAM/repo/new-default-strict/packages/no-nv/opam in 0.000s +FILE(opam) Read packages/direct-root.1/opam (out of ${BASEDIR}/OPAM/repo/new-default-strict) in 0.000s +FILE(opam) Read packages/good/good.1/opam (out of ${BASEDIR}/OPAM/repo/new-default-strict) in 0.000s +FILE(opam) Read packages/i/n/e/r/very-inner-n-nv/very-inner-n-nv.1/opam (out of ${BASEDIR}/OPAM/repo/new-default-strict) in 0.000s +FILE(opam) Read packages/no-nv/opam (out of ${BASEDIR}/OPAM/repo/new-default-strict) in 0.000s RSTATE ERR: directory name not a valid package: ignored ${BASEDIR}/OPAM/repo/new-default-strict/packages/no-nv/opam -FILE(opam) Read ${BASEDIR}/OPAM/repo/new-default-strict/packages/not/no-n-nv.1/opam in 0.000s -FILE(opam) Read ${BASEDIR}/OPAM/repo/new-default-strict/packages/v/e/r/y/very-inner-nv.1/opam in 0.000s +FILE(opam) Read packages/not/no-n-nv.1/opam (out of ${BASEDIR}/OPAM/repo/new-default-strict) in 0.000s +FILE(opam) Read packages/v/e/r/y/very-inner-nv.1/opam (out of ${BASEDIR}/OPAM/repo/new-default-strict) in 0.000s ### OPAMDEBUGSECTIONS="FILE(opam) opam-file RSTATE UPDATE" OPAMDEBUG=-3 opam repository add new-default ./REPO --this-switch FILE(config) Read ${BASEDIR}/OPAM/config in 0.000s RSTATE LOAD-REPOSITORY-STATE @ ${BASEDIR}/OPAM @@ -1247,13 +1283,19 @@ RSTATE Cache found [new-default] Initialised UPDATE Repository has new changes RSTATE load repo new-default from dir -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/good/good.1/opam in 0.000s -FILE(opam) Read ${BASEDIR}/OPAM/repo/new-default/packages/i/n/e/r/very-inner-n-nv/very-inner-n-nv.1/opam in 0.000s -FILE(opam) Read ${BASEDIR}/OPAM/repo/new-default/packages/no-nv/opam in 0.000s +FILE(opam) Read packages/direct-root.1/opam (out of ${BASEDIR}/OPAM/repo/new-default) in 0.000s +FILE(opam) Read packages/good/good.1/opam (out of ${BASEDIR}/OPAM/repo/new-default) in 0.000s +FILE(opam) Read packages/i/n/e/r/very-inner-n-nv/very-inner-n-nv.1/opam (out of ${BASEDIR}/OPAM/repo/new-default) in 0.000s +FILE(opam) Read packages/no-nv/opam (out of ${BASEDIR}/OPAM/repo/new-default) in 0.000s RSTATE ERR: directory name not a valid package: ignored ${BASEDIR}/OPAM/repo/new-default/packages/no-nv/opam -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/v/e/r/y/very-inner-nv.1/opam in 0.000s +FILE(opam) Read packages/not/no-n-nv.1/opam (out of ${BASEDIR}/OPAM/repo/new-default) in 0.000s +FILE(opam) Read packages/v/e/r/y/very-inner-nv.1/opam (out of ${BASEDIR}/OPAM/repo/new-default) in 0.000s +### OPAMDEBUGSECTIONS="FILE(opam) opam-file RSTATE UPDATE" OPAMDEBUG=-3 opam repository add new-default ./REPO --this-switch | unordered +[new-default] no changes from file://${BASEDIR}/REPO +UPDATE Repository did not change: nothing to do. +FILE(config) Read ${BASEDIR}/OPAM/config in 0.000s +RSTATE LOAD-REPOSITORY-STATE @ ${BASEDIR}/OPAM +RSTATE Cache found ### :VII:1:b: List available package ### opam switch create root-no-nv-sw-from-scratch --empty --repo=new-default,new-default-strict ### opam repository --this-switch @@ -1286,7 +1328,7 @@ RSTATE Cache found [default-strict] synchronised from file://${BASEDIR}/REPO UPDATE Repository has new changes RSTATE load repo default-strict from diff -FILE(opam) Read ${BASEDIR}/OPAM/repo/default-strict/root-no-nv/opam in 0.000s +FILE(opam) Read root-no-nv/opam (out of ${BASEDIR}/OPAM/repo/default-strict) in 0.000s RSTATE ERR: directory name not a valid package: ignored ${BASEDIR}/OPAM/repo/default-strict/root-no-nv/opam RSTATE ERR: Could not load ${BASEDIR}/OPAM/repo/default-strict/root-no-nv/files/un/der/opam, ignored ### OPAMDEBUGSECTIONS="FILE(opam) opam-file RSTATE UPDATE" OPAMDEBUG=-3 opam update default @@ -1298,7 +1340,7 @@ RSTATE Cache found [default] synchronised from file://${BASEDIR}/REPO UPDATE Repository has new changes RSTATE load repo default from diff -FILE(opam) Read ${BASEDIR}/OPAM/repo/default/root-no-nv/opam in 0.000s +FILE(opam) Read root-no-nv/opam (out of ${BASEDIR}/OPAM/repo/default) in 0.000s RSTATE ERR: directory name not a valid package: ignored ${BASEDIR}/OPAM/repo/default/root-no-nv/opam RSTATE ERR: Could not load ${BASEDIR}/OPAM/repo/default/root-no-nv/files/un/der/opam, ignored ### :VII:2:b List available package @@ -1332,8 +1374,8 @@ RSTATE Cache found [default-strict] synchronised from file://${BASEDIR}/REPO UPDATE Repository has new changes RSTATE load repo default-strict from diff -FILE(opam) Read ${BASEDIR}/OPAM/repo/default-strict/root-no-nv/opam in 0.000s -opam-file Mismatching extra-files at ${BASEDIR}/OPAM/repo/default-strict/root-no-nv: missing from 'files' directory (1) +FILE(opam) Read root-no-nv/opam (out of ${BASEDIR}/OPAM/repo/default-strict) in 0.000s +opam-file Mismatching extra-files at root-no-nv (out of ${BASEDIR}/OPAM/repo/default-strict): missing from 'files' directory (1) RSTATE ERR: directory name not a valid package: ignored ${BASEDIR}/OPAM/repo/default-strict/root-no-nv/opam ### OPAMDEBUGSECTIONS="FILE(opam) opam-file RSTATE UPDATE" OPAMDEBUG=-3 opam update default FILE(config) Read ${BASEDIR}/OPAM/config in 0.000s @@ -1344,8 +1386,8 @@ RSTATE Cache found [default] synchronised from file://${BASEDIR}/REPO UPDATE Repository has new changes RSTATE load repo default from diff -FILE(opam) Read ${BASEDIR}/OPAM/repo/default/root-no-nv/opam in 0.000s -opam-file Mismatching extra-files at ${BASEDIR}/OPAM/repo/default/root-no-nv: missing from 'files' directory (1) +FILE(opam) Read root-no-nv/opam (out of ${BASEDIR}/OPAM/repo/default) in 0.000s +opam-file Mismatching extra-files at root-no-nv (out of ${BASEDIR}/OPAM/repo/default): missing from 'files' directory (1) RSTATE ERR: directory name not a valid package: ignored ${BASEDIR}/OPAM/repo/default/root-no-nv/opam ### :VII:3:b: Add the last extrafile and update ### sh xfile.sh root-no-nv @@ -1412,13 +1454,13 @@ RSTATE Cache found [new-default-strict] Initialised UPDATE Repository has new changes RSTATE load repo new-default-strict from dir -FILE(opam) Read ${BASEDIR}/OPAM/repo/new-default-strict/packages/direct-root.1/opam in 0.000s -FILE(opam) Read ${BASEDIR}/OPAM/repo/new-default-strict/packages/good/good.1/opam in 0.000s -FILE(opam) Read ${BASEDIR}/OPAM/repo/new-default-strict/packages/i/n/e/r/very-inner-n-nv/very-inner-n-nv.1/opam in 0.000s -FILE(opam) Read ${BASEDIR}/OPAM/repo/new-default-strict/packages/no-nv/opam in 0.000s +FILE(opam) Read packages/direct-root.1/opam (out of ${BASEDIR}/OPAM/repo/new-default-strict) in 0.000s +FILE(opam) Read packages/good/good.1/opam (out of ${BASEDIR}/OPAM/repo/new-default-strict) in 0.000s +FILE(opam) Read packages/i/n/e/r/very-inner-n-nv/very-inner-n-nv.1/opam (out of ${BASEDIR}/OPAM/repo/new-default-strict) in 0.000s +FILE(opam) Read packages/no-nv/opam (out of ${BASEDIR}/OPAM/repo/new-default-strict) in 0.000s RSTATE ERR: directory name not a valid package: ignored ${BASEDIR}/OPAM/repo/new-default-strict/packages/no-nv/opam -FILE(opam) Read ${BASEDIR}/OPAM/repo/new-default-strict/packages/not/no-n-nv.1/opam in 0.000s -[ERROR] In ${BASEDIR}/OPAM/repo/new-default-strict/packages/not-same-nv-in/not-same-nv-in.2/opam: +FILE(opam) Read packages/not/no-n-nv.1/opam (out of ${BASEDIR}/OPAM/repo/new-default-strict) in 0.000s +[ERROR] In 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) @@ -1431,14 +1473,14 @@ RSTATE Cache found [new-default] Initialised UPDATE Repository has new changes RSTATE load repo new-default from dir -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/good/good.1/opam in 0.000s -FILE(opam) Read ${BASEDIR}/OPAM/repo/new-default/packages/i/n/e/r/very-inner-n-nv/very-inner-n-nv.1/opam in 0.000s -FILE(opam) Read ${BASEDIR}/OPAM/repo/new-default/packages/no-nv/opam in 0.000s +FILE(opam) Read packages/direct-root.1/opam (out of ${BASEDIR}/OPAM/repo/new-default) in 0.000s +FILE(opam) Read packages/good/good.1/opam (out of ${BASEDIR}/OPAM/repo/new-default) in 0.000s +FILE(opam) Read packages/i/n/e/r/very-inner-n-nv/very-inner-n-nv.1/opam (out of ${BASEDIR}/OPAM/repo/new-default) in 0.000s +FILE(opam) Read packages/no-nv/opam (out of ${BASEDIR}/OPAM/repo/new-default) in 0.000s RSTATE ERR: directory name not a valid package: ignored ${BASEDIR}/OPAM/repo/new-default/packages/no-nv/opam -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/not-same-nv-in/not-same-nv-in.2/opam in 0.000s -FILE(opam) Read ${BASEDIR}/OPAM/repo/new-default/packages/v/e/r/y/very-inner-nv.1/opam in 0.000s +FILE(opam) Read packages/not/no-n-nv.1/opam (out of ${BASEDIR}/OPAM/repo/new-default) in 0.000s +FILE(opam) Read packages/not-same-nv-in/not-same-nv-in.2/opam (out of ${BASEDIR}/OPAM/repo/new-default) in 0.000s +FILE(opam) Read packages/v/e/r/y/very-inner-nv.1/opam (out of ${BASEDIR}/OPAM/repo/new-default) in 0.000s ### :VIII:1:b: List available package ### opam switch create not-same-nv-in-sw-from-scratch --empty --repo=new-default,new-default-strict ### opam repository --this-switch @@ -1477,7 +1519,7 @@ RSTATE Cache found [default-strict] synchronised from file://${BASEDIR}/REPO UPDATE Repository has new changes RSTATE load repo default-strict from diff -[ERROR] In ${BASEDIR}/OPAM/repo/default-strict/packages/not-same-nv-in/not-same-nv-in.2/opam: +[ERROR] In 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) @@ -1491,7 +1533,7 @@ RSTATE Cache found [default] synchronised from file://${BASEDIR}/REPO UPDATE Repository has new changes RSTATE load repo default from diff -FILE(opam) Read ${BASEDIR}/OPAM/repo/default/packages/not-same-nv-in/not-same-nv-in.2/opam in 0.000s +FILE(opam) Read packages/not-same-nv-in/not-same-nv-in.2/opam (out of ${BASEDIR}/OPAM/repo/default) in 0.000s RSTATE ERR: Could not load ${BASEDIR}/OPAM/repo/default/packages/not-same-nv-in/not-same-nv-in.2/files/un/der/opam, ignored Now run 'opam upgrade' to apply any package updates. ### :VIII:2:b List available package @@ -1530,7 +1572,7 @@ RSTATE Cache found [default-strict] synchronised from file://${BASEDIR}/REPO UPDATE Repository has new changes RSTATE load repo default-strict from diff -[ERROR] In ${BASEDIR}/OPAM/repo/default-strict/packages/not-same-nv-in/not-same-nv-in.2/opam: +[ERROR] In 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) @@ -1544,8 +1586,8 @@ RSTATE Cache found [default] synchronised from file://${BASEDIR}/REPO UPDATE Repository has new changes RSTATE load repo default from diff -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 packages/not-same-nv-in/not-same-nv-in.2/opam (out of ${BASEDIR}/OPAM/repo/default) in 0.000s +opam-file Mismatching extra-files at packages/not-same-nv-in/not-same-nv-in.2 (out of ${BASEDIR}/OPAM/repo/default): missing from 'files' directory (1) Now run 'opam upgrade' to apply any package updates. ### :VIII:3:b: Add the last extrafile and update ### sh xfile.sh packages/not-same-nv-in/not-same-nv-in.2 @@ -1628,14 +1670,14 @@ RSTATE Cache found [new-default-strict] Initialised UPDATE Repository has new changes RSTATE load repo new-default-strict from dir -FILE(opam) Read ${BASEDIR}/OPAM/repo/new-default-strict/packages/direct-root.1/opam in 0.000s -FILE(opam) Read ${BASEDIR}/OPAM/repo/new-default-strict/packages/good/good.1/opam in 0.000s -FILE(opam) Read ${BASEDIR}/OPAM/repo/new-default-strict/packages/i/n/e/r/very-inner-n-nv/very-inner-n-nv.1/opam in 0.000s -FILE(opam) Read ${BASEDIR}/OPAM/repo/new-default-strict/packages/no-nv/opam in 0.000s +FILE(opam) Read packages/direct-root.1/opam (out of ${BASEDIR}/OPAM/repo/new-default-strict) in 0.000s +FILE(opam) Read packages/good/good.1/opam (out of ${BASEDIR}/OPAM/repo/new-default-strict) in 0.000s +FILE(opam) Read packages/i/n/e/r/very-inner-n-nv/very-inner-n-nv.1/opam (out of ${BASEDIR}/OPAM/repo/new-default-strict) in 0.000s +FILE(opam) Read packages/no-nv/opam (out of ${BASEDIR}/OPAM/repo/new-default-strict) in 0.000s RSTATE ERR: directory name not a valid package: ignored ${BASEDIR}/OPAM/repo/new-default-strict/packages/no-nv/opam -FILE(opam) Read ${BASEDIR}/OPAM/repo/new-default-strict/packages/not/no-n-nv.1/opam in 0.000s -FILE(opam) Read ${BASEDIR}/OPAM/repo/new-default-strict/packages/not-same-nv-in/not-same-nv-in.2/opam in 0.000s -FILE(opam) Read ${BASEDIR}/OPAM/repo/new-default-strict/packages/v/e/r/y/very-inner-nv.1/opam in 0.000s +FILE(opam) Read packages/not/no-n-nv.1/opam (out of ${BASEDIR}/OPAM/repo/new-default-strict) in 0.000s +FILE(opam) Read packages/not-same-nv-in/not-same-nv-in.2/opam (out of ${BASEDIR}/OPAM/repo/new-default-strict) in 0.000s +FILE(opam) Read packages/v/e/r/y/very-inner-nv.1/opam (out of ${BASEDIR}/OPAM/repo/new-default-strict) in 0.000s ### OPAMDEBUGSECTIONS="FILE(opam) opam-file RSTATE UPDATE" OPAMDEBUG=-3 opam repository add new-default ./REPO --this-switch FILE(config) Read ${BASEDIR}/OPAM/config in 0.000s RSTATE LOAD-REPOSITORY-STATE @ ${BASEDIR}/OPAM @@ -1643,14 +1685,20 @@ RSTATE Cache found [new-default] Initialised UPDATE Repository has new changes RSTATE load repo new-default from dir -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/good/good.1/opam in 0.000s -FILE(opam) Read ${BASEDIR}/OPAM/repo/new-default/packages/i/n/e/r/very-inner-n-nv/very-inner-n-nv.1/opam in 0.000s -FILE(opam) Read ${BASEDIR}/OPAM/repo/new-default/packages/no-nv/opam in 0.000s +FILE(opam) Read packages/direct-root.1/opam (out of ${BASEDIR}/OPAM/repo/new-default) in 0.000s +FILE(opam) Read packages/good/good.1/opam (out of ${BASEDIR}/OPAM/repo/new-default) in 0.000s +FILE(opam) Read packages/i/n/e/r/very-inner-n-nv/very-inner-n-nv.1/opam (out of ${BASEDIR}/OPAM/repo/new-default) in 0.000s +FILE(opam) Read packages/no-nv/opam (out of ${BASEDIR}/OPAM/repo/new-default) in 0.000s RSTATE ERR: directory name not a valid package: ignored ${BASEDIR}/OPAM/repo/new-default/packages/no-nv/opam -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/not-same-nv-in/not-same-nv-in.2/opam in 0.000s -FILE(opam) Read ${BASEDIR}/OPAM/repo/new-default/packages/v/e/r/y/very-inner-nv.1/opam in 0.000s +FILE(opam) Read packages/not/no-n-nv.1/opam (out of ${BASEDIR}/OPAM/repo/new-default) in 0.000s +FILE(opam) Read packages/not-same-nv-in/not-same-nv-in.2/opam (out of ${BASEDIR}/OPAM/repo/new-default) in 0.000s +FILE(opam) Read packages/v/e/r/y/very-inner-nv.1/opam (out of ${BASEDIR}/OPAM/repo/new-default) in 0.000s +### OPAMDEBUGSECTIONS="FILE(opam) opam-file RSTATE UPDATE" OPAMDEBUG=-3 opam repository add new-default ./REPO --this-switch | unordered +[new-default] no changes from file://${BASEDIR}/REPO +UPDATE Repository did not change: nothing to do. +FILE(config) Read ${BASEDIR}/OPAM/config in 0.000s +RSTATE LOAD-REPOSITORY-STATE @ ${BASEDIR}/OPAM +RSTATE Cache found ### :IX:1:b: List available package ### opam switch create not-opam-filename-sw-from-scratch --empty --repo=new-default,new-default-strict ### opam repository --this-switch @@ -1804,16 +1852,16 @@ RSTATE Cache found [new-default-strict] Initialised UPDATE Repository has new changes RSTATE load repo new-default-strict from dir -FILE(opam) Read ${BASEDIR}/OPAM/repo/new-default-strict/packages/direct-root.1/opam in 0.000s -FILE(opam) Read ${BASEDIR}/OPAM/repo/new-default-strict/packages/good/good.1/opam in 0.000s -FILE(opam) Read ${BASEDIR}/OPAM/repo/new-default-strict/packages/i/n/e/r/very-inner-n-nv/very-inner-n-nv.1/opam in 0.000s -FILE(opam) Read ${BASEDIR}/OPAM/repo/new-default-strict/packages/no-nv/opam in 0.000s +FILE(opam) Read packages/direct-root.1/opam (out of ${BASEDIR}/OPAM/repo/new-default-strict) in 0.000s +FILE(opam) Read packages/good/good.1/opam (out of ${BASEDIR}/OPAM/repo/new-default-strict) in 0.000s +FILE(opam) Read packages/i/n/e/r/very-inner-n-nv/very-inner-n-nv.1/opam (out of ${BASEDIR}/OPAM/repo/new-default-strict) in 0.000s +FILE(opam) Read packages/no-nv/opam (out of ${BASEDIR}/OPAM/repo/new-default-strict) in 0.000s RSTATE ERR: directory name not a valid package: ignored ${BASEDIR}/OPAM/repo/new-default-strict/packages/no-nv/opam -FILE(opam) Read ${BASEDIR}/OPAM/repo/new-default-strict/packages/not/no-n-nv.1/opam in 0.000s -FILE(opam) Read ${BASEDIR}/OPAM/repo/new-default-strict/packages/not-same-nv-in/not-same-nv-in.2/opam in 0.000s -FILE(opam) Read ${BASEDIR}/OPAM/repo/new-default-strict/packages/opam-dir-nv/opam-dir-nv.1/opam/opam in 0.000s +FILE(opam) Read packages/not/no-n-nv.1/opam (out of ${BASEDIR}/OPAM/repo/new-default-strict) in 0.000s +FILE(opam) Read packages/not-same-nv-in/not-same-nv-in.2/opam (out of ${BASEDIR}/OPAM/repo/new-default-strict) in 0.000s +FILE(opam) Read packages/opam-dir-nv/opam-dir-nv.1/opam/opam (out of ${BASEDIR}/OPAM/repo/new-default-strict) in 0.000s RSTATE ERR: directory name not a valid package: ignored ${BASEDIR}/OPAM/repo/new-default-strict/packages/opam-dir-nv/opam-dir-nv.1/opam/opam -FILE(opam) Read ${BASEDIR}/OPAM/repo/new-default-strict/packages/v/e/r/y/very-inner-nv.1/opam in 0.000s +FILE(opam) Read packages/v/e/r/y/very-inner-nv.1/opam (out of ${BASEDIR}/OPAM/repo/new-default-strict) in 0.000s ### OPAMDEBUGSECTIONS="FILE(opam) opam-file RSTATE UPDATE" OPAMDEBUG=-3 opam repository add new-default ./REPO --this-switch FILE(config) Read ${BASEDIR}/OPAM/config in 0.000s RSTATE LOAD-REPOSITORY-STATE @ ${BASEDIR}/OPAM @@ -1821,16 +1869,22 @@ RSTATE Cache found [new-default] Initialised UPDATE Repository has new changes RSTATE load repo new-default from dir -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/good/good.1/opam in 0.000s -FILE(opam) Read ${BASEDIR}/OPAM/repo/new-default/packages/i/n/e/r/very-inner-n-nv/very-inner-n-nv.1/opam in 0.000s -FILE(opam) Read ${BASEDIR}/OPAM/repo/new-default/packages/no-nv/opam in 0.000s +FILE(opam) Read packages/direct-root.1/opam (out of ${BASEDIR}/OPAM/repo/new-default) in 0.000s +FILE(opam) Read packages/good/good.1/opam (out of ${BASEDIR}/OPAM/repo/new-default) in 0.000s +FILE(opam) Read packages/i/n/e/r/very-inner-n-nv/very-inner-n-nv.1/opam (out of ${BASEDIR}/OPAM/repo/new-default) in 0.000s +FILE(opam) Read packages/no-nv/opam (out of ${BASEDIR}/OPAM/repo/new-default) in 0.000s RSTATE ERR: directory name not a valid package: ignored ${BASEDIR}/OPAM/repo/new-default/packages/no-nv/opam -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/not-same-nv-in/not-same-nv-in.2/opam in 0.000s -FILE(opam) Read ${BASEDIR}/OPAM/repo/new-default/packages/opam-dir-nv/opam-dir-nv.1/opam/opam in 0.000s +FILE(opam) Read packages/not/no-n-nv.1/opam (out of ${BASEDIR}/OPAM/repo/new-default) in 0.000s +FILE(opam) Read packages/not-same-nv-in/not-same-nv-in.2/opam (out of ${BASEDIR}/OPAM/repo/new-default) in 0.000s +FILE(opam) Read packages/opam-dir-nv/opam-dir-nv.1/opam/opam (out of ${BASEDIR}/OPAM/repo/new-default) in 0.000s RSTATE ERR: directory name not a valid package: ignored ${BASEDIR}/OPAM/repo/new-default/packages/opam-dir-nv/opam-dir-nv.1/opam/opam -FILE(opam) Read ${BASEDIR}/OPAM/repo/new-default/packages/v/e/r/y/very-inner-nv.1/opam in 0.000s +FILE(opam) Read packages/v/e/r/y/very-inner-nv.1/opam (out of ${BASEDIR}/OPAM/repo/new-default) in 0.000s +### OPAMDEBUGSECTIONS="FILE(opam) opam-file RSTATE UPDATE" OPAMDEBUG=-3 opam repository add new-default ./REPO --this-switch | unordered +[new-default] no changes from file://${BASEDIR}/REPO +UPDATE Repository did not change: nothing to do. +FILE(config) Read ${BASEDIR}/OPAM/config in 0.000s +RSTATE LOAD-REPOSITORY-STATE @ ${BASEDIR}/OPAM +RSTATE Cache found ### :X:1:b: List available package ### opam switch create opam-dir-nv-sw-from-scratch --empty --repo=new-default,new-default-strict ### opam repository --this-switch @@ -1864,7 +1918,7 @@ RSTATE Cache found [default-strict] synchronised from file://${BASEDIR}/REPO UPDATE Repository has new changes RSTATE load repo default-strict from diff -FILE(opam) Read ${BASEDIR}/OPAM/repo/default-strict/packages/opam-dir-nv/opam-dir-nv.1/opam/opam in 0.000s +FILE(opam) Read packages/opam-dir-nv/opam-dir-nv.1/opam/opam (out of ${BASEDIR}/OPAM/repo/default-strict) in 0.000s RSTATE ERR: directory name not a valid package: ignored ${BASEDIR}/OPAM/repo/default-strict/packages/opam-dir-nv/opam-dir-nv.1/opam/opam RSTATE ERR: Could not load ${BASEDIR}/OPAM/repo/default-strict/packages/opam-dir-nv/opam-dir-nv.1/opam/files/un/der/opam, ignored ### OPAMDEBUGSECTIONS="FILE(opam) opam-file RSTATE UPDATE" OPAMDEBUG=-3 opam update default @@ -1876,7 +1930,7 @@ RSTATE Cache found [default] synchronised from file://${BASEDIR}/REPO UPDATE Repository has new changes RSTATE load repo default from diff -FILE(opam) Read ${BASEDIR}/OPAM/repo/default/packages/opam-dir-nv/opam-dir-nv.1/opam/opam in 0.000s +FILE(opam) Read packages/opam-dir-nv/opam-dir-nv.1/opam/opam (out of ${BASEDIR}/OPAM/repo/default) in 0.000s RSTATE ERR: directory name not a valid package: ignored ${BASEDIR}/OPAM/repo/default/packages/opam-dir-nv/opam-dir-nv.1/opam/opam RSTATE ERR: Could not load ${BASEDIR}/OPAM/repo/default/packages/opam-dir-nv/opam-dir-nv.1/opam/files/un/der/opam, ignored ### :X:2:b List available package @@ -1909,8 +1963,8 @@ RSTATE Cache found [default-strict] synchronised from file://${BASEDIR}/REPO UPDATE Repository has new changes RSTATE load repo default-strict from diff -FILE(opam) Read ${BASEDIR}/OPAM/repo/default-strict/packages/opam-dir-nv/opam-dir-nv.1/opam/opam in 0.000s -opam-file Mismatching extra-files at ${BASEDIR}/OPAM/repo/default-strict/packages/opam-dir-nv/opam-dir-nv.1/opam: missing from 'files' directory (1) +FILE(opam) Read packages/opam-dir-nv/opam-dir-nv.1/opam/opam (out of ${BASEDIR}/OPAM/repo/default-strict) in 0.000s +opam-file Mismatching extra-files at packages/opam-dir-nv/opam-dir-nv.1/opam (out of ${BASEDIR}/OPAM/repo/default-strict): missing from 'files' directory (1) RSTATE ERR: directory name not a valid package: ignored ${BASEDIR}/OPAM/repo/default-strict/packages/opam-dir-nv/opam-dir-nv.1/opam/opam ### OPAMDEBUGSECTIONS="FILE(opam) opam-file RSTATE UPDATE" OPAMDEBUG=-3 opam update default FILE(config) Read ${BASEDIR}/OPAM/config in 0.000s @@ -1921,8 +1975,8 @@ RSTATE Cache found [default] synchronised from file://${BASEDIR}/REPO UPDATE Repository has new changes RSTATE load repo default from diff -FILE(opam) Read ${BASEDIR}/OPAM/repo/default/packages/opam-dir-nv/opam-dir-nv.1/opam/opam in 0.000s -opam-file Mismatching extra-files at ${BASEDIR}/OPAM/repo/default/packages/opam-dir-nv/opam-dir-nv.1/opam: missing from 'files' directory (1) +FILE(opam) Read packages/opam-dir-nv/opam-dir-nv.1/opam/opam (out of ${BASEDIR}/OPAM/repo/default) in 0.000s +opam-file Mismatching extra-files at packages/opam-dir-nv/opam-dir-nv.1/opam (out of ${BASEDIR}/OPAM/repo/default): missing from 'files' directory (1) RSTATE ERR: directory name not a valid package: ignored ${BASEDIR}/OPAM/repo/default/packages/opam-dir-nv/opam-dir-nv.1/opam/opam ### :X:3:b: Add the last extrafile and update ### sh xfile.sh packages/opam-dir-nv/opam-dir-nv.1/opam @@ -1989,18 +2043,18 @@ RSTATE Cache found [new-default-strict] Initialised UPDATE Repository has new changes RSTATE load repo new-default-strict from dir -FILE(opam) Read ${BASEDIR}/OPAM/repo/new-default-strict/packages/direct-root.1/opam in 0.000s -FILE(opam) Read ${BASEDIR}/OPAM/repo/new-default-strict/packages/good/good.1/opam in 0.000s -FILE(opam) Read ${BASEDIR}/OPAM/repo/new-default-strict/packages/i/n/e/r/very-inner-n-nv/very-inner-n-nv.1/opam in 0.000s -FILE(opam) Read ${BASEDIR}/OPAM/repo/new-default-strict/packages/no-nv/opam in 0.000s +FILE(opam) Read packages/direct-root.1/opam (out of ${BASEDIR}/OPAM/repo/new-default-strict) in 0.000s +FILE(opam) Read packages/good/good.1/opam (out of ${BASEDIR}/OPAM/repo/new-default-strict) in 0.000s +FILE(opam) Read packages/i/n/e/r/very-inner-n-nv/very-inner-n-nv.1/opam (out of ${BASEDIR}/OPAM/repo/new-default-strict) in 0.000s +FILE(opam) Read packages/no-nv/opam (out of ${BASEDIR}/OPAM/repo/new-default-strict) in 0.000s RSTATE ERR: directory name not a valid package: ignored ${BASEDIR}/OPAM/repo/new-default-strict/packages/no-nv/opam -FILE(opam) Read ${BASEDIR}/OPAM/repo/new-default-strict/packages/not/no-n-nv.1/opam in 0.000s -FILE(opam) Read ${BASEDIR}/OPAM/repo/new-default-strict/packages/not-same-nv-in/not-same-nv-in.2/opam in 0.000s -FILE(opam) Read ${BASEDIR}/OPAM/repo/new-default-strict/packages/opam-dir-n/opam/opam in 0.000s +FILE(opam) Read packages/not/no-n-nv.1/opam (out of ${BASEDIR}/OPAM/repo/new-default-strict) in 0.000s +FILE(opam) Read packages/not-same-nv-in/not-same-nv-in.2/opam (out of ${BASEDIR}/OPAM/repo/new-default-strict) in 0.000s +FILE(opam) Read packages/opam-dir-n/opam/opam (out of ${BASEDIR}/OPAM/repo/new-default-strict) in 0.000s RSTATE ERR: directory name not a valid package: ignored ${BASEDIR}/OPAM/repo/new-default-strict/packages/opam-dir-n/opam/opam -FILE(opam) Read ${BASEDIR}/OPAM/repo/new-default-strict/packages/opam-dir-nv/opam-dir-nv.1/opam/opam in 0.000s +FILE(opam) Read packages/opam-dir-nv/opam-dir-nv.1/opam/opam (out of ${BASEDIR}/OPAM/repo/new-default-strict) in 0.000s RSTATE ERR: directory name not a valid package: ignored ${BASEDIR}/OPAM/repo/new-default-strict/packages/opam-dir-nv/opam-dir-nv.1/opam/opam -FILE(opam) Read ${BASEDIR}/OPAM/repo/new-default-strict/packages/v/e/r/y/very-inner-nv.1/opam in 0.000s +FILE(opam) Read packages/v/e/r/y/very-inner-nv.1/opam (out of ${BASEDIR}/OPAM/repo/new-default-strict) in 0.000s ### OPAMDEBUGSECTIONS="FILE(opam) opam-file RSTATE UPDATE" OPAMDEBUG=-3 opam repository add new-default ./REPO --this-switch FILE(config) Read ${BASEDIR}/OPAM/config in 0.000s RSTATE LOAD-REPOSITORY-STATE @ ${BASEDIR}/OPAM @@ -2008,18 +2062,24 @@ RSTATE Cache found [new-default] Initialised UPDATE Repository has new changes RSTATE load repo new-default from dir -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/good/good.1/opam in 0.000s -FILE(opam) Read ${BASEDIR}/OPAM/repo/new-default/packages/i/n/e/r/very-inner-n-nv/very-inner-n-nv.1/opam in 0.000s -FILE(opam) Read ${BASEDIR}/OPAM/repo/new-default/packages/no-nv/opam in 0.000s +FILE(opam) Read packages/direct-root.1/opam (out of ${BASEDIR}/OPAM/repo/new-default) in 0.000s +FILE(opam) Read packages/good/good.1/opam (out of ${BASEDIR}/OPAM/repo/new-default) in 0.000s +FILE(opam) Read packages/i/n/e/r/very-inner-n-nv/very-inner-n-nv.1/opam (out of ${BASEDIR}/OPAM/repo/new-default) in 0.000s +FILE(opam) Read packages/no-nv/opam (out of ${BASEDIR}/OPAM/repo/new-default) in 0.000s RSTATE ERR: directory name not a valid package: ignored ${BASEDIR}/OPAM/repo/new-default/packages/no-nv/opam -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/not-same-nv-in/not-same-nv-in.2/opam in 0.000s -FILE(opam) Read ${BASEDIR}/OPAM/repo/new-default/packages/opam-dir-n/opam/opam in 0.000s +FILE(opam) Read packages/not/no-n-nv.1/opam (out of ${BASEDIR}/OPAM/repo/new-default) in 0.000s +FILE(opam) Read packages/not-same-nv-in/not-same-nv-in.2/opam (out of ${BASEDIR}/OPAM/repo/new-default) in 0.000s +FILE(opam) Read packages/opam-dir-n/opam/opam (out of ${BASEDIR}/OPAM/repo/new-default) in 0.000s RSTATE ERR: directory name not a valid package: ignored ${BASEDIR}/OPAM/repo/new-default/packages/opam-dir-n/opam/opam -FILE(opam) Read ${BASEDIR}/OPAM/repo/new-default/packages/opam-dir-nv/opam-dir-nv.1/opam/opam in 0.000s +FILE(opam) Read packages/opam-dir-nv/opam-dir-nv.1/opam/opam (out of ${BASEDIR}/OPAM/repo/new-default) in 0.000s RSTATE ERR: directory name not a valid package: ignored ${BASEDIR}/OPAM/repo/new-default/packages/opam-dir-nv/opam-dir-nv.1/opam/opam -FILE(opam) Read ${BASEDIR}/OPAM/repo/new-default/packages/v/e/r/y/very-inner-nv.1/opam in 0.000s +FILE(opam) Read packages/v/e/r/y/very-inner-nv.1/opam (out of ${BASEDIR}/OPAM/repo/new-default) in 0.000s +### OPAMDEBUGSECTIONS="FILE(opam) opam-file RSTATE UPDATE" OPAMDEBUG=-3 opam repository add new-default ./REPO --this-switch | unordered +[new-default] no changes from file://${BASEDIR}/REPO +UPDATE Repository did not change: nothing to do. +FILE(config) Read ${BASEDIR}/OPAM/config in 0.000s +RSTATE LOAD-REPOSITORY-STATE @ ${BASEDIR}/OPAM +RSTATE Cache found ### :XI:1:b: List available package ### opam switch create opam-dir-n-sw-from-scratch --empty --repo=new-default,new-default-strict ### opam repository --this-switch @@ -2053,7 +2113,7 @@ RSTATE Cache found [default-strict] synchronised from file://${BASEDIR}/REPO UPDATE Repository has new changes RSTATE load repo default-strict from diff -FILE(opam) Read ${BASEDIR}/OPAM/repo/default-strict/packages/opam-dir-n/opam/opam in 0.000s +FILE(opam) Read packages/opam-dir-n/opam/opam (out of ${BASEDIR}/OPAM/repo/default-strict) in 0.000s RSTATE ERR: directory name not a valid package: ignored ${BASEDIR}/OPAM/repo/default-strict/packages/opam-dir-n/opam/opam RSTATE ERR: Could not load ${BASEDIR}/OPAM/repo/default-strict/packages/opam-dir-n/opam/files/un/der/opam, ignored ### OPAMDEBUGSECTIONS="FILE(opam) opam-file RSTATE UPDATE" OPAMDEBUG=-3 opam update default @@ -2065,7 +2125,7 @@ RSTATE Cache found [default] synchronised from file://${BASEDIR}/REPO UPDATE Repository has new changes RSTATE load repo default from diff -FILE(opam) Read ${BASEDIR}/OPAM/repo/default/packages/opam-dir-n/opam/opam in 0.000s +FILE(opam) Read packages/opam-dir-n/opam/opam (out of ${BASEDIR}/OPAM/repo/default) in 0.000s RSTATE ERR: directory name not a valid package: ignored ${BASEDIR}/OPAM/repo/default/packages/opam-dir-n/opam/opam RSTATE ERR: Could not load ${BASEDIR}/OPAM/repo/default/packages/opam-dir-n/opam/files/un/der/opam, ignored ### :XI:2:b List available package @@ -2098,8 +2158,8 @@ RSTATE Cache found [default-strict] synchronised from file://${BASEDIR}/REPO UPDATE Repository has new changes RSTATE load repo default-strict from diff -FILE(opam) Read ${BASEDIR}/OPAM/repo/default-strict/packages/opam-dir-n/opam/opam in 0.000s -opam-file Mismatching extra-files at ${BASEDIR}/OPAM/repo/default-strict/packages/opam-dir-n/opam: missing from 'files' directory (1) +FILE(opam) Read packages/opam-dir-n/opam/opam (out of ${BASEDIR}/OPAM/repo/default-strict) in 0.000s +opam-file Mismatching extra-files at packages/opam-dir-n/opam (out of ${BASEDIR}/OPAM/repo/default-strict): missing from 'files' directory (1) RSTATE ERR: directory name not a valid package: ignored ${BASEDIR}/OPAM/repo/default-strict/packages/opam-dir-n/opam/opam ### OPAMDEBUGSECTIONS="FILE(opam) opam-file RSTATE UPDATE" OPAMDEBUG=-3 opam update default FILE(config) Read ${BASEDIR}/OPAM/config in 0.000s @@ -2110,8 +2170,8 @@ RSTATE Cache found [default] synchronised from file://${BASEDIR}/REPO UPDATE Repository has new changes RSTATE load repo default from diff -FILE(opam) Read ${BASEDIR}/OPAM/repo/default/packages/opam-dir-n/opam/opam in 0.000s -opam-file Mismatching extra-files at ${BASEDIR}/OPAM/repo/default/packages/opam-dir-n/opam: missing from 'files' directory (1) +FILE(opam) Read packages/opam-dir-n/opam/opam (out of ${BASEDIR}/OPAM/repo/default) in 0.000s +opam-file Mismatching extra-files at packages/opam-dir-n/opam (out of ${BASEDIR}/OPAM/repo/default): missing from 'files' directory (1) RSTATE ERR: directory name not a valid package: ignored ${BASEDIR}/OPAM/repo/default/packages/opam-dir-n/opam/opam ### :XI:3:b: Add the last extrafile and update ### sh xfile.sh packages/opam-dir-n/opam @@ -2179,7 +2239,7 @@ RSTATE Cache found [new-default-strict] Initialised UPDATE Repository has new changes RSTATE load repo new-default-strict from dir -FILE(opam) Read ${BASEDIR}/OPAM/repo/new-default-strict/packages/opam in 0.000s +FILE(opam) Read packages/opam (out of ${BASEDIR}/OPAM/repo/new-default-strict) in 0.000s RSTATE ERR: directory name not a valid package: ignored ${BASEDIR}/OPAM/repo/new-default-strict/packages/opam ### OPAMDEBUGSECTIONS="FILE(opam) opam-file RSTATE UPDATE" OPAMDEBUG=-3 opam repository add new-default ./REPO --this-switch FILE(config) Read ${BASEDIR}/OPAM/config in 0.000s @@ -2188,7 +2248,7 @@ RSTATE Cache found [new-default] Initialised UPDATE Repository has new changes RSTATE load repo new-default from dir -FILE(opam) Read ${BASEDIR}/OPAM/repo/new-default/packages/opam in 0.000s +FILE(opam) Read packages/opam (out of ${BASEDIR}/OPAM/repo/new-default) in 0.000s RSTATE ERR: directory name not a valid package: ignored ${BASEDIR}/OPAM/repo/new-default/packages/opam ### :XII:1:b: List available package ### opam switch create opam-at-root-pkg-sw-from-scratch --empty --repo=new-default,new-default-strict @@ -2217,7 +2277,7 @@ RSTATE Cache found [default-strict] synchronised from file://${BASEDIR}/REPO UPDATE Repository has new changes RSTATE load repo default-strict from diff -FILE(opam) Read ${BASEDIR}/OPAM/repo/default-strict/packages/opam in 0.000s +FILE(opam) Read packages/opam (out of ${BASEDIR}/OPAM/repo/default-strict) in 0.000s RSTATE ERR: directory name not a valid package: ignored ${BASEDIR}/OPAM/repo/default-strict/packages/opam RSTATE ERR: Could not load ${BASEDIR}/OPAM/repo/default-strict/packages/files/un/der/opam, ignored ### OPAMDEBUGSECTIONS="FILE(opam) opam-file RSTATE UPDATE" OPAMDEBUG=-3 opam update default @@ -2229,7 +2289,7 @@ RSTATE Cache found [default] synchronised from file://${BASEDIR}/REPO UPDATE Repository has new changes RSTATE load repo default from diff -FILE(opam) Read ${BASEDIR}/OPAM/repo/default/packages/opam in 0.000s +FILE(opam) Read packages/opam (out of ${BASEDIR}/OPAM/repo/default) in 0.000s RSTATE ERR: directory name not a valid package: ignored ${BASEDIR}/OPAM/repo/default/packages/opam RSTATE ERR: Could not load ${BASEDIR}/OPAM/repo/default/packages/files/un/der/opam, ignored ### :XII:2:b List available package @@ -2263,8 +2323,8 @@ RSTATE Cache found [default-strict] synchronised from file://${BASEDIR}/REPO UPDATE Repository has new changes RSTATE load repo default-strict from diff -FILE(opam) Read ${BASEDIR}/OPAM/repo/default-strict/packages/opam in 0.000s -opam-file Mismatching extra-files at ${BASEDIR}/OPAM/repo/default-strict/packages: missing from 'files' directory (1) +FILE(opam) Read packages/opam (out of ${BASEDIR}/OPAM/repo/default-strict) in 0.000s +opam-file Mismatching extra-files at packages (out of ${BASEDIR}/OPAM/repo/default-strict): missing from 'files' directory (1) RSTATE ERR: directory name not a valid package: ignored ${BASEDIR}/OPAM/repo/default-strict/packages/opam ### OPAMDEBUGSECTIONS="FILE(opam) opam-file RSTATE UPDATE" OPAMDEBUG=-3 opam update default FILE(config) Read ${BASEDIR}/OPAM/config in 0.000s @@ -2275,8 +2335,8 @@ RSTATE Cache found [default] synchronised from file://${BASEDIR}/REPO UPDATE Repository has new changes RSTATE load repo default from diff -FILE(opam) Read ${BASEDIR}/OPAM/repo/default/packages/opam in 0.000s -opam-file Mismatching extra-files at ${BASEDIR}/OPAM/repo/default/packages: missing from 'files' directory (1) +FILE(opam) Read packages/opam (out of ${BASEDIR}/OPAM/repo/default) in 0.000s +opam-file Mismatching extra-files at packages (out of ${BASEDIR}/OPAM/repo/default): missing from 'files' directory (1) RSTATE ERR: directory name not a valid package: ignored ${BASEDIR}/OPAM/repo/default/packages/opam ### :XII:3:b: Add the last extrafile and update ### sh xfile.sh packages @@ -2343,7 +2403,7 @@ RSTATE Cache found [new-default-strict] Initialised UPDATE Repository has new changes RSTATE load repo new-default-strict from dir -FILE(opam) Read ${BASEDIR}/OPAM/repo/new-default-strict/packages/opam in 0.000s +FILE(opam) Read packages/opam (out of ${BASEDIR}/OPAM/repo/new-default-strict) in 0.000s RSTATE ERR: directory name not a valid package: ignored ${BASEDIR}/OPAM/repo/new-default-strict/packages/opam ### OPAMDEBUGSECTIONS="FILE(opam) opam-file RSTATE UPDATE" OPAMDEBUG=-3 opam repository add new-default ./REPO --this-switch FILE(config) Read ${BASEDIR}/OPAM/config in 0.000s @@ -2352,7 +2412,7 @@ RSTATE Cache found [new-default] Initialised UPDATE Repository has new changes RSTATE load repo new-default from dir -FILE(opam) Read ${BASEDIR}/OPAM/repo/new-default/packages/opam in 0.000s +FILE(opam) Read packages/opam (out of ${BASEDIR}/OPAM/repo/new-default) in 0.000s RSTATE ERR: directory name not a valid package: ignored ${BASEDIR}/OPAM/repo/new-default/packages/opam ### :XIII:1:b: List available package ### opam switch create z-good-sw-from-scratch --empty --repo=new-default,new-default-strict @@ -2381,7 +2441,7 @@ RSTATE Cache found [default-strict] synchronised from file://${BASEDIR}/REPO UPDATE Repository has new changes RSTATE load repo default-strict from diff -FILE(opam) Read ${BASEDIR}/OPAM/repo/default-strict/pkg/z-good/z-good.1/opam in 0.000s +FILE(opam) Read pkg/z-good/z-good.1/opam (out of ${BASEDIR}/OPAM/repo/default-strict) in 0.000s RSTATE ERR: Could not load ${BASEDIR}/OPAM/repo/default-strict/pkg/z-good/z-good.1/files/un/der/opam, ignored Now run 'opam upgrade' to apply any package updates. ### OPAMDEBUGSECTIONS="FILE(opam) opam-file RSTATE UPDATE" OPAMDEBUG=-3 opam update default @@ -2393,7 +2453,7 @@ RSTATE Cache found [default] synchronised from file://${BASEDIR}/REPO UPDATE Repository has new changes RSTATE load repo default from diff -FILE(opam) Read ${BASEDIR}/OPAM/repo/default/pkg/z-good/z-good.1/opam in 0.000s +FILE(opam) Read pkg/z-good/z-good.1/opam (out of ${BASEDIR}/OPAM/repo/default) in 0.000s RSTATE ERR: Could not load ${BASEDIR}/OPAM/repo/default/pkg/z-good/z-good.1/files/un/der/opam, ignored Now run 'opam upgrade' to apply any package updates. ### :XIII:2:b List available package @@ -2431,8 +2491,8 @@ RSTATE Cache found [default-strict] synchronised from file://${BASEDIR}/REPO UPDATE Repository has new changes RSTATE load repo default-strict from diff -FILE(opam) Read ${BASEDIR}/OPAM/repo/default-strict/pkg/z-good/z-good.1/opam in 0.000s -opam-file Mismatching extra-files at ${BASEDIR}/OPAM/repo/default-strict/pkg/z-good/z-good.1: missing from 'files' directory (1) +FILE(opam) Read pkg/z-good/z-good.1/opam (out of ${BASEDIR}/OPAM/repo/default-strict) in 0.000s +opam-file Mismatching extra-files at pkg/z-good/z-good.1 (out of ${BASEDIR}/OPAM/repo/default-strict): missing from 'files' directory (1) Now run 'opam upgrade' to apply any package updates. ### OPAMDEBUGSECTIONS="FILE(opam) opam-file RSTATE UPDATE" OPAMDEBUG=-3 opam update default FILE(config) Read ${BASEDIR}/OPAM/config in 0.000s @@ -2443,8 +2503,8 @@ RSTATE Cache found [default] synchronised from file://${BASEDIR}/REPO UPDATE Repository has new changes RSTATE load repo default from diff -FILE(opam) Read ${BASEDIR}/OPAM/repo/default/pkg/z-good/z-good.1/opam in 0.000s -opam-file Mismatching extra-files at ${BASEDIR}/OPAM/repo/default/pkg/z-good/z-good.1: missing from 'files' directory (1) +FILE(opam) Read pkg/z-good/z-good.1/opam (out of ${BASEDIR}/OPAM/repo/default) in 0.000s +opam-file Mismatching extra-files at pkg/z-good/z-good.1 (out of ${BASEDIR}/OPAM/repo/default): missing from 'files' directory (1) Now run 'opam upgrade' to apply any package updates. ### :XIII:3:b: Add the last extrafile and update ### sh xfile.sh pkg/z-good/z-good.1 @@ -2541,9 +2601,9 @@ RSTATE Cache found [default-strict] synchronised from file://${BASEDIR}/REPO UPDATE Repository has new changes RSTATE load repo default-strict from diff -FILE(opam) Read ${BASEDIR}/OPAM/repo/default-strict/packages/wrong-opamf-updated/wrong-opamf-updated.1/opam in 0.000s -opam-file Mismatching extra-files at ${BASEDIR}/OPAM/repo/default-strict/packages/wrong-opamf-updated/wrong-opamf-updated.1: missing from 'files' directory (1) -FILE(opam) Read ${BASEDIR}/OPAM/repo/default-strict/packages/another-good/another-good.1/opam in 0.000s +FILE(opam) Read packages/wrong-opamf-updated/wrong-opamf-updated.1/opam (out of ${BASEDIR}/OPAM/repo/default-strict) in 0.000s +opam-file Mismatching extra-files at packages/wrong-opamf-updated/wrong-opamf-updated.1 (out of ${BASEDIR}/OPAM/repo/default-strict): missing from 'files' directory (1) +FILE(opam) Read packages/another-good/another-good.1/opam (out of ${BASEDIR}/OPAM/repo/default-strict) in 0.000s Now run 'opam upgrade' to apply any package updates. ### OPAMDEBUGSECTIONS="FILE(opam) opam-file RSTATE UPDATE" OPAMDEBUG=-3 opam update default FILE(config) Read ${BASEDIR}/OPAM/config in 0.000s @@ -2554,9 +2614,9 @@ RSTATE Cache found [default] synchronised from file://${BASEDIR}/REPO UPDATE Repository has new changes RSTATE load repo default from diff -FILE(opam) Read ${BASEDIR}/OPAM/repo/default/packages/wrong-opamf-updated/wrong-opamf-updated.1/opam in 0.000s -opam-file Mismatching extra-files at ${BASEDIR}/OPAM/repo/default/packages/wrong-opamf-updated/wrong-opamf-updated.1: missing from 'files' directory (1) -FILE(opam) Read ${BASEDIR}/OPAM/repo/default/packages/another-good/another-good.1/opam in 0.000s +FILE(opam) Read packages/wrong-opamf-updated/wrong-opamf-updated.1/opam (out of ${BASEDIR}/OPAM/repo/default) in 0.000s +opam-file Mismatching extra-files at packages/wrong-opamf-updated/wrong-opamf-updated.1 (out of ${BASEDIR}/OPAM/repo/default): missing from 'files' directory (1) +FILE(opam) Read packages/another-good/another-good.1/opam (out of ${BASEDIR}/OPAM/repo/default) in 0.000s Now run 'opam upgrade' to apply any package updates. ### :::::::::::::::::::::: ### :CI: opam admin repository reading @@ -2574,7 +2634,7 @@ Now run 'opam upgrade' to apply any package updates. ### OPAMDEBUGSECTIONS="FILE(opam) opam-file RSTATE" OPAMDEBUG=-3 opam admin list FILE(config) Read ${BASEDIR}/OPAM/config in 0.000s RSTATE load repo local from dir -FILE(opam) Read ${BASEDIR}/packages/opam in 0.000s +FILE(opam) Read packages/opam (out of ${BASEDIR}) in 0.000s RSTATE ERR: directory name not a valid package: ignored ${BASEDIR}/packages/opam # Packages matching: available # No matches found diff --git a/tests/reftests/repository.test b/tests/reftests/repository.test index 2f38a4d0ea5..a733e58f1ea 100644 --- a/tests/reftests/repository.test +++ b/tests/reftests/repository.test @@ -37,13 +37,13 @@ some content ### sh hash.sh REPO foo.2 ### OPAMDEBUG=-1 OPAMDEBUGSECTIONS=TAR opam update default | grep TAR TAR creating archive ${BASEDIR}/OPAM/repo/default.tar.gz from ${BASEDIR}/OPAM/repo/default +TAR creating archive ${BASEDIR}/OPAM/repo/default.tar.gz.new from ${BASEDIR}/REPO ### ls $OPAMROOT/repo | grep -v "cache" default.tar.gz lock plain repos-config ### opam install foo.2 -vv | grep '^\+' | sed-cmd test tar -+ tar "xfz" "${BASEDIR}/OPAM/repo/default.tar.gz" "-C" "${OPAMTMP}" + test "-f" "baz" (CWD=${BASEDIR}/OPAM/tarring/.opam-switch/build/foo.2) ### opam repository remove default --all ### : Add tarred repo (tarred) @@ -62,7 +62,6 @@ plain repos-config tarred.tar.gz ### opam install foo.3 -vv | grep '^\+' | sed-cmd test tar -+ tar "xfz" "${BASEDIR}/OPAM/repo/tarred.tar.gz" "-C" "${OPAMTMP}" + test "-f" "baz" (CWD=${BASEDIR}/OPAM/tarring/.opam-switch/build/foo.3) ### opam repository remove plain --all ### : Update tarred repo (tarred) @@ -73,14 +72,12 @@ build: ["test" "-f" "baz"] some content ### sh hash.sh REPO foo.4 ### OPAMDEBUG=-1 OPAMDEBUGSECTIONS=TAR opam update -vv | grep '^(\+|TAR)' | sed-cmd tar -+ tar "xfz" "${BASEDIR}/OPAM/repo/tarred.tar.gz" "-C" "${OPAMTMP}" -TAR creating archive ${BASEDIR}/OPAM/repo/tarred.tar.gz from ${OPAMTMP}/tarred +TAR creating archive ${BASEDIR}/OPAM/repo/tarred.tar.gz.new from ${BASEDIR}/REPO ### opam install foo.4 -vv | grep '^\+' | sed-cmd test tar -+ tar "xfz" "${BASEDIR}/OPAM/repo/tarred.tar.gz" "-C" "${OPAMTMP}" + test "-f" "baz" (CWD=${BASEDIR}/OPAM/tarring/.opam-switch/build/foo.4) ### mkdir tarred-ext -### tar xf OPAM/repo/tarred.tar.gz -### diff -ru ./tarred REPO +### tar xf OPAM/repo/tarred.tar.gz -C tarred-ext +### diff -ru ./tarred-ext REPO ### ls $OPAMROOT/repo | grep -v "cache" lock repos-config @@ -94,7 +91,7 @@ build: ["test" "-f" "quux"] some content ### sh hash.sh REPO foo.5 ### opam update -vv | grep '^\+' | sed-cmd tar -+ tar "xfz" "${BASEDIR}/OPAM/repo/tarred.tar.gz" "-C" "${OPAMTMP}" ++ tar "xfz" "${BASEDIR}/OPAM/repo/tarred.tar.gz" "-C" "${BASEDIR}/OPAM/repo/tarred" ### opam install foo.5 -vv | grep '^\+' | sed-cmd test + test "-f" "quux" (CWD=${BASEDIR}/OPAM/tarring/.opam-switch/build/foo.5) ### ls $OPAMROOT/repo | grep -v "cache" @@ -122,7 +119,7 @@ FILE(opam) Read ${BASEDIR}/OPAM/tarring/.opam-switch/packag <><> Updating package repositories ><><><><><><><><><><><><><><><><><><><><><><> [tarred] synchronised from file://${BASEDIR}/REPO FILE(repo) Read ${BASEDIR}/OPAM/repo/tarred/repo in 0.000s -FILE(opam) Read ${BASEDIR}/OPAM/repo/tarred/packages/foo/foo.4/opam in 0.000s +FILE(opam) Read packages/foo/foo.4/opam (out of ${BASEDIR}/OPAM/repo/tarred) in 0.000s FILE(repos-config) Wrote ${BASEDIR}/OPAM/repo/repos-config atomically in 0.000s CACHE(repository) Writing the repository cache to ${BASEDIR}/OPAM/repo/state-magicv.cache ... CACHE(repository) ${BASEDIR}/OPAM/repo/state-magicv.cache written in 0.000s @@ -203,7 +200,7 @@ CACHE(repository) Loaded ${BASEDIR}/OPAM/repo/state-magicv.cache i <><> Updating package repositories ><><><><><><><><><><><><><><><><><><><><><><> [repo2] synchronised from file://${BASEDIR}/REPO2 FILE(repo) Read ${BASEDIR}/OPAM/repo/repo2/repo in 0.000s -FILE(opam) Read ${BASEDIR}/OPAM/repo/repo2/packages/bar/bar.2/opam in 0.000s +FILE(opam) Read packages/bar/bar.2/opam (out of ${BASEDIR}/OPAM/repo/repo2) in 0.000s [tarred] no changes from file://${BASEDIR}/REPO FILE(repos-config) Wrote ${BASEDIR}/OPAM/repo/repos-config atomically in 0.000s CACHE(repository) Writing the repository cache to ${BASEDIR}/OPAM/repo/state-magicv.cache ... @@ -240,10 +237,10 @@ FILE(opam) Read ${BASEDIR}/OPAM/tarring/.opam-switch/packag <><> Updating package repositories ><><><><><><><><><><><><><><><><><><><><><><> [repo2] synchronised from file://${BASEDIR}/REPO2 FILE(repo) Read ${BASEDIR}/OPAM/repo/repo2/repo in 0.000s -FILE(opam) Read ${BASEDIR}/OPAM/repo/repo2/packages/bar/bar.3/opam in 0.000s +FILE(opam) Read packages/bar/bar.3/opam (out of ${BASEDIR}/OPAM/repo/repo2) in 0.000s +FILE(opam) Read packages/foo/foo.6/opam (out of ${BASEDIR}/OPAM/repo/tarred) in 0.000s [tarred] synchronised from file://${BASEDIR}/REPO FILE(repo) Read ${BASEDIR}/OPAM/repo/tarred/repo in 0.000s -FILE(opam) Read ${BASEDIR}/OPAM/repo/tarred/packages/foo/foo.6/opam in 0.000s FILE(repos-config) Wrote ${BASEDIR}/OPAM/repo/repos-config atomically in 0.000s CACHE(repository) Writing the repository cache to ${BASEDIR}/OPAM/repo/state-magicv.cache ... CACHE(repository) ${BASEDIR}/OPAM/repo/state-magicv.cache written in 0.000s @@ -383,7 +380,7 @@ first -- 1 oper file://${BASEDIR}/OPER ### opam repository --this-switch add oper2 ./OPER2 --strict [oper2] Initialised -[ERROR] In ${BASEDIR}/OPAM/repo/oper2/packages/second/second.2/opam: +[ERROR] In packages/second/second.2/opam: This file is for package 'second.2' but has mismatching fields 'version:2.2. [ERROR] Strict mode: aborting [ERROR] Could not update repository "oper2": OpamStd.OpamSys.Exit(30) @@ -395,7 +392,7 @@ first -- 1 oper file://${BASEDIR}/OPER ### opam repository --this-switch set-url oper ./OPER2 --strict [oper] Initialised -[ERROR] In ${BASEDIR}/OPAM/repo/oper/packages/second/second.2/opam: +[ERROR] In packages/second/second.2/opam: This file is for package 'second.2' but has mismatching fields 'version:2.2. [ERROR] Strict mode: aborting [ERROR] Could not update repository "oper": OpamStd.OpamSys.Exit(30) @@ -549,7 +546,7 @@ first -- 1 oper file://${BASEDIR}/OPER ### opam repository --this-switch add oper2 ./OPER2 --strict [oper2] Initialised -[ERROR] In ${BASEDIR}/OPAM/repo/oper2/packages/second/second.2/opam: +[ERROR] In packages/second/second.2/opam: This file is for package 'second.2' but has mismatching fields 'version:2.2. [ERROR] Strict mode: aborting [ERROR] Could not update repository "oper2": OpamStd.OpamSys.Exit(30) @@ -561,7 +558,7 @@ first -- 1 oper file://${BASEDIR}/OPER ### opam repository --this-switch set-url oper ./OPER2 --strict [oper] Initialised -[ERROR] In ${BASEDIR}/OPAM/repo/oper/packages/second/second.2/opam: +[ERROR] In packages/second/second.2/opam: This file is for package 'second.2' but has mismatching fields 'version:2.2. [ERROR] Strict mode: aborting [ERROR] Could not update repository "oper": OpamStd.OpamSys.Exit(30) @@ -634,7 +631,7 @@ some-field-that-do-not-exist: true <><> Updating package repositories ><><><><><><><><><><><><><><><><><><><><><><> [repo] no changes from file://${BASEDIR}/REPO [versions] synchronised from file://${BASEDIR}/VRS -opam-file opam-version "5.0" unsupported on ${BASEDIR}/OPAM/repo/versions/packages/bad-opam-version/bad-opam-version.1/opam. Added as dummy unavailable package. +opam-file opam-version "5.0" unsupported on packages/bad-opam-version/bad-opam-version.1/opam (out of ${BASEDIR}/OPAM/repo/versions). Added as dummy unavailable package. Now run 'opam upgrade' to apply any package updates. ### opam list -A --all-versions -s bad-opam-version.1 @@ -669,8 +666,8 @@ opam-version: "2.0" <><> Updating package repositories ><><><><><><><><><><><><><><><><><><><><><><> [repo] synchronised from file://${BASEDIR}/REPO -opam-file opam-version "5.0" unsupported on ${BASEDIR}/OPAM/repo/repo/packages/bad-opam-version/bad-opam-version.2/opam. Added as dummy unavailable package. -opam-file opam-version "5.0" unsupported on ${BASEDIR}/OPAM/repo/repo/packages/bad-opam-version/bad-opam-version.3/opam. Added as dummy unavailable package. +opam-file opam-version "5.0" unsupported on packages/bad-opam-version/bad-opam-version.2/opam (out of ${BASEDIR}/OPAM/repo/repo). Added as dummy unavailable package. +opam-file opam-version "5.0" unsupported on packages/bad-opam-version/bad-opam-version.3/opam (out of ${BASEDIR}/OPAM/repo/repo). Added as dummy unavailable package. [versions] synchronised from file://${BASEDIR}/VRS Now run 'opam upgrade' to apply any package updates. ### opam list -A --all-versions -s @@ -742,8 +739,8 @@ GARBAGE <><> Updating package repositories ><><><><><><><><><><><><><><><><><><><><><><> [versions] synchronised from file://${BASEDIR}/VRS -[WARNING] Could not read file ${BASEDIR}/OPAM/repo/versions/packages/two-zero/two-zero.1/opam. skipping: - At ${BASEDIR}/OPAM/repo/versions/packages/two-zero/two-zero.1/opam:3:0-3:0:: +[WARNING] Could not read file packages/two-zero/two-zero.1/opam (out of ${BASEDIR}/OPAM/repo/versions). skipping: + At packages/two-zero/two-zero.1/opam:3:0-3:0:: Parse error ### opam show two-zero --raw [ERROR] No package matching two-zero found @@ -756,8 +753,8 @@ GARBAGE <><> Updating package repositories ><><><><><><><><><><><><><><><><><><><><><><> [versions] synchronised from file://${BASEDIR}/VRS -[WARNING] Could not read file ${BASEDIR}/OPAM/repo/versions/packages/two-one/two-one.1/opam. skipping: - At ${BASEDIR}/OPAM/repo/versions/packages/two-one/two-one.1/opam:3:0-3:0:: +[WARNING] Could not read file packages/two-one/two-one.1/opam (out of ${BASEDIR}/OPAM/repo/versions). skipping: + At packages/two-one/two-one.1/opam:3:0-3:0:: Parse error Now run 'opam upgrade' to apply any package updates. ### opam show two-one --raw @@ -771,8 +768,8 @@ GARBAGE <><> Updating package repositories ><><><><><><><><><><><><><><><><><><><><><><> [versions] synchronised from file://${BASEDIR}/VRS -[WARNING] Could not read file ${BASEDIR}/OPAM/repo/versions/packages/two-two/two-two.1/opam. skipping: - At ${BASEDIR}/OPAM/repo/versions/packages/two-two/two-two.1/opam:3:0-3:0:: +[WARNING] Could not read file packages/two-two/two-two.1/opam (out of ${BASEDIR}/OPAM/repo/versions). skipping: + At packages/two-two/two-two.1/opam:3:0-3:0:: Parse error ### opam show two-two --raw [ERROR] No package matching two-two found @@ -785,8 +782,8 @@ GARBAGE <><> Updating package repositories ><><><><><><><><><><><><><><><><><><><><><><> [versions] synchronised from file://${BASEDIR}/VRS -[WARNING] Could not read file ${BASEDIR}/OPAM/repo/versions/packages/two-three/two-three.1/opam. skipping: - At ${BASEDIR}/OPAM/repo/versions/packages/two-three/two-three.1/opam:3:0-3:0:: +[WARNING] Could not read file packages/two-three/two-three.1/opam (out of ${BASEDIR}/OPAM/repo/versions). skipping: + At packages/two-three/two-three.1/opam:3:0-3:0:: Parse error ### opam show two-three --raw [ERROR] No package matching two-three found diff --git a/tests/reftests/update.test b/tests/reftests/update.test index d0c52596a23..1e978b3d0d1 100644 --- a/tests/reftests/update.test +++ b/tests/reftests/update.test @@ -201,7 +201,7 @@ opam-version: "2.0" <><> Updating package repositories ><><><><><><><><><><><><><><><><><><><><><><> [default] synchronised from file://${BASEDIR}/REPO FILE(config) Read ${BASEDIR}/OPAM/config in 0.000s -opam-file Mismatching extra-files at ${BASEDIR}/OPAM/repo/default/packages/qux/qux.1: wrong checksum (1) +opam-file Mismatching extra-files at packages/qux/qux.1 (out of ${BASEDIR}/OPAM/repo/default): wrong checksum (1) Now run 'opam upgrade' to apply any package updates. ### opam show qux --field extra-files: | sed-hash $INSTALL_MD5 install-md5 "qux.installl" "md5=+install-md5+" @@ -215,7 +215,7 @@ opam-version: "2.0" <><> Updating package repositories ><><><><><><><><><><><><><><><><><><><><><><> [default] synchronised from file://${BASEDIR}/REPO FILE(config) Read ${BASEDIR}/OPAM/config in 0.000s -opam-file Missing expected extra files qux.installl at ${BASEDIR}/OPAM/repo/default/packages/qux/qux.1/files +opam-file Missing expected extra files qux.installl at packages/qux/qux.1/files (out of ${BASEDIR}/OPAM/repo/default) ### opam show qux --field extra-files: | sed-hash $INSTALL_MD5 install-md5 "qux.installl" "md5=+install-md5+" ### :II: Git repo @@ -344,7 +344,7 @@ opam-version: "2.0" <><> Updating package repositories ><><><><><><><><><><><><><><><><><><><><><><> [git-test] synchronised from git+file://${BASEDIR}/GITREPO -opam-file Mismatching extra-files at ${BASEDIR}/OPAM/repo/git-test/packages/qux/qux.1: wrong checksum (1) +opam-file Mismatching extra-files at packages/qux/qux.1 (out of ${BASEDIR}/OPAM/repo/git-test): wrong checksum (1) Now run 'opam upgrade' to apply any package updates. ### opam show qux --field extra-files | sed-hash $INSTALL_MD5 install-md5 "qux.installl" "md5=+install-md5+" @@ -359,7 +359,7 @@ opam-version: "2.0" <><> Updating package repositories ><><><><><><><><><><><><><><><><><><><><><><> [git-test] synchronised from git+file://${BASEDIR}/GITREPO -opam-file Missing expected extra files qux.installl at ${BASEDIR}/OPAM/repo/git-test/packages/qux/qux.1/files +opam-file Missing expected extra files qux.installl at packages/qux/qux.1/files (out of ${BASEDIR}/OPAM/repo/git-test) ### opam show qux --field extra-files: | sed-hash $INSTALL_MD5 install-md5 "qux.installl" "md5=+install-md5+" ### :II:6: Package removal with prefix directories @@ -451,7 +451,7 @@ rm 'packages/prefix-pkg-c/pkg-c.1/files/k/1' <><> Updating package repositories ><><><><><><><><><><><><><><><><><><><><><><> [git-test] synchronised from git+file://${BASEDIR}/GITREPO -opam-file Missing expected extra files 1, k/1 at ${BASEDIR}/OPAM/repo/git-test/packages/prefix-pkg-c/pkg-c.1/files +opam-file Missing expected extra files 1, k/1 at packages/prefix-pkg-c/pkg-c.1/files (out of ${BASEDIR}/OPAM/repo/git-test) ### : ^ opam was updated so the missing extra files are detected ### opam list --all --repo=git-test -s new-pkg @@ -519,7 +519,7 @@ FILE(config) Read ${BASEDIR}/OPAM/config in 0.000s REPO_BACKEND diff: ${BASEDIR}/OPAM/repo/{incremental,incremental.new} REPO_BACKEND Internal diff (non-empty, 1 changed files) done in 0.00s. [incremental] synchronised from file://${BASEDIR}/INCR_REPO -FILE(opam) Read ${BASEDIR}/OPAM/repo/incremental/packages/gamma/gamma.1/opam in 0.000s +FILE(opam) Read packages/gamma/gamma.1/opam (out of ${BASEDIR}/OPAM/repo/incremental) in 0.000s ### opam show gamma.1 --field synopsis Gamma package - UPDATED ### :III:2: Add a new package - update should process only 1 new file @@ -533,7 +533,7 @@ FILE(config) Read ${BASEDIR}/OPAM/config in 0.000s REPO_BACKEND diff: ${BASEDIR}/OPAM/repo/{incremental,incremental.new} REPO_BACKEND Internal diff (non-empty, 1 changed files) done in 0.00s. [incremental] synchronised from file://${BASEDIR}/INCR_REPO -FILE(opam) Read ${BASEDIR}/OPAM/repo/incremental/packages/delta/delta.1/opam in 0.000s +FILE(opam) Read packages/delta/delta.1/opam (out of ${BASEDIR}/OPAM/repo/incremental) in 0.000s Now run 'opam upgrade' to apply any package updates. ### opam list --all -s --repo=incremental alpha @@ -570,9 +570,9 @@ FILE(config) Read ${BASEDIR}/OPAM/config in 0.000s REPO_BACKEND diff: ${BASEDIR}/OPAM/repo/{incremental,incremental.new} REPO_BACKEND Internal diff (non-empty, 4 changed files) done in 0.00s. [incremental] synchronised from file://${BASEDIR}/INCR_REPO -FILE(opam) Read ${BASEDIR}/OPAM/repo/incremental/packages/zeta/zeta.1/opam in 0.000s -FILE(opam) Read ${BASEDIR}/OPAM/repo/incremental/packages/epsilon/epsilon.1/opam in 0.000s -FILE(opam) Read ${BASEDIR}/OPAM/repo/incremental/packages/alpha/alpha.1/opam in 0.000s +FILE(opam) Read packages/alpha/alpha.1/opam (out of ${BASEDIR}/OPAM/repo/incremental) in 0.000s +FILE(opam) Read packages/epsilon/epsilon.1/opam (out of ${BASEDIR}/OPAM/repo/incremental) in 0.000s +FILE(opam) Read packages/zeta/zeta.1/opam (out of ${BASEDIR}/OPAM/repo/incremental) in 0.000s Now run 'opam upgrade' to apply any package updates. ### :III:5: Verify all changes were applied - 2 added, 1 modified, 1 deleted ### opam show alpha.1 --field synopsis @@ -605,7 +605,7 @@ FILE(config) Read ${BASEDIR}/OPAM/config in 0.000s REPO_BACKEND diff: ${BASEDIR}/OPAM/repo/{incremental,incremental.new} REPO_BACKEND Internal diff (non-empty, 2 changed files) done in 0.00s. [incremental] synchronised from file://${BASEDIR}/INCR_REPO -FILE(opam) Read ${BASEDIR}/OPAM/repo/incremental/packages/eta/eta.1/opam in 0.000s +FILE(opam) Read packages/eta/eta.1/opam (out of ${BASEDIR}/OPAM/repo/incremental) in 0.000s Now run 'opam upgrade' to apply any package updates. ### opam show eta --field extra-files: | sed-hash $INSTALL_MD5 install-md5 "eta.installl" "md5=+install-md5+" @@ -630,7 +630,7 @@ FILE(config) Read ${BASEDIR}/OPAM/config in 0.000s REPO_BACKEND diff: ${BASEDIR}/OPAM/repo/{incremental,incremental.new} REPO_BACKEND Internal diff (non-empty, 2 changed files) done in 0.00s. [incremental] synchronised from file://${BASEDIR}/INCR_REPO -FILE(opam) Read ${BASEDIR}/OPAM/repo/incremental/packages/eta/eta.1/opam in 0.000s +FILE(opam) Read packages/eta/eta.1/opam (out of ${BASEDIR}/OPAM/repo/incremental) in 0.000s Now run 'opam upgrade' to apply any package updates. ### opam show eta --field extra-files: | sed-hash $AINSTALL_MD5 ainstall-md5 "eta.installl" "md5=+ainstall-md5+" @@ -655,7 +655,7 @@ FILE(config) Read ${BASEDIR}/OPAM/config in 0.000s REPO_BACKEND diff: ${BASEDIR}/OPAM/repo/{incremental,incremental.new} REPO_BACKEND Internal diff (non-empty, 2 changed files) done in 0.00s. [incremental] synchronised from file://${BASEDIR}/INCR_REPO -FILE(opam) Read ${BASEDIR}/OPAM/repo/incremental/packages/eta/eta.1/opam in 0.000s +FILE(opam) Read packages/eta/eta.1/opam (out of ${BASEDIR}/OPAM/repo/incremental) in 0.000s Now run 'opam upgrade' to apply any package updates. ### opam show eta --field extra-files: @@ -689,7 +689,7 @@ REPO_BACKEND diff: ${BASEDIR}/OPAM/repo/{incremental,incremen REPO_BACKEND Internal diff (non-empty, 1 changed files) done in 0.00s. [incremental] synchronised from file://${BASEDIR}/INCR_REPO FILE(config) Read ${BASEDIR}/OPAM/config in 0.000s -FILE(opam) Read ${BASEDIR}/OPAM/repo/incremental/packages/eta/eta.1/opam in 0.000s +FILE(opam) Read packages/eta/eta.1/opam (out of ${BASEDIR}/OPAM/repo/incremental) in 0.000s opam-file Missing extra-files field for eta.installl for eta.1, ignoring them. ### opam show eta --field extra-files: @@ -724,8 +724,8 @@ REPO_BACKEND diff: ${BASEDIR}/OPAM/repo/{incremental,incremen REPO_BACKEND Internal diff (non-empty, 2 changed files) done in 0.00s. [incremental] synchronised from file://${BASEDIR}/INCR_REPO FILE(config) Read ${BASEDIR}/OPAM/config in 0.000s -FILE(opam) Read ${BASEDIR}/OPAM/repo/incremental/packages/eta/eta.1/opam in 0.000s -opam-file Mismatching extra-files at ${BASEDIR}/OPAM/repo/incremental/packages/eta/eta.1: wrong checksum (1) +FILE(opam) Read packages/eta/eta.1/opam (out of ${BASEDIR}/OPAM/repo/incremental) in 0.000s +opam-file Mismatching extra-files at packages/eta/eta.1 (out of ${BASEDIR}/OPAM/repo/incremental): wrong checksum (1) Now run 'opam upgrade' to apply any package updates. ### opam show eta --field extra-files: | sed-hash $INSTALL_MD5 install-md5 "eta.installl" "md5=+install-md5+" @@ -761,8 +761,8 @@ REPO_BACKEND diff: ${BASEDIR}/OPAM/repo/{incremental,incremen REPO_BACKEND Internal diff (non-empty, 1 changed files) done in 0.00s. [incremental] synchronised from file://${BASEDIR}/INCR_REPO FILE(config) Read ${BASEDIR}/OPAM/config in 0.000s -FILE(opam) Read ${BASEDIR}/OPAM/repo/incremental/packages/eta/eta.1/opam in 0.000s -opam-file Missing expected extra files eta.installl at ${BASEDIR}/OPAM/repo/incremental/packages/eta/eta.1/files +FILE(opam) Read packages/eta/eta.1/opam (out of ${BASEDIR}/OPAM/repo/incremental) in 0.000s +opam-file Missing expected extra files eta.installl at packages/eta/eta.1/files (out of ${BASEDIR}/OPAM/repo/incremental) ### opam show eta --field extra-files: | sed-hash $INSTALL_MD5 install-md5 "eta.installl" "md5=+install-md5+" ### opam install eta From 4852c2742087f1ae27a5acdac5653e0f28ae3e50 Mon Sep 17 00:00:00 2001 From: Raja Boujbel Date: Wed, 27 May 2026 19:51:24 +0200 Subject: [PATCH 20/24] reftest: add a test in repository-http for switching from directory to archive representation --- master_changes.md | 1 + tests/reftests/repository-http.test | 53 +++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+) diff --git a/master_changes.md b/master_changes.md index b5182197e04..e37315d45b6 100644 --- a/master_changes.md +++ b/master_changes.md @@ -191,6 +191,7 @@ users) * Add a test showing the behaviour of `opam repo add` and `opam update` when faced with a repository containing an `opam` directory [#6995 @kit-ty-kate] * Add a tests for the several layouts of packages in a repository [#6941 @rjbou] * Add a `opam repo set-url` case in repository-http [#6625 @rjbou] + * Add in `repository-http` a test case for switching from directory to archive format, automatically [#6625 @rjbou] ### Engine * Add `http-server` to launch a minimal http server [#6939 @rjbou] diff --git a/tests/reftests/repository-http.test b/tests/reftests/repository-http.test index 69d2397f3fe..5cf03aa539a 100644 --- a/tests/reftests/repository-http.test +++ b/tests/reftests/repository-http.test @@ -213,4 +213,57 @@ satu -- tiga -- ### opam repository remove set-repo --all ### rm -r SETREPO +### :VI: Test automatic changes from directory to archive repository internal storage +### +opam-version: "2.0" +### +opam-version: "2.0" +### rm -r packages/tiga +### opam admin index +Generating urls.txt... +Generating index.tar.gz... +Done. +### find OPAM/repo | sort +OPAM/repo +OPAM/repo/http-repo.tar.gz +OPAM/repo/lock +OPAM/repo/repos-config +OPAM/repo/state-magicv.cache +### mkdir OPAM/repo/http-repo +### tar xf OPAM/repo/http-repo.tar.gz -C OPAM/repo/http-repo +### rm OPAM/repo/http-repo.tar.gz +### OPAMDEBUGSECTIONS="TAR RSTATE REPOSITORY REPO_BACKEND UPDATE" OPAMDEBUG=-3 OPAMVERBOSE=2 +### opam update | sed-cmd curl tar | grep -v "^+-" | ".*\(curl\|wget\).* \"--\"" -> 'curl-or-wget --' | "${HTTPSERVERPORT}" -> "port" +FILE(config) Read ${BASEDIR}/OPAM/config in 0.000s +RSTATE LOAD-REPOSITORY-STATE @ ${BASEDIR}/OPAM +RSTATE Cache found + +<><> Updating package repositories ><><><><><><><><><><><><><><><><><><><><><><> +UPDATE repository format change: from directory to archive (${BASEDIR}/OPAM/repo/http-repo.tar.gz) +TAR creating archive ${BASEDIR}/OPAM/repo/http-repo.tar.gz from ${BASEDIR}/OPAM/repo/http-repo +TAR Writing archive ${BASEDIR}/OPAM/repo/http-repo.tar.gz +REPOSITORY update http-repo from http://localhost:port +Processing 1/1: [http-repo: http] +curl-or-wget -- "http://localhost:port/index.tar.gz" +REPO_BACKEND diff: ${BASEDIR}/OPAM/repo/{http-repo.tar.gz,http-repo.tar.gz.new} +REPO_BACKEND Internal diff (non-empty, 4 changed files) done in 0.00s. +[http-repo] synchronised from http://localhost:port +REPOSITORY http-repo: applying patch update at ${BASEDIR}/OPAM/log/patch-xxx +TAR Writing archive ${BASEDIR}/OPAM/repo/http-repo.tar.gz +UPDATE Repository has new changes +Processing: [http-repo: loading data] +RSTATE load repo http-repo from diff +Now run 'opam upgrade' to apply any package updates. +### unset OPAMDEBUGSECTIONS +### unset OPAMDEBUG +### unset OPAMVERBOSE +### opam list --all +# Packages matching: any +# Name # Installed # Synopsis +delapan -- +dua -- +empat -- +enam -- +lima -- +satu -- [[[Killing micro_httpd]]] From 34fc6b2a6cec30aac5f7527b8e3fc82e1775e9b1 Mon Sep 17 00:00:00 2001 From: Raja Boujbel Date: Fri, 19 Jun 2026 17:40:10 +0200 Subject: [PATCH 21/24] reftests: add repository test format change from dir to tar and vice versa --- master_changes.md | 2 + tests/reftests/repository.test | 439 +++++++++++++++++++++++++++++++++ 2 files changed, 441 insertions(+) diff --git a/master_changes.md b/master_changes.md index e37315d45b6..f73273d656c 100644 --- a/master_changes.md +++ b/master_changes.md @@ -192,6 +192,8 @@ users) * Add a tests for the several layouts of packages in a repository [#6941 @rjbou] * Add a `opam repo set-url` case in repository-http [#6625 @rjbou] * Add in `repository-http` a test case for switching from directory to archive format, automatically [#6625 @rjbou] + * Add in `repository` test cases for switching automatically from directory to archive format & vice versa [#6625 @rjbou] + * Add in `repository` test cases for upgrade opam root from 2.5 with repo tarring or 2.1 to 2.6, with `OPAMREPOSITORYTARRING` enabled (trigger upgrade) [#6625 @rjbou] ### Engine * Add `http-server` to launch a minimal http server [#6939 @rjbou] diff --git a/tests/reftests/repository.test b/tests/reftests/repository.test index a733e58f1ea..5ed5d569088 100644 --- a/tests/reftests/repository.test +++ b/tests/reftests/repository.test @@ -1006,3 +1006,442 @@ Processing 2/4: [opam: echo update] -> removed opam.1 -> installed opam.1 Done. +### opam repository remove opam-dir --all +### : :::::::::::::::::::::::: +### : repository format change +### : we test here only local dir or tarred to & from vcs. Simple local to and +### : from tar is already tested at the beginning of the file +### : should the test force tarred/dir/git by directly writing it internally +### : or should it keep using opam to setup the state ? +### : ===> it should be done via internal change, it is unreachable states via opam +### : :::::::::::::::::::::::: +### opam repository remove oper oper3 test-git to-many-commits --all +### +opam-version: "2.0" +### +opam-version: "2.0" +### +un +### sh hash.sh CHG yan.1 +### opam switch create format-change --empty +### OPAMREPOSITORYTARRING=1 +### OPAMDEBUGSECTIONS="TAR RSTATE REPOSITORY REPO_BACKEND UPDATE" OPAMDEBUG=-3 OPAMVERBOSE=2 +### opam repository add changes ./CHG --this-switch +FILE(config) Read ${BASEDIR}/OPAM/config in 0.000s +RSTATE LOAD-REPOSITORY-STATE @ ${BASEDIR}/OPAM +RSTATE Cache found +REPOSITORY repository-add +REPOSITORY update changes from file://${BASEDIR}/CHG +TAR creating archive ${BASEDIR}/OPAM/repo/changes.tar.gz.new from ${BASEDIR}/CHG +TAR Writing archive ${BASEDIR}/OPAM/repo/changes.tar.gz.new +REPOSITORY changes: applying update from scratch at ${BASEDIR}/OPAM/repo/changes.tar.gz.new +[changes] Initialised +UPDATE Repository has new changes +Processing: [changes: loading data] +RSTATE load repo changes from tgz +### test -d OPAM/repo/changes +# Return code 1 # +### test -d OPAM/repo/changes/.git +# Return code 1 # +### test -f OPAM/repo/changes.tar.gz +### cp OPAM/repo/changes.tar.gz changes.tar.gz +### :: local tarred - git * no changes +### git -C ./CHG init -q +### git -C ./CHG config core.autocrlf false +### git -C ./CHG add repo packages +### git -C ./CHG commit -qm "yan" +### test -f OPAM/repo/changes.tar.gz +### opam repository set-url changes git+file://${BASEDIR}/CHG | sed-cmd git | grep -v "HEAD is now" +FILE(config) Read ${BASEDIR}/OPAM/config in 0.000s +RSTATE LOAD-REPOSITORY-STATE @ ${BASEDIR}/OPAM +RSTATE Cache found +REPOSITORY repository-set-url +REPOSITORY update changes from git+file://${BASEDIR}/CHG +Processing 1/1: [changes: git] ++ git "-C" "${BASEDIR}/OPAM/repo/changes" "init" +- Initialized empty Git repository in ${BASEDIR}/OPAM/repo/changes/.git/ ++ git "-C" "${BASEDIR}/OPAM/repo/changes" "config" "--local" "fetch.prune" "false" ++ git "-C" "${BASEDIR}/OPAM/repo/changes" "config" "--local" "diff.noprefix" "false" ++ git "-C" "${BASEDIR}/OPAM/repo/changes" "config" "--local" "core.autocrlf" "false" ++ git "-C" "${BASEDIR}/OPAM/repo/changes" "config" "--local" "core.eol" "lf" ++ git "-C" "${BASEDIR}/OPAM/repo/changes" "config" "--local" "color.ui" "false" ++ git "-C" "${BASEDIR}/OPAM/repo/changes" "remote" "add" "origin" "file://${BASEDIR}/CHG" ++ git "-C" "${BASEDIR}/OPAM/repo/changes" "remote" "set-url" "origin" "file://${BASEDIR}/CHG" ++ git "-C" "${BASEDIR}/OPAM/repo/changes" "fetch" "-q" "file://${BASEDIR}/CHG" "--update-shallow" "--depth=1" "+HEAD:refs/remotes/opam-ref" ++ git "-C" "${BASEDIR}/OPAM/repo/changes.new" "reset" "--hard" "refs/remotes/opam-ref" "--" ++ git "-C" "${BASEDIR}/OPAM/repo/changes.new" "clean" "-fdx" +REPOSITORY changes: applying update from scratch at ${BASEDIR}/OPAM/repo/changes.new +[changes] Initialised +UPDATE Repository has new changes +Processing: [changes: loading data] +RSTATE load repo changes from dir +### test -d OPAM/repo/changes +### test -d OPAM/repo/changes/.git +### test -f OPAM/repo/changes.tar.gz +# Return code 1 # +### opam install yan +FILE(config) Read ${BASEDIR}/OPAM/config in 0.000s +RSTATE LOAD-REPOSITORY-STATE @ ${BASEDIR}/OPAM +RSTATE Cache found +The following actions will be performed: +=== install 1 package + - install yan 1 + +<><> Processing actions <><><><><><><><><><><><><><><><><><><><><><><><><><><><> +-> installed yan.1 +Done. +### :: local tarred - git * changes +### OPAMREPOSITORYTARRING=1 +### cp changes.tar.gz OPAM/repo/changes.tar.gz +### rm -r OPAM/repo/changes +### +opam-version: "2.0" +### +deux +### sh hash.sh CHG sin.2 +### git -C ./CHG add packages +### git -C ./CHG commit -qm "sin" +### opam update | sed-cmd git tar | grep -v "HEAD is now" +FILE(config) Read ${BASEDIR}/OPAM/config in 0.000s +RSTATE LOAD-REPOSITORY-STATE @ ${BASEDIR}/OPAM +RSTATE Cache found + +<><> Updating package repositories ><><><><><><><><><><><><><><><><><><><><><><> +UPDATE repository format change: from archive to directory (${BASEDIR}/OPAM/repo/changes) +Processing 1/1: ++ tar "xfz" "${BASEDIR}/OPAM/repo/changes.tar.gz" "-C" "${BASEDIR}/OPAM/repo/changes" +REPOSITORY update changes from git+file://${BASEDIR}/CHG +Processing 1/1: [changes: git] ++ git "-C" "${BASEDIR}/OPAM/repo/changes" "init" +- Initialized empty Git repository in ${BASEDIR}/OPAM/repo/changes/.git/ ++ git "-C" "${BASEDIR}/OPAM/repo/changes" "config" "--local" "fetch.prune" "false" ++ git "-C" "${BASEDIR}/OPAM/repo/changes" "config" "--local" "diff.noprefix" "false" ++ git "-C" "${BASEDIR}/OPAM/repo/changes" "config" "--local" "core.autocrlf" "false" ++ git "-C" "${BASEDIR}/OPAM/repo/changes" "config" "--local" "core.eol" "lf" ++ git "-C" "${BASEDIR}/OPAM/repo/changes" "config" "--local" "color.ui" "false" ++ git "-C" "${BASEDIR}/OPAM/repo/changes" "remote" "add" "origin" "file://${BASEDIR}/CHG" ++ git "-C" "${BASEDIR}/OPAM/repo/changes" "remote" "set-url" "origin" "file://${BASEDIR}/CHG" ++ git "-C" "${BASEDIR}/OPAM/repo/changes" "fetch" "-q" "file://${BASEDIR}/CHG" "--update-shallow" "--depth=1" "+HEAD:refs/remotes/opam-ref" ++ git "-C" "${BASEDIR}/OPAM/repo/changes.new" "reset" "--hard" "refs/remotes/opam-ref" "--" ++ git "-C" "${BASEDIR}/OPAM/repo/changes.new" "clean" "-fdx" +REPOSITORY changes: applying update from scratch at ${BASEDIR}/OPAM/repo/changes.new +[changes] Initialised +UPDATE Repository has new changes +Processing: [changes: loading data] +RSTATE load repo changes from dir +Now run 'opam upgrade' to apply any package updates. +### test -d OPAM/repo/changes +### opam install sin +FILE(config) Read ${BASEDIR}/OPAM/config in 0.000s +RSTATE LOAD-REPOSITORY-STATE @ ${BASEDIR}/OPAM +RSTATE Cache found +The following actions will be performed: +=== install 1 package + - install sin 2 + +<><> Processing actions <><><><><><><><><><><><><><><><><><><><><><><><><><><><> +-> installed sin.2 +Done. +### :: git - local tarred * no changes +### OPAMREPOSITORYTARRING=1 +### cp -R OPAM/repo/changes changes +### rm -rf CHG/.git +### opam repository set-url changes file://${BASEDIR}/CHG +FILE(config) Read ${BASEDIR}/OPAM/config in 0.000s +RSTATE LOAD-REPOSITORY-STATE @ ${BASEDIR}/OPAM +RSTATE Cache found +REPOSITORY repository-set-url +REPOSITORY update changes from file://${BASEDIR}/CHG +TAR creating archive ${BASEDIR}/OPAM/repo/changes.tar.gz.new from ${BASEDIR}/CHG +TAR Writing archive ${BASEDIR}/OPAM/repo/changes.tar.gz.new +REPOSITORY changes: applying update from scratch at ${BASEDIR}/OPAM/repo/changes.tar.gz.new +[changes] Initialised +UPDATE Repository has new changes +Processing: [changes: loading data] +RSTATE load repo changes from tgz +### test -f OPAM/repo/changes.tar.gz +### opam reinstall sin +FILE(config) Read ${BASEDIR}/OPAM/config in 0.000s +RSTATE LOAD-REPOSITORY-STATE @ ${BASEDIR}/OPAM +RSTATE Cache found +The following actions will be performed: +=== recompile 1 package + - recompile sin 2 + +<><> Processing actions <><><><><><><><><><><><><><><><><><><><><><><><><><><><> +-> removed sin.2 +-> installed sin.2 +Done. +### :: git - local tarred * changes +### OPAMREPOSITORYTARRING=1 +### +opam-version: "2.0" +### +trois +### sh hash.sh CHG krad.3 +### rm OPAM/repo/changes.tar.gz +### mv changes OPAM/repo/changes +### opam update +FILE(config) Read ${BASEDIR}/OPAM/config in 0.000s +RSTATE LOAD-REPOSITORY-STATE @ ${BASEDIR}/OPAM +RSTATE Cache found + +<><> Updating package repositories ><><><><><><><><><><><><><><><><><><><><><><> +UPDATE repository format change: from directory to archive (${BASEDIR}/OPAM/repo/changes.tar.gz) +TAR creating archive ${BASEDIR}/OPAM/repo/changes.tar.gz from ${BASEDIR}/OPAM/repo/changes +TAR Writing archive ${BASEDIR}/OPAM/repo/changes.tar.gz +REPOSITORY update changes from file://${BASEDIR}/CHG +TAR creating archive ${BASEDIR}/OPAM/repo/changes.tar.gz.new from ${BASEDIR}/CHG +TAR Writing archive ${BASEDIR}/OPAM/repo/changes.tar.gz.new +REPO_BACKEND diff: ${BASEDIR}/OPAM/repo/{changes.tar.gz,changes.tar.gz.new} +REPO_BACKEND Internal diff (non-empty, 2 changed files) done in 0.00s. +[changes] synchronised from file://${BASEDIR}/CHG +REPOSITORY changes: applying patch update at ${BASEDIR}/OPAM/log/patch-xxx +TAR Writing archive ${BASEDIR}/OPAM/repo/changes.tar.gz +UPDATE Repository has new changes +Processing: [changes: loading data] +RSTATE load repo changes from diff +Now run 'opam upgrade' to apply any package updates. +### test -d OPAM/repo/changes +# Return code 1 # +### test -d OPAM/repo/changes/.git +# Return code 1 # +### test -f OPAM/repo/changes.tar.gz +### opam install krad +FILE(config) Read ${BASEDIR}/OPAM/config in 0.000s +RSTATE LOAD-REPOSITORY-STATE @ ${BASEDIR}/OPAM +RSTATE Cache found +The following actions will be performed: +=== install 1 package + - install krad 3 + +<><> Processing actions <><><><><><><><><><><><><><><><><><><><><><><><><><><><> +-> installed krad.3 +Done. +### :: local dir - git * no changes +### OPAMREPOSITORYTARRING=0 +### mkdir OPAM/repo/changes +### tar xf OPAM/repo/changes.tar.gz -C OPAM/repo/changes +### rm OPAM/repo/changes.tar.gz +### git -C ./CHG init -q +### git -C ./CHG config core.autocrlf false +### git -C ./CHG add repo packages +### git -C ./CHG commit -qm "krad" +### opam repository set-url changes git+file://${BASEDIR}/CHG | sed-cmd git | grep -v "HEAD is now" +FILE(config) Read ${BASEDIR}/OPAM/config in 0.000s +RSTATE LOAD-REPOSITORY-STATE @ ${BASEDIR}/OPAM +RSTATE Cache found +REPOSITORY repository-set-url +REPOSITORY update changes from git+file://${BASEDIR}/CHG +Processing 1/1: [changes: git] ++ git "-C" "${BASEDIR}/OPAM/repo/changes" "init" +- Initialized empty Git repository in ${BASEDIR}/OPAM/repo/changes/.git/ ++ git "-C" "${BASEDIR}/OPAM/repo/changes" "config" "--local" "fetch.prune" "false" ++ git "-C" "${BASEDIR}/OPAM/repo/changes" "config" "--local" "diff.noprefix" "false" ++ git "-C" "${BASEDIR}/OPAM/repo/changes" "config" "--local" "core.autocrlf" "false" ++ git "-C" "${BASEDIR}/OPAM/repo/changes" "config" "--local" "core.eol" "lf" ++ git "-C" "${BASEDIR}/OPAM/repo/changes" "config" "--local" "color.ui" "false" ++ git "-C" "${BASEDIR}/OPAM/repo/changes" "remote" "add" "origin" "file://${BASEDIR}/CHG" ++ git "-C" "${BASEDIR}/OPAM/repo/changes" "remote" "set-url" "origin" "file://${BASEDIR}/CHG" ++ git "-C" "${BASEDIR}/OPAM/repo/changes" "fetch" "-q" "file://${BASEDIR}/CHG" "--update-shallow" "--depth=1" "+HEAD:refs/remotes/opam-ref" ++ git "-C" "${BASEDIR}/OPAM/repo/changes.new" "reset" "--hard" "refs/remotes/opam-ref" "--" ++ git "-C" "${BASEDIR}/OPAM/repo/changes.new" "clean" "-fdx" +REPOSITORY changes: applying update from scratch at ${BASEDIR}/OPAM/repo/changes.new +[changes] Initialised +UPDATE Repository has new changes +Processing: [changes: loading data] +RSTATE load repo changes from dir +### test -d OPAM/repo/changes +### test -d OPAM/repo/changes/.git +### test -f OPAM/repo/changes.tar.gz +# Return code 1 # +### opam reinstall krad +FILE(config) Read ${BASEDIR}/OPAM/config in 0.000s +RSTATE LOAD-REPOSITORY-STATE @ ${BASEDIR}/OPAM +RSTATE Cache found +The following actions will be performed: +=== recompile 1 package + - recompile krad 3 + +<><> Processing actions <><><><><><><><><><><><><><><><><><><><><><><><><><><><> +-> removed krad.3 +-> installed krad.3 +Done. +### :: local dir - git * changes +### OPAMREPOSITORYTARRING=0 +### +opam-version: "2.0" +### +quatre +### sh hash.sh CHG okkoz.4 +### git -C ./CHG add packages +### git -C ./CHG commit -qm "okkoz" +### rm -r OPAM/repo/changes/.git +### opam update | sed-cmd git | grep -v "HEAD is now" +FILE(config) Read ${BASEDIR}/OPAM/config in 0.000s +RSTATE LOAD-REPOSITORY-STATE @ ${BASEDIR}/OPAM +RSTATE Cache found + +<><> Updating package repositories ><><><><><><><><><><><><><><><><><><><><><><> +REPOSITORY update changes from git+file://${BASEDIR}/CHG +Processing 1/1: [changes: git] ++ git "-C" "${BASEDIR}/OPAM/repo/changes" "init" +- Initialized empty Git repository in ${BASEDIR}/OPAM/repo/changes/.git/ ++ git "-C" "${BASEDIR}/OPAM/repo/changes" "config" "--local" "fetch.prune" "false" ++ git "-C" "${BASEDIR}/OPAM/repo/changes" "config" "--local" "diff.noprefix" "false" ++ git "-C" "${BASEDIR}/OPAM/repo/changes" "config" "--local" "core.autocrlf" "false" ++ git "-C" "${BASEDIR}/OPAM/repo/changes" "config" "--local" "core.eol" "lf" ++ git "-C" "${BASEDIR}/OPAM/repo/changes" "config" "--local" "color.ui" "false" ++ git "-C" "${BASEDIR}/OPAM/repo/changes" "remote" "add" "origin" "file://${BASEDIR}/CHG" ++ git "-C" "${BASEDIR}/OPAM/repo/changes" "remote" "set-url" "origin" "file://${BASEDIR}/CHG" ++ git "-C" "${BASEDIR}/OPAM/repo/changes" "fetch" "-q" "file://${BASEDIR}/CHG" "--update-shallow" "--depth=1" "+HEAD:refs/remotes/opam-ref" ++ git "-C" "${BASEDIR}/OPAM/repo/changes.new" "reset" "--hard" "refs/remotes/opam-ref" "--" ++ git "-C" "${BASEDIR}/OPAM/repo/changes.new" "clean" "-fdx" +REPOSITORY changes: applying update from scratch at ${BASEDIR}/OPAM/repo/changes.new +[changes] Initialised +UPDATE Repository has new changes +Processing: [changes: loading data] +RSTATE load repo changes from dir +Now run 'opam upgrade' to apply any package updates. +### test -d OPAM/repo/changes +### test -d OPAM/repo/changes/.git +### test -f OPAM/repo/changes.tar.gz +# Return code 1 # +### opam install okkoz +FILE(config) Read ${BASEDIR}/OPAM/config in 0.000s +RSTATE LOAD-REPOSITORY-STATE @ ${BASEDIR}/OPAM +RSTATE Cache found +The following actions will be performed: +=== install 1 package + - install okkoz 4 + +<><> Processing actions <><><><><><><><><><><><><><><><><><><><><><><><><><><><> +-> installed okkoz.4 +Done. +### :: git - local dir * no changes +### OPAMREPOSITORYTARRING=0 +### cp -R OPAM/repo/changes changes +### rm -rf CHG/.git +### opam repository set-url changes file://${BASEDIR}/CHG +FILE(config) Read ${BASEDIR}/OPAM/config in 0.000s +RSTATE LOAD-REPOSITORY-STATE @ ${BASEDIR}/OPAM +RSTATE Cache found +REPOSITORY repository-set-url +REPOSITORY update changes from file://${BASEDIR}/CHG +REPOSITORY changes: applying update from scratch at ${BASEDIR}/OPAM/repo/changes.new +[changes] Initialised +UPDATE Repository has new changes +Processing: [changes: loading data] +RSTATE load repo changes from dir +### test -d OPAM/repo/changes +### test -d OPAM/repo/changes/.git +# Return code 1 # +### test -f OPAM/repo/changes.tar.gz +# Return code 1 # +### opam reinstall okkoz +FILE(config) Read ${BASEDIR}/OPAM/config in 0.000s +RSTATE LOAD-REPOSITORY-STATE @ ${BASEDIR}/OPAM +RSTATE Cache found +The following actions will be performed: +=== recompile 1 package + - recompile okkoz 4 + +<><> Processing actions <><><><><><><><><><><><><><><><><><><><><><><><><><><><> +-> removed okkoz.4 +-> installed okkoz.4 +Done. +### :: git - local dir * changes +### OPAMREPOSITORYTARRING=0 +### +opam-version: "2.0" +### +cinq +### sh hash.sh CHG semmus.5 +### rm -r OPAM/repo/changes +### mv changes OPAM/repo/ +### opam update +FILE(config) Read ${BASEDIR}/OPAM/config in 0.000s +RSTATE LOAD-REPOSITORY-STATE @ ${BASEDIR}/OPAM +RSTATE Cache found + +<><> Updating package repositories ><><><><><><><><><><><><><><><><><><><><><><> +REPOSITORY update changes from file://${BASEDIR}/CHG +REPO_BACKEND diff: ${BASEDIR}/OPAM/repo/{changes,changes.new} +REPO_BACKEND Internal diff (non-empty, 2 changed files) done in 0.00s. +[changes] synchronised from file://${BASEDIR}/CHG +REPOSITORY changes: applying patch update at ${BASEDIR}/OPAM/log/patch-xxx +UPDATE Repository has new changes +Processing: [changes: loading data] +RSTATE load repo changes from diff +Now run 'opam upgrade' to apply any package updates. +### test -d OPAM/repo/changes +### test -d OPAM/repo/changes/.git +### test -f OPAM/repo/changes.tar.gz +# Return code 1 # +### opam install semmus +FILE(config) Read ${BASEDIR}/OPAM/config in 0.000s +RSTATE LOAD-REPOSITORY-STATE @ ${BASEDIR}/OPAM +RSTATE Cache found +The following actions will be performed: +=== install 1 package + - install semmus 5 + +<><> Processing actions <><><><><><><><><><><><><><><><><><><><><><><><><><><><> +-> installed semmus.5 +Done. +### :: both exists - no tarring +### opam-cat OPAM/repo/repos-config +opam-version: "2.0" +repositories: "changes" {"file://${BASEDIR}/CHG"} +### sh -c "test -d CHG/.git && rm -r CHG/.git || true" +### OPAMREPOSITORYTARRING=0 +### cp changes.tar.gz OPAM/repo/changes.tar.gz +### +opam-version: "2.0" +build: true +### opam update +FILE(config) Read ${BASEDIR}/OPAM/config in 0.000s +RSTATE LOAD-REPOSITORY-STATE @ ${BASEDIR}/OPAM +RSTATE Cache found + +<><> Updating package repositories ><><><><><><><><><><><><><><><><><><><><><><> +UPDATE repository exists as directory and archive, removing both +REPOSITORY update changes from file://${BASEDIR}/CHG +REPOSITORY changes: applying update from scratch at ${BASEDIR}/OPAM/repo/changes.new +[changes] Initialised +UPDATE Repository has new changes +Processing: [changes: loading data] +RSTATE load repo changes from dir +Now run 'opam upgrade' to apply any package updates. +### test -d OPAM/repo/changes +### test -d OPAM/repo/changes/.git +# Return code 1 # +### test -f OPAM/repo/changes.tar.gz +# Return code 1 # +### :: both exists - tarring +### OPAMREPOSITORYTARRING=1 +### cp changes.tar.gz OPAM/repo/changes.tar.gz +### +opam-version: "2.0" +build: false +### opam update +FILE(config) Read ${BASEDIR}/OPAM/config in 0.000s +RSTATE LOAD-REPOSITORY-STATE @ ${BASEDIR}/OPAM +RSTATE Cache found + +<><> Updating package repositories ><><><><><><><><><><><><><><><><><><><><><><> +UPDATE repository exists as directory and archive, removing both +REPOSITORY update changes from file://${BASEDIR}/CHG +TAR creating archive ${BASEDIR}/OPAM/repo/changes.tar.gz.new from ${BASEDIR}/CHG +TAR Writing archive ${BASEDIR}/OPAM/repo/changes.tar.gz.new +REPOSITORY changes: applying update from scratch at ${BASEDIR}/OPAM/repo/changes.tar.gz.new +[changes] Initialised +UPDATE Repository has new changes +Processing: [changes: loading data] +RSTATE load repo changes from tgz +### test -d OPAM/repo/changes +# Return code 1 # +### test -d OPAM/repo/changes/.git +# Return code 1 # +### test -f OPAM/repo/changes.tar.gz +### unset OPAMDEBUG OPAMDEBUGSECTIONS OPAMVERBOSE From 0456e11488b03b36d64566c17fbdf9710d1f27e2 Mon Sep 17 00:00:00 2001 From: Raja Boujbel Date: Wed, 27 May 2026 21:41:02 +0200 Subject: [PATCH 22/24] Add conditional upgrade opam root for 2.6 This opam root upgrade is triggered only if there is an already present archive repository, generated from old OPAMREPOSITORYTARRING usage, or 2.1 (that does it automatically). It reconstruct that archive in the new version of repository storage archive (no root directory). --- master_changes.md | 2 + src/format/opamFile.ml | 2 +- src/state/opamFormatUpgrade.ml | 51 ++++ tests/reftests/opamroot-versions.test | 372 +++++++++++++++++++++++++- 4 files changed, 418 insertions(+), 9 deletions(-) diff --git a/master_changes.md b/master_changes.md index f73273d656c..74b092b59bc 100644 --- a/master_changes.md +++ b/master_changes.md @@ -93,6 +93,7 @@ users) * Fix switch and repo format upgrade on Windows. A block occurred because the global lock fd was reopened instead of using the one already opened. [#6839 @rjbou] * Add opam root format upgrade conditional mechanism for hard upgrades [#6949 @rjbou] * Stop the opam 1.2 to 2.0 repository upgrade process from downloading packages without checksums to add a non-trusted md5 [#6978 @kit-ty-kate] + * Add conditional upgrade to opam root 2.6. It is triggered by an already present repository archive (from `OPAMREPOSITORYTARRING` usage, or 2.1 opamroot) [#6625 @rjbou] ## Sandbox * Allow the macOS sandbox to write in the `/var/folders/` and `/var/db/mds/` directories as it is required by some of macOS core tools [#4797 @kit-ty-kate - fix #4389 #6460] @@ -194,6 +195,7 @@ users) * Add in `repository-http` a test case for switching from directory to archive format, automatically [#6625 @rjbou] * Add in `repository` test cases for switching automatically from directory to archive format & vice versa [#6625 @rjbou] * Add in `repository` test cases for upgrade opam root from 2.5 with repo tarring or 2.1 to 2.6, with `OPAMREPOSITORYTARRING` enabled (trigger upgrade) [#6625 @rjbou] + * Add 2.6 root test cases in opamroot-versions [#6625 @rjbou] ### Engine * Add `http-server` to launch a minimal http server [#6939 @rjbou] diff --git a/src/format/opamFile.ml b/src/format/opamFile.ml index 84145a1d67e..968996b305c 100644 --- a/src/format/opamFile.ml +++ b/src/format/opamFile.ml @@ -1415,7 +1415,7 @@ module ConfigSyntax = struct let internal = "config" let format_version = OpamVersion.of_string "2.1" let file_format_version = OpamVersion.of_string "2.0" - let root_version = OpamVersion.of_string "2.2" + let root_version = OpamVersion.of_string "2.6~alpha" let default_old_root_version = OpamVersion.of_string "2.1~~previous" diff --git a/src/state/opamFormatUpgrade.ml b/src/state/opamFormatUpgrade.ml index cacc5be7f7d..b6c3203b121 100644 --- a/src/state/opamFormatUpgrade.ml +++ b/src/state/opamFormatUpgrade.ml @@ -1152,6 +1152,56 @@ let v2_2 = OpamVersion.of_string "2.2" let from_2_2_beta_to_2_2 ~on_the_fly:_ _ conf = conf, gtc_none +let v2_6_alpha = OpamVersion.of_string "2.6~alpha" + +let from_2_2_to_2_6_alpha ~on_the_fly:_ root conf = + let repos = + OpamFile.Repos_config.safe_read (OpamPath.repos_config root) + in + OpamRepositoryName.Map.iter (fun name _ -> + let tgz = OpamRepositoryRoot.Tgz.Path.root root name in + if OpamRepositoryRoot.Tgz.exists tgz then + OpamFilename.with_tmp_dir @@ fun tmp_dir -> + OpamRepositoryRoot.Tgz.extract_in tgz tmp_dir; + match OpamSystem.get_files (OpamFilename.Dir.to_string tmp_dir) with + | [] | _::_::_ -> () + | [x] -> + OpamConsole.msg + "Upgrading the internal repository format for '%s'...\n" + (OpamRepositoryName.to_string name); + OpamTar.create ~flat:true + (OpamRepositoryRoot.Tgz.to_file tgz) + OpamFilename.Op.(tmp_dir / x)) + repos; + conf, gtc_none + +let cond_hard_upg_2_6_alpha root _conf = + let exception Found of bool in + let repos = + OpamFile.Repos_config.safe_read (OpamPath.repos_config root) + in + OpamRepositoryName.Map.exists (fun name _ -> + let tgz = OpamRepositoryRoot.Tgz.(to_file (Path.root root name)) in + OpamFilename.exists tgz + (* We need to check for a given archive that it is not the root of a + repository *) + && (try + OpamTar.fold_reg_files (fun _ rfile _ -> + let is_package = + Option.equal String.equal + (OpamFilename.Unix.root_dir rfile) + (Some OpamRepositoryPathName.packages_d) + in + let is_repo = + String.equal (OpamFilename.Unix.to_string rfile) + OpamRepositoryPathName.repo_f + in + raise (Found (is_package || is_repo))) + () tgz; + false + with Found is_repo_or_package_dir -> not is_repo_or_package_dir)) + repos + (* To add an upgrade layer * If it is a light upgrade, returns as second element if the repo or switch need an light upgrade with `gtc_*` values. @@ -1250,6 +1300,7 @@ let upgrades root_version root config = v2_2_alpha, from_2_1_to_2_2_alpha, None; v2_2_beta, from_2_2_alpha_to_2_2_beta, None; v2_2, from_2_2_beta_to_2_2, None; + v2_6_alpha, from_2_2_to_2_6_alpha, Some cond_hard_upg_2_6_alpha; ] in (* First we filter the unneeded upgrades *) diff --git a/tests/reftests/opamroot-versions.test b/tests/reftests/opamroot-versions.test index 5ea32665044..81f4f9bb571 100644 --- a/tests/reftests/opamroot-versions.test +++ b/tests/reftests/opamroot-versions.test @@ -3215,6 +3215,362 @@ i-am-sys-compiler 2 One-line description ### :V:8:a: From 2.2 root, global ### ocaml generate.ml 2.2 ### # ro global state +### opam option jobs | "${OPAMROOTVERSION}$" -> "current" +GSTATE LOAD-GLOBAL-STATE @ ${BASEDIR}/OPAM +FMT_UPG On-the-fly config upgrade, from 2.2 to current +FMT_UPG Format upgrade done +### # ro global state, ro repo state, ro switch state +### opam list | "${OPAMROOTVERSION}$" -> "current" +GSTATE LOAD-GLOBAL-STATE @ ${BASEDIR}/OPAM +FMT_UPG On-the-fly config upgrade, from 2.2 to current +FMT_UPG Format upgrade done +RSTATE LOAD-REPOSITORY-STATE @ ${BASEDIR}/OPAM +RSTATE No cache found +RSTATE loaded opam files from repo default in 0.000s +STATE LOAD-SWITCH-STATE @ sw-sys-comp +STATE Switch state loaded in 0.000s +# Packages matching: installed +# Name # Installed # Synopsis +i-am-another-package 2 One-line description +i-am-package 2 One-line description +i-am-sys-compiler 1 One-line description +### # ro global state, ro repo state, rw switch state +### opam install i-am-another-package --switch sw-comp | "${OPAMROOTVERSION}$" -> "current" +GSTATE LOAD-GLOBAL-STATE @ ${BASEDIR}/OPAM +FMT_UPG On-the-fly config upgrade, from 2.2 to current +FMT_UPG Format upgrade done +RSTATE LOAD-REPOSITORY-STATE @ ${BASEDIR}/OPAM +RSTATE Cache found +STATE LOAD-SWITCH-STATE @ sw-comp +STATE Switch state loaded in 0.000s +STATE Detected changed packages (marked for reinstall): {} +The following actions will be performed: +=== install 1 package + - install i-am-another-package 2 + +<><> Processing actions <><><><><><><><><><><><><><><><><><><><><><><><><><><><> +-> installed i-am-another-package.2 +STATE dependencies (0.000) result={ i-am-compiler.2 } +Done. +### # ro global state, rw repo state +### opam repo add root-config ./root-config | "${OPAMROOTVERSION}$" -> "current" +GSTATE LOAD-GLOBAL-STATE @ ${BASEDIR}/OPAM +FMT_UPG On-the-fly config upgrade, from 2.2 to current +FMT_UPG Format upgrade done +RSTATE LOAD-REPOSITORY-STATE @ ${BASEDIR}/OPAM +RSTATE Cache found +[root-config] Initialised +[NOTE] Repository root-config has been added to the selections of switch sw-sys-comp only. + Run `opam repository add root-config --all-switches|--set-default' to use it in all existing switches, or in newly created switches, respectively. + +### # rw global state +### opam option jobs=4 | "${OPAMROOTVERSION}($|,)" -> "current" +GSTATE LOAD-GLOBAL-STATE @ ${BASEDIR}/OPAM +[WARNING] Removing global switch 'this-internal-error' as it no longer exists +FMT_UPG Light config upgrade, from 2.2 to current +This version of opam requires an update to the layout of ${BASEDIR}/OPAM from version 2.2 to version current which can't be reverted. +You may want to back it up before going further. + +Continue? [Y/n] y +Format upgrade done. +Set to '4' the field jobs in global configuration +### opam-cat $OPAMROOT/config | '"${OPAMROOTVERSION}"' -> "current" | grep -v sys-pkg-manager-cmd | grep -v global-variables +default-compiler: ["i-am-sys-compiler" "i-am-compiler"] +default-invariant: ["i-am-sys-compiler"] +depext: true +depext-cannot-install: false +depext-run-installs: true +download-jobs: 1 +eval-variables: [sys-comp-version ["sh" "-c" "echo $OPAMSYSCOMP"] "comp version"] +installed-switches: ["sw-sys-comp" "sw-comp" "default"] +jobs: 4 +opam-root-version: current +opam-version: "2.0" +repositories: "default" +swh-fallback: false +switch: "sw-sys-comp" +### opam-cat $OPAMROOT/repo/repos-config +opam-version: "2.0" +repositories: ["default" {"file://${BASEDIR}/default"} "root-config" {"file://${BASEDIR}/root-config"}] +### opam-cat $OPAMROOT/sw-comp/.opam-switch/switch-config +invariant: ["i-am-compiler"] +opam-version: "2.0" +synopsis: "switch with compiler" +### opam-cat $OPAMROOT/sw-comp/.opam-switch/switch-state +compiler: ["i-am-compiler.2"] +installed: ["i-am-another-package.2" "i-am-compiler.2" "i-am-package.2"] +opam-version: "2.0" +roots: ["i-am-another-package.2" "i-am-compiler.2" "i-am-package.2"] +### :V:8:b: From 2.2 root, local +### ocaml generate.ml 2.2 local +### opam list | "${OPAMROOTVERSION}($|,)" -> "current" +GSTATE LOAD-GLOBAL-STATE @ ${BASEDIR}/OPAM +FMT_UPG On-the-fly config upgrade, from 2.2 to current +FMT_UPG Format upgrade done +RSTATE LOAD-REPOSITORY-STATE @ ${BASEDIR}/OPAM +RSTATE No cache found +RSTATE loaded opam files from repo default in 0.000s +STATE LOAD-SWITCH-STATE @ ${BASEDIR} +STATE Switch state loaded in 0.000s +# Packages matching: installed +# Name # Installed # Synopsis +i-am-sys-compiler 2 One-line description +### # ro global state, ro repo state, rw switch state +### opam install i-am-package | "${OPAMROOTVERSION}$" -> "current" +GSTATE LOAD-GLOBAL-STATE @ ${BASEDIR}/OPAM +FMT_UPG On-the-fly config upgrade, from 2.2 to current +FMT_UPG Format upgrade done +RSTATE LOAD-REPOSITORY-STATE @ ${BASEDIR}/OPAM +RSTATE Cache found +STATE LOAD-SWITCH-STATE @ ${BASEDIR} +STATE Definition missing for installed package i-am-sys-compiler.2, copying from repo +STATE Switch state loaded in 0.000s +STATE Detected changed packages (marked for reinstall): {} +The following actions will be performed: +=== install 1 package + - install i-am-package 2 + +<><> Processing actions <><><><><><><><><><><><><><><><><><><><><><><><><><><><> +-> installed i-am-package.2 +STATE dependencies (0.000) result={ i-am-sys-compiler.2 } +Done. +### # rw global state +### opam option jobs=4 | "${OPAMROOTVERSION}($|,)" -> "current" +GSTATE LOAD-GLOBAL-STATE @ ${BASEDIR}/OPAM +[WARNING] Removing global switch 'this-internal-error' as it no longer exists +FMT_UPG Light config upgrade, from 2.2 to current +This version of opam requires an update to the layout of ${BASEDIR}/OPAM from version 2.2 to version current which can't be reverted. +You may want to back it up before going further. + +Continue? [Y/n] y +Format upgrade done. +Set to '4' the field jobs in global configuration +### opam-cat $OPAMROOT/config | '"${OPAMROOTVERSION}"' -> "current" | grep -v sys-pkg-manager-cmd | grep -v global-variables +default-compiler: ["i-am-sys-compiler" "i-am-compiler"] +default-invariant: ["i-am-sys-compiler"] +depext: true +depext-cannot-install: false +depext-run-installs: true +download-jobs: 1 +eval-variables: [sys-comp-version ["sh" "-c" "echo $OPAMSYSCOMP"] "comp version"] +installed-switches: ["sw-sys-comp" "sw-comp" "${BASEDIR}" "default"] +jobs: 4 +opam-root-version: current +opam-version: "2.0" +repositories: "default" +swh-fallback: false +switch: "sw-sys-comp" +### opam-cat $OPAMROOT/repo/repos-config +opam-version: "2.0" +repositories: "default" {"file://${BASEDIR}/default"} +### opam-cat _opam/.opam-switch/switch-config +invariant: ["i-am-sys-compiler" | "i-am-compiler"] +opam-root: "${BASEDIR}/OPAM" +opam-version: "2.0" +synopsis: "local switch" +### opam-cat _opam/.opam-switch/switch-state +compiler: ["i-am-sys-compiler.2"] +installed: ["i-am-package.2" "i-am-sys-compiler.2"] +opam-version: "2.0" +roots: ["i-am-package.2" "i-am-sys-compiler.2"] +### :V:8:c: From 2.2 root, local unknown from config +### ocaml generate.ml 2.2 local +### opam list | "${OPAMROOTVERSION}($|,)" -> "current" +GSTATE LOAD-GLOBAL-STATE @ ${BASEDIR}/OPAM +FMT_UPG On-the-fly config upgrade, from 2.2 to current +FMT_UPG Format upgrade done +RSTATE LOAD-REPOSITORY-STATE @ ${BASEDIR}/OPAM +RSTATE No cache found +RSTATE loaded opam files from repo default in 0.000s +STATE LOAD-SWITCH-STATE @ ${BASEDIR} +STATE Switch state loaded in 0.000s +# Packages matching: installed +# Name # Installed # Synopsis +i-am-sys-compiler 2 One-line description +### # ro global state, ro repo state, rw switch state +### opam install i-am-package | "${OPAMROOTVERSION}($|,)" -> "current" +GSTATE LOAD-GLOBAL-STATE @ ${BASEDIR}/OPAM +FMT_UPG On-the-fly config upgrade, from 2.2 to current +FMT_UPG Format upgrade done +RSTATE LOAD-REPOSITORY-STATE @ ${BASEDIR}/OPAM +RSTATE Cache found +STATE LOAD-SWITCH-STATE @ ${BASEDIR} +STATE Switch state loaded in 0.000s +STATE Detected changed packages (marked for reinstall): {} +The following actions will be performed: +=== install 1 package + - install i-am-package 2 + +<><> Processing actions <><><><><><><><><><><><><><><><><><><><><><><><><><><><> +-> installed i-am-package.2 +STATE dependencies (0.000) result={ i-am-sys-compiler.2 } +Done. +### # rw global state +### opam option jobs=4 | "${OPAMROOTVERSION}($|,)" -> "current" +GSTATE LOAD-GLOBAL-STATE @ ${BASEDIR}/OPAM +[WARNING] Removing global switch 'this-internal-error' as it no longer exists +FMT_UPG Light config upgrade, from 2.2 to current +This version of opam requires an update to the layout of ${BASEDIR}/OPAM from version 2.2 to version current which can't be reverted. +You may want to back it up before going further. + +Continue? [Y/n] y +Format upgrade done. +Set to '4' the field jobs in global configuration +### opam-cat $OPAMROOT/config | '"${OPAMROOTVERSION}"' -> "current" | grep -v sys-pkg-manager-cmd | grep -v global-variables +default-compiler: ["i-am-sys-compiler" "i-am-compiler"] +default-invariant: ["i-am-sys-compiler"] +depext: true +depext-cannot-install: false +depext-run-installs: true +download-jobs: 1 +eval-variables: [sys-comp-version ["sh" "-c" "echo $OPAMSYSCOMP"] "comp version"] +installed-switches: ["sw-sys-comp" "sw-comp" "${BASEDIR}" "default"] +jobs: 4 +opam-root-version: current +opam-version: "2.0" +repositories: "default" +swh-fallback: false +switch: "sw-sys-comp" +### opam-cat $OPAMROOT/repo/repos-config +opam-version: "2.0" +repositories: "default" {"file://${BASEDIR}/default"} +### opam-cat _opam/.opam-switch/switch-config +invariant: ["i-am-sys-compiler" | "i-am-compiler"] +opam-root: "${BASEDIR}/OPAM" +opam-version: "2.0" +synopsis: "local switch" +### opam-cat _opam/.opam-switch/switch-state +compiler: ["i-am-sys-compiler.2"] +installed: ["i-am-package.2" "i-am-sys-compiler.2"] +opam-version: "2.0" +roots: ["i-am-package.2" "i-am-sys-compiler.2"] +### :V:8:d: Upgraded root and local 2.2 switch not recorded +### ocaml generate.ml 2.2 orphaned 2.2 +### # ro global state, ro repo state, ro switch state +### opam list | "${OPAMROOTVERSION}$" -> "current" +GSTATE LOAD-GLOBAL-STATE @ ${BASEDIR}/OPAM +FMT_UPG On-the-fly config upgrade, from 2.2 to current +FMT_UPG Format upgrade done +RSTATE LOAD-REPOSITORY-STATE @ ${BASEDIR}/OPAM +RSTATE No cache found +RSTATE loaded opam files from repo default in 0.000s +STATE LOAD-SWITCH-STATE @ ${BASEDIR} +STATE Switch state loaded in 0.000s +# Packages matching: installed +# Name # Installed # Synopsis +i-am-sys-compiler 2 One-line description +### # ro global state, ro repo state, rw switch state +### opam install i-am-package | "${OPAMROOTVERSION}$" -> "current" +GSTATE LOAD-GLOBAL-STATE @ ${BASEDIR}/OPAM +FMT_UPG On-the-fly config upgrade, from 2.2 to current +FMT_UPG Format upgrade done +RSTATE LOAD-REPOSITORY-STATE @ ${BASEDIR}/OPAM +RSTATE Cache found +STATE LOAD-SWITCH-STATE @ ${BASEDIR} +STATE Switch state loaded in 0.000s +STATE Detected changed packages (marked for reinstall): {} +The following actions will be performed: +=== install 1 package + - install i-am-package 2 + +<><> Processing actions <><><><><><><><><><><><><><><><><><><><><><><><><><><><> +-> installed i-am-package.2 +STATE dependencies (0.000) result={ i-am-sys-compiler.2 } +Done. +### # rw global state +### opam option jobs=4 | "${OPAMROOTVERSION}($|,)" -> "current" +GSTATE LOAD-GLOBAL-STATE @ ${BASEDIR}/OPAM +[WARNING] Removing global switch 'this-internal-error' as it no longer exists +FMT_UPG Light config upgrade, from 2.2 to current +This version of opam requires an update to the layout of ${BASEDIR}/OPAM from version 2.2 to version current which can't be reverted. +You may want to back it up before going further. + +Continue? [Y/n] y +Format upgrade done. +Set to '4' the field jobs in global configuration +### opam-cat $OPAMROOT/config | '"${OPAMROOTVERSION}"' -> "current" | grep -v sys-pkg-manager-cmd | grep -v global-variables +default-compiler: ["i-am-sys-compiler" "i-am-compiler"] +default-invariant: ["i-am-sys-compiler"] +depext: true +depext-cannot-install: false +depext-run-installs: true +download-jobs: 1 +eval-variables: [sys-comp-version ["sh" "-c" "echo $OPAMSYSCOMP"] "comp version"] +installed-switches: ["sw-sys-comp" "sw-comp" "default"] +jobs: 4 +opam-root-version: current +opam-version: "2.0" +repositories: "default" +swh-fallback: false +switch: "sw-sys-comp" +### opam-cat $OPAMROOT/repo/repos-config +opam-version: "2.0" +repositories: "default" {"file://${BASEDIR}/default"} +### opam-cat _opam/.opam-switch/switch-config +invariant: ["i-am-sys-compiler" | "i-am-compiler"] +opam-root: "${BASEDIR}/OPAM" +opam-version: "2.0" +synopsis: "local switch" +### opam-cat _opam/.opam-switch/switch-state +compiler: ["i-am-sys-compiler.2"] +installed: ["i-am-package.2" "i-am-sys-compiler.2"] +opam-version: "2.0" +roots: ["i-am-package.2" "i-am-sys-compiler.2"] +### :V:8:e: reinit from 2.2 +### ocaml generate.ml 2.2 +### opam init --reinit --bypass-checks --no-setup | "${OPAMROOTVERSION}($|,)" -> "current" | grep -v Cygwin +No configuration file found, using built-in defaults. +GSTATE LOAD-GLOBAL-STATE @ ${BASEDIR}/OPAM +[WARNING] Removing global switch 'this-internal-error' as it no longer exists +FMT_UPG Light config upgrade, from 2.2 to current +This version of opam requires an update to the layout of ${BASEDIR}/OPAM from version 2.2 to version current which can't be reverted. +You may want to back it up before going further. + +Continue? [Y/n] y +Format upgrade done. +RSTATE LOAD-REPOSITORY-STATE @ ${BASEDIR}/OPAM +RSTATE No cache found +RSTATE loaded opam files from repo default in 0.000s + +<><> Updating repositories ><><><><><><><><><><><><><><><><><><><><><><><><><><> +[default] no changes from file://${BASEDIR}/default +### opam-cat $OPAMROOT/config | '"${OPAMROOTVERSION}"' -> "current" | grep -v sys-pkg-manager-cmd | grep -v global-variables +default-compiler: ["i-am-sys-compiler" "i-am-compiler"] +default-invariant: ["i-am-sys-compiler"] +depext: true +depext-cannot-install: false +depext-run-installs: true +download-jobs: 3 +eval-variables: [sys-comp-version ["sh" "-c" "echo $OPAMSYSCOMP"] "comp version"] +installed-switches: ["sw-sys-comp" "sw-comp" "default"] +opam-root-version: current +opam-version: "2.0" +repositories: "default" +swh-fallback: false +switch: "sw-sys-comp" +wrap-build-commands: ["%{hooks}%/sandbox.sh" "build"] {os = "linux" | os = "macos"} +wrap-install-commands: ["%{hooks}%/sandbox.sh" "install"] {os = "linux" | os = "macos"} +wrap-remove-commands: ["%{hooks}%/sandbox.sh" "remove"] {os = "linux" | os = "macos"} +### opam switch --short +GSTATE LOAD-GLOBAL-STATE @ ${BASEDIR}/OPAM +${BASEDIR} +default +sw-comp +sw-sys-comp +### opam list +GSTATE LOAD-GLOBAL-STATE @ ${BASEDIR}/OPAM +RSTATE LOAD-REPOSITORY-STATE @ ${BASEDIR}/OPAM +RSTATE Cache found +STATE LOAD-SWITCH-STATE @ ${BASEDIR} +STATE Switch state loaded in 0.000s +# Packages matching: installed +# Name # Installed # Synopsis +i-am-package 2 One-line description +i-am-sys-compiler 2 One-line description +### rm -rf _opam +### :V:9:a: From 2.6~alpha root, global +### ocaml generate.ml 2.6~alpha +### # ro global state ### opam option jobs GSTATE LOAD-GLOBAL-STATE @ ${BASEDIR}/OPAM ### # ro global state, ro repo state, ro switch state @@ -3286,8 +3642,8 @@ compiler: ["i-am-compiler.2"] installed: ["i-am-another-package.2" "i-am-compiler.2" "i-am-package.2"] opam-version: "2.0" roots: ["i-am-another-package.2" "i-am-compiler.2" "i-am-package.2"] -### :V:8:b: From 2.2 root, local -### ocaml generate.ml 2.2 local +### :V:9:b: From 2.6~alpha root, local +### ocaml generate.ml 2.6~alpha local ### opam list | "${OPAMROOTVERSION}($|,)" -> "current" GSTATE LOAD-GLOBAL-STATE @ ${BASEDIR}/OPAM RSTATE LOAD-REPOSITORY-STATE @ ${BASEDIR}/OPAM @@ -3347,8 +3703,8 @@ compiler: ["i-am-sys-compiler.2"] installed: ["i-am-package.2" "i-am-sys-compiler.2"] opam-version: "2.0" roots: ["i-am-package.2" "i-am-sys-compiler.2"] -### :V:8:c: From 2.2 root, local unknown from config -### ocaml generate.ml 2.2 local +### :V:9:c: From 2.6~alpha root, local unknown from config +### ocaml generate.ml 2.6~alpha local ### opam list | "${OPAMROOTVERSION}($|,)" -> "current" GSTATE LOAD-GLOBAL-STATE @ ${BASEDIR}/OPAM RSTATE LOAD-REPOSITORY-STATE @ ${BASEDIR}/OPAM @@ -3407,8 +3763,8 @@ compiler: ["i-am-sys-compiler.2"] installed: ["i-am-package.2" "i-am-sys-compiler.2"] opam-version: "2.0" roots: ["i-am-package.2" "i-am-sys-compiler.2"] -### :V:8:d: Upgraded root and local 2.2 switch not recorded -### ocaml generate.ml 2.2 orphaned 2.2 +### :V:9:d: Upgraded root and local 2.6~alpha switch not recorded +### ocaml generate.ml 2.6~alpha orphaned 2.6~alpha ### # ro global state, ro repo state, ro switch state ### opam list GSTATE LOAD-GLOBAL-STATE @ ${BASEDIR}/OPAM @@ -3468,8 +3824,8 @@ compiler: ["i-am-sys-compiler.2"] installed: ["i-am-package.2" "i-am-sys-compiler.2"] opam-version: "2.0" roots: ["i-am-package.2" "i-am-sys-compiler.2"] -### :V:8:e: reinit from 2.2 -### ocaml generate.ml 2.2 +### :V:9:e: reinit from 2.6~alpha +### ocaml generate.ml 2.6~alpha ### opam init --reinit --bypass-checks --no-setup | grep -v Cygwin No configuration file found, using built-in defaults. GSTATE LOAD-GLOBAL-STATE @ ${BASEDIR}/OPAM From 7d3b6d21684269eee6a35c829c39e814d1efe729 Mon Sep 17 00:00:00 2001 From: Raja Boujbel Date: Fri, 3 Jul 2026 13:03:12 +0200 Subject: [PATCH 23/24] reftests: add repository test case that triggers opam root upgrade to 2.6 with OPAMREPOSITORYTARRING --- tests/reftests/repository.test | 139 +++++++++++++++++++++++++++++++++ 1 file changed, 139 insertions(+) diff --git a/tests/reftests/repository.test b/tests/reftests/repository.test index 5ed5d569088..ffd6d3ac505 100644 --- a/tests/reftests/repository.test +++ b/tests/reftests/repository.test @@ -1445,3 +1445,142 @@ RSTATE load repo changes from tgz # Return code 1 # ### test -f OPAM/repo/changes.tar.gz ### unset OPAMDEBUG OPAMDEBUGSECTIONS OPAMVERBOSE +### : :::::::::::::::::::::::: +### : change format from old tarred to the new one, trigger from repo state +### : the old format was present when using OPAMREPOTARRING=1 (>= 2.1 < 2.6) +### : or by default in opam 2.1 +### : :::::::::::::::::::::::: +### mkdir -p old-tarred/packages empty-repo/packages +### cp -R REPO/packages/foo old-tarred/packages/ +### cp REPO/repo old-tarred/ +### cp REPO/repo empty-repo/ +### tar czf old-tarred.tar.gz old-tarred +### rm -rf "$OPAMROOT" +### OPAMREPOSITORYTARRING=1 +### opam init --no-setup --bypass-checks --disable-sandbox --bare old-tarred ./old-tarred +No configuration file found, using built-in defaults. + +<><> Fetching repository information ><><><><><><><><><><><><><><><><><><><><><> +[old-tarred] Initialised +### opam switch create empty --empty +### sed -i.bak 's/opam-root-version.*/opam-root-version: "2.5.0"/' OPAM/config +### sh -c "rm OPAM/repo/*.cache" +### OPAMDEBUGSECTIONS="TAR FMT_UPG RSTATE" OPAMDEBUG=-5 OPAMYES=1 OPAMVERBOSE=2 +### head -2 OPAM/config +opam-version: "2.0" +opam-root-version: "2.5.0" +### cp old-tarred.tar.gz OPAM/repo/old-tarred.tar.gz +### tar tf OPAM/repo/old-tarred.tar.gz | grep repo +old-tarred/repo +### # We need to grep over SUCCESS because of sandbox re enabled on format upgrade reinit, see #6968 +### opam repo add empty-r ./empty-repo | sed-cmd tar | grep -v SUCCESS | grep -v 'cygpath\.exe' | grep -v 'cygwin' +FILE(config) Read ${BASEDIR}/OPAM/config in 0.000s +FMT_UPG Hard config upgrade, from 2.5.0 to 2.6~alpha +This version of opam requires an update to the layout of ${BASEDIR}/OPAM from version 2.5.0 to version 2.6~alpha, which can't be reverted. +You may want to back it up before going further. + +Perform the update and continue? [Y/n] y ++ tar "xfz" "${BASEDIR}/OPAM/repo/old-tarred.tar.gz" "-C" "${OPAMTMP}" +Upgrading the internal repository format for 'old-tarred'... +TAR creating archive ${BASEDIR}/OPAM/repo/old-tarred.tar.gz from ${OPAMTMP}/old-tarred +TAR Writing archive ${BASEDIR}/OPAM/repo/old-tarred.tar.gz +Format upgrade done. + +<><> Rerunning init and update ><><><><><><><><><><><><><><><><><><><><><><><><> +RSTATE LOAD-REPOSITORY-STATE @ ${BASEDIR}/OPAM +RSTATE No cache found +Processing: [old-tarred: loading data] +RSTATE load repo old-tarred from tgz +RSTATE read repo +RSTATE loaded opam files from repo old-tarred in 0.000s + +<><> Updating repositories ><><><><><><><><><><><><><><><><><><><><><><><><><><> +TAR creating archive ${BASEDIR}/OPAM/repo/old-tarred.tar.gz.new from ${BASEDIR}/old-tarred +TAR Writing archive ${BASEDIR}/OPAM/repo/old-tarred.tar.gz.new +[old-tarred] no changes from file://${BASEDIR}/old-tarred +Update done, please now retry your command. +# Return code 10 # +### tar tf OPAM/repo/old-tarred.tar.gz | grep repo +repo +### opam list --all-versions --available +FILE(config) Read ${BASEDIR}/OPAM/config in 0.000s +RSTATE LOAD-REPOSITORY-STATE @ ${BASEDIR}/OPAM +RSTATE Cache found +# Packages matching: available +# Package # Installed # Synopsis +foo.1 -- +foo.2 -- +foo.3 -- +foo.4 -- +foo.5 -- +foo.6 -- +### : change format from old tarred to the new one, trigger from global state +### rm -rf "$OPAMROOT" +### OPAMREPOSITORYTARRING=1 +### opam init --no-setup --bypass-checks --disable-sandbox --bare old-tarred ./old-tarred | grep -v 'cygpath\.exe' | grep -v 'cygwin' +No configuration file found, using built-in defaults. +RSTATE LOAD-REPOSITORY-STATE @ ${BASEDIR}/OPAM +RSTATE No cache found +Processing: [old-tarred: loading data] +RSTATE load repo old-tarred from dir +RSTATE loaded opam files from repo old-tarred in 0.000s + +<><> Fetching repository information ><><><><><><><><><><><><><><><><><><><><><> +TAR creating archive ${BASEDIR}/OPAM/repo/old-tarred.tar.gz.new from ${BASEDIR}/old-tarred +TAR Writing archive ${BASEDIR}/OPAM/repo/old-tarred.tar.gz.new +[old-tarred] Initialised +RSTATE load repo old-tarred from tgz +RSTATE read repo +### opam switch create empty --empty +FILE(config) Read ${BASEDIR}/OPAM/config in 0.000s +RSTATE LOAD-REPOSITORY-STATE @ ${BASEDIR}/OPAM +RSTATE Cache found +### sed -i.bak 's/opam-root-version.*/opam-root-version: "2.5.0"/' OPAM/config +### sh -c "rm OPAM/repo/*.cache" +### head -2 OPAM/config +opam-version: "2.0" +opam-root-version: "2.5.0" +### cp old-tarred.tar.gz OPAM/repo/old-tarred.tar.gz +### tar tf OPAM/repo/old-tarred.tar.gz | grep repo +old-tarred/repo +### opam update | sed-cmd tar | grep -v SUCCESS | grep -v 'cygpath\.exe' | grep -v 'cygwin' +FILE(config) Read ${BASEDIR}/OPAM/config in 0.000s +FMT_UPG Hard config upgrade, from 2.5.0 to 2.6~alpha +This version of opam requires an update to the layout of ${BASEDIR}/OPAM from version 2.5.0 to version 2.6~alpha, which can't be reverted. +You may want to back it up before going further. + +Perform the update and continue? [Y/n] y ++ tar "xfz" "${BASEDIR}/OPAM/repo/old-tarred.tar.gz" "-C" "${OPAMTMP}" +Upgrading the internal repository format for 'old-tarred'... +TAR creating archive ${BASEDIR}/OPAM/repo/old-tarred.tar.gz from ${OPAMTMP}/old-tarred +TAR Writing archive ${BASEDIR}/OPAM/repo/old-tarred.tar.gz +Format upgrade done. + +<><> Rerunning init and update ><><><><><><><><><><><><><><><><><><><><><><><><> +RSTATE LOAD-REPOSITORY-STATE @ ${BASEDIR}/OPAM +RSTATE No cache found +Processing: [old-tarred: loading data] +RSTATE load repo old-tarred from tgz +RSTATE read repo +RSTATE loaded opam files from repo old-tarred in 0.000s + +<><> Updating repositories ><><><><><><><><><><><><><><><><><><><><><><><><><><> +TAR creating archive ${BASEDIR}/OPAM/repo/old-tarred.tar.gz.new from ${BASEDIR}/old-tarred +TAR Writing archive ${BASEDIR}/OPAM/repo/old-tarred.tar.gz.new +[old-tarred] no changes from file://${BASEDIR}/old-tarred +Update done, please now retry your command. +# Return code 10 # +### tar tf OPAM/repo/old-tarred.tar.gz | grep repo +repo +### opam list --all-versions --available +FILE(config) Read ${BASEDIR}/OPAM/config in 0.000s +RSTATE LOAD-REPOSITORY-STATE @ ${BASEDIR}/OPAM +RSTATE Cache found +# Packages matching: available +# Package # Installed # Synopsis +foo.1 -- +foo.2 -- +foo.3 -- +foo.4 -- +foo.5 -- +foo.6 -- From 994bc698a3c3685e399da91db7486e569bfe3b26 Mon Sep 17 00:00:00 2001 From: Raja Boujbel Date: Mon, 8 Jun 2026 18:58:15 +0200 Subject: [PATCH 24/24] Add memoisation in repo root archive folding, to avoid opening twice a repository --- src/repository/opamRepositoryRoot.ml | 22 +++++++++++++++++++++- src/repository/opamRepositoryRoot.mli | 2 ++ src/state/opamRepositoryState.ml | 2 +- 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/src/repository/opamRepositoryRoot.ml b/src/repository/opamRepositoryRoot.ml index d3407724c8a..78feed669fa 100644 --- a/src/repository/opamRepositoryRoot.ml +++ b/src/repository/opamRepositoryRoot.ml @@ -75,7 +75,27 @@ module Tgz = struct let move = OpamFilename.move let is_symlink = OpamFilename.is_symlink - let fold = OpamTar.fold_reg_files + let archives : (OpamHash.t, string OpamFilename.Unix.Map.t) Hashtbl.t = Hashtbl.create 8 + let unload_repo_tars () = Hashtbl.clear archives + + let fold f x tar = + (* QUESTION : do we need to have a sha256 ? md5 have collision, will it + really happen irl ? *) + let hash = OpamHash.compute ~kind:`SHA256 (OpamFilename.to_string tar) in + match Hashtbl.find_opt archives hash with + | Some contents -> + OpamFilename.Unix.Map.fold (fun filename content acc -> + f acc filename content) + contents x + | None -> + let result, map = + OpamTar.fold_reg_files (fun (acc, map) file content -> + f acc file content, + OpamFilename.Unix.Map.add file content map) + (x, OpamFilename.Unix.Map.empty) tar + in + Hashtbl.add archives hash map; + result let patch ~allow_unclean patch_source tar = let patch_source = diff --git a/src/repository/opamRepositoryRoot.mli b/src/repository/opamRepositoryRoot.mli index 29c683b4ec8..5f458abcf82 100644 --- a/src/repository/opamRepositoryRoot.mli +++ b/src/repository/opamRepositoryRoot.mli @@ -84,6 +84,8 @@ module Tgz : sig val fold: ('a -> OpamTar.archived_file -> OpamTar.archived_file_content -> 'a) -> 'a -> t -> 'a + (* clean hashtbl that keep the repositories in ram *) + val unload_repo_tars: unit -> unit (* Repository paths *) module Path : OpamRepositoryPath.PATH diff --git a/src/state/opamRepositoryState.ml b/src/state/opamRepositoryState.ml index 9327ef90499..1a6166e80fc 100644 --- a/src/state/opamRepositoryState.ml +++ b/src/state/opamRepositoryState.ml @@ -549,7 +549,7 @@ let unlock ?cleanup:(cln=true) rt = let drop ?cleanup rt = let _ = unlock ?cleanup rt in - () + OpamRepositoryRoot.Tgz.unload_repo_tars () let with_write_lock ?dontblock rt f = if OpamStateConfig.is_newer_than_self ~lock_kind:`Lock_write rt.repos_global