Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Be more robust on repository format changes (#166)

* tell the user to upgrade opam when a newest version is available
* store in the repository a file containing the oldest client version which will be able to fetch it
  • Loading branch information...
commit 6e54186b21270d7db8ad3ba15271b3dc8daca0a2 1 parent 1dbe946
@samoht samoht authored
View
145 src/client.ml
@@ -1913,6 +1913,77 @@ let dry_upgrade () =
| Conflicts _ -> None
| Success sol -> Some (get_stats sol)
+let upgrade names =
+ log "upgrade %s" (N.Set.to_string names);
+ let t = update_available_current (load_state ()) in
+ let reinstall = NV.Set.inter t.reinstall t.installed in
+ let to_not_reinstall = ref NV.Set.empty in
+ let solution_found = ref No_solution in
+ if N.Set.is_empty names then (
+ let solution = Heuristic.resolve (`upgrade reinstall) t
+ (List.map (fun to_upgrade ->
+ { wish_install = [];
+ wish_remove = [];
+ wish_upgrade = N.Map.values (Heuristic.get_installed t to_upgrade) })
+ [ Heuristic.v_max; Heuristic.v_ge ]) in
+ solution_found := solution;
+ ) else (
+ let names = Heuristic.nv_of_names t names in
+ let partial_reinstall = NV.Set.of_list (List.map nv_of_version_constraint names) in
+ to_not_reinstall := NV.Set.diff reinstall partial_reinstall;
+ let solution = Heuristic.resolve (`upgrade partial_reinstall) t
+ (List.map (fun (to_upgrade, to_keep) ->
+ let wish_install = Heuristic.get_installed t to_keep in
+ let wish_install =
+ (* Remove the packages in [names] *)
+ N.Map.filter
+ (fun n _ -> List.for_all (fun vc -> name_of_version_constraint vc <> n) names)
+ wish_install in
+ let wish_install = N.Map.values wish_install in
+ let wish_upgrade = Heuristic.apply to_upgrade names in
+ { wish_install;
+ wish_remove = [];
+ wish_upgrade })
+ [ (Heuristic.v_max, Heuristic.v_eq);
+ (Heuristic.v_max, Heuristic.v_ge);
+ (Heuristic.v_max, Heuristic.v_any);
+ (Heuristic.v_ge , Heuristic.v_eq);
+ (Heuristic.v_ge , Heuristic.v_ge);
+ (Heuristic.v_ge , Heuristic.v_any); ]
+ ) in
+ solution_found := solution;
+ );
+ let t = load_state () in
+ begin match !solution_found with
+ | OK -> ()
+ | Nothing_to_do -> Globals.msg "Already up-to-date.\n"
+ | Aborted
+ | No_solution -> to_not_reinstall := reinstall
+ end;
+ let reinstall = NV.Set.inter t.installed !to_not_reinstall in
+ let reinstall_f = Path.C.reinstall t.compiler in
+ if NV.Set.is_empty reinstall then
+ Filename.remove reinstall_f
+ else
+ OpamFile.Reinstall.write reinstall_f reinstall
+
+let check_opam_version () =
+ let t = load_state () in
+ let n = N.of_string "opam" in
+ let current_version =
+ let v = match Run.read_command_output ["opam"; "--version"] with
+ | s::_ -> List.hd (List.rev (Utils.split s ' '))
+ | _ -> assert false in
+ V.of_string v in
+ let max_version = V.Set.max_elt (Path.G.available_versions t.global n) in
+ if V.compare max_version current_version > 0 then (
+ if confirm "Your version of opam (%s) is not up-to-date. Do you want to upgrade to version %s ?"
+ (V.to_string current_version)
+ (V.to_string max_version)
+ then
+ upgrade (N.Set.singleton n)
+ )
+
let update repos =
log "update %s" (String.concat " " repos);
let t = load_state () in
@@ -1933,13 +2004,19 @@ let update repos =
update_packages t ~show_packages:true repos;
);
match dry_upgrade () with
- | None -> Globals.msg "Already up-to-date.\n"
- | Some stats ->
- if sum stats > 0 then (
- print_stats stats;
- Globals.msg "You can now run 'opam upgrade' to upgrade your system.\n"
- ) else
- Globals.msg "Already up-to-date.\n"
+ | None -> Globals.msg "Already up-to-date.\n"
+ | Some _ ->
+ check_opam_version ();
+ (* we re-run dry_upgrade, as some packages might have been
+ upgraded by the precedent function *)
+ match dry_upgrade () with
+ | None -> Globals.msg "Already up-to-date.\n"
+ | Some stats ->
+ if sum stats > 0 then (
+ print_stats stats;
+ Globals.msg "You can now run 'opam upgrade' to upgrade your system.\n"
+ ) else
+ Globals.msg "Already up-to-date.\n"
let init repo ocaml_version cores =
log "init %s" (Repository.to_string repo);
@@ -2159,60 +2236,6 @@ let remove names =
; Heuristic.v_any ]) in
())
-let upgrade names =
- log "upgrade %s" (N.Set.to_string names);
- let t = update_available_current (load_state ()) in
- let reinstall = NV.Set.inter t.reinstall t.installed in
- let to_not_reinstall = ref NV.Set.empty in
- let solution_found = ref No_solution in
- if N.Set.is_empty names then (
- let solution = Heuristic.resolve (`upgrade reinstall) t
- (List.map (fun to_upgrade ->
- { wish_install = [];
- wish_remove = [];
- wish_upgrade = N.Map.values (Heuristic.get_installed t to_upgrade) })
- [ Heuristic.v_max; Heuristic.v_ge ]) in
- solution_found := solution;
- ) else (
- let names = Heuristic.nv_of_names t names in
- let partial_reinstall = NV.Set.of_list (List.map nv_of_version_constraint names) in
- to_not_reinstall := NV.Set.diff reinstall partial_reinstall;
- let solution = Heuristic.resolve (`upgrade partial_reinstall) t
- (List.map (fun (to_upgrade, to_keep) ->
- let wish_install = Heuristic.get_installed t to_keep in
- let wish_install =
- (* Remove the packages in [names] *)
- N.Map.filter
- (fun n _ -> List.for_all (fun vc -> name_of_version_constraint vc <> n) names)
- wish_install in
- let wish_install = N.Map.values wish_install in
- let wish_upgrade = Heuristic.apply to_upgrade names in
- { wish_install;
- wish_remove = [];
- wish_upgrade })
- [ (Heuristic.v_max, Heuristic.v_eq);
- (Heuristic.v_max, Heuristic.v_ge);
- (Heuristic.v_max, Heuristic.v_any);
- (Heuristic.v_ge , Heuristic.v_eq);
- (Heuristic.v_ge , Heuristic.v_ge);
- (Heuristic.v_ge , Heuristic.v_any); ]
- ) in
- solution_found := solution;
- );
- let t = load_state () in
- begin match !solution_found with
- | OK -> ()
- | Nothing_to_do -> Globals.msg "Already up-to-date.\n"
- | Aborted
- | No_solution -> to_not_reinstall := reinstall
- end;
- let reinstall = NV.Set.inter t.installed !to_not_reinstall in
- let reinstall_f = Path.C.reinstall t.compiler in
- if NV.Set.is_empty reinstall then
- Filename.remove reinstall_f
- else
- OpamFile.Reinstall.write reinstall_f reinstall
-
let reinstall names =
log "reinstall %s" (N.Set.to_string names);
let t = update_available_current (load_state ()) in
View
2  src/globals.ml.in
@@ -112,7 +112,7 @@ let makecmd = ref (match os with FreeBSD | OpenBSD -> "gmake" | _ -> "make") (*
let default_cores = 1
-let version () =
+let version_msg () =
Printf.printf "\
%s version %s
View
2  src/opam.ml
@@ -41,7 +41,7 @@ let global_args = [
"--debug" , Arg.Set Globals.debug , " Print internal debug messages (very verbose)";
"--verbose" , Arg.Set Globals.verbose , " Display the output of subprocesses";
"--quiet" , Arg.Clear quiet , " Do not display the output of subprocesses";
- "--version" , Arg.Unit Globals.version, " Display version information";
+ "--version" , Arg.Unit Globals.version_msg, " Display version information";
"--yes" , Arg.Set Globals.yes , " Answer yes to all questions";
"--makecmd" , Arg.Set_string Globals.makecmd,
Printf.sprintf " Set the 'make' program used when compiling packages (default is %s)" !Globals.makecmd;
View
2  src/path.ml
@@ -164,6 +164,8 @@ module R = struct
let root t = t
+ let version t = t // "version"
+
let config t = t // "config"
let packages_dir t = t / "packages"
View
3  src/path.mli
@@ -189,6 +189,9 @@ module R: sig
(** Return the repository folder: {i $opam/repo/$repo} *)
val root: t -> dirname
+ (** Return the version file *)
+ val version: t -> filename
+
(** Return the repository config: {i $opam/repo/$repo/config} *)
val config: t -> filename
View
1  src/repo/rsync.ml
@@ -102,6 +102,7 @@ module B = struct
let updates = Filename.Set.of_list archives
++ sync_dir Path.R.packages_dir
++ sync_dir Path.R.compilers_dir in
+ ignore (rsync_file (Path.R.version remote_repo) (Path.R.version local_repo));
updates
let upload_dir ~address local_dir =
View
11 src/repositories.ml
@@ -245,12 +245,23 @@ let download r nv =
(NV.to_string nv);
Dirname.in_dir local_dir (fun () -> make_archive nv)
+let check_version repo =
+ let repo_version =
+ try V.of_string (Raw.to_string (Filename.read (Path.R.version repo)))
+ with e -> V.of_string "0.7.5" in
+ if V.compare repo_version (V.of_string Globals.version) >= 0 then
+ Globals.error_and_exit
+ "\nThe current version of OPAM cannot read the repository. \
+ You should upgrade to at least the version %s.\n" (V.to_string repo_version)
+
let update r =
log "update %s" (Repository.to_string r);
let local_repo = Path.R.create r in
let local_dir = Path.R.root local_repo in
let module B = (val find_backend r: BACKEND) in
let updated_files = Dirname.in_dir local_dir (fun () -> B.update (Repository.address r)) in
+
+ check_version local_repo;
let updated_packages = nv_set_of_files updated_files in
(* Clean-up archives and tmp files on URL changes *)
View
2  src/scripts/opam_check.ml
@@ -8,7 +8,7 @@ let label = ref ""
let spec = Arg.align [
("--root", Arg.Set_string Globals.root_path, " Set opam path");
("-l" , Arg.Set_string label , " Set a test label");
- ("--version", Arg.Unit Globals.version , " Display version information");
+ ("--version", Arg.Unit Globals.version_msg , " Display version information");
]
let packages = ref []
View
4 src/scripts/opam_mk_repo.ml
@@ -35,8 +35,8 @@ let all, index, packages, gener_digest, dryrun, recurse =
let dryrun = ref false in
let recurse = ref false in
let specs = Arg.align [
- ("-v" , Arg.Unit Globals.version, " Display version information");
- ("--version", Arg.Unit Globals.version, " Display version information");
+ ("-v" , Arg.Unit Globals.version_msg, " Display version information");
+ ("--version", Arg.Unit Globals.version_msg, " Display version information");
("-a" , Arg.Set all, "");
("--all", Arg.Set all , Printf.sprintf " Build all package archives (default is %b)" !all);
View
2  src/scripts/opam_repo_check.ml
@@ -6,7 +6,7 @@ open OpamFile
let () =
let usage = Printf.sprintf "Usage: %s" Sys.argv.(0) in
let specs = [
- ("--version", Arg.Unit Globals.version, " Display version information")
+ ("--version", Arg.Unit Globals.version_msg, " Display version information")
] in
let ano x =
Printf.eprintf "%s: invalid argument" x in
Please sign in to comment.
Something went wrong with that request. Please try again.