123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190(**************************************************************************)(* *)(* Copyright 2012-2015 OCamlPro *)(* Copyright 2012 INRIA *)(* *)(* All rights reserved. This file is distributed under the terms of the *)(* GNU Lesser General Public License version 2.1, with the special *)(* exception on linking described in the file LICENSE. *)(* *)(**************************************************************************)openOpamTypesopenOpamStd.OpopenOpamFilename.OpopenOpamStateTypesletlogfmt=OpamConsole.log"GSTATE"fmtletslog=OpamConsole.slogletload_configglobal_lockroot=letconfig=matchOpamStateConfig.loadrootwith|Somec->c|None->ifOpamFilename.exists(root//"aliases")thenOpamFile.Config.(with_opam_version(OpamVersion.of_string"1.1")empty)elseOpamConsole.error_and_exit`Configuration_error"%s exists, but does not appear to be a valid opam root. Please \
remove it and use `opam init', or specify a different `--root' \
argument"(OpamFilename.Dir.to_stringroot)inOpamFormatUpgrade.as_necessaryglobal_lockrootconfig;configletinferred_from_system="Inferred from system"letloadlock_kind=letroot=OpamStateConfig.(!r.root_dir)inlog"LOAD-GLOBAL-STATE @ %a"(slogOpamFilename.Dir.to_string)root;(* Always take a global read lock, this is only used to prevent concurrent
~/.opam format changes *)lethas_root=OpamFilename.exists_dirrootinletglobal_lock=ifhas_rootthenOpamFilename.flock`Lock_read(OpamPath.lockroot)elseOpamSystem.lock_nonein(* The global_state lock actually concerns the global config file only (and
the consistence thereof with the repository and switch sets, and the
currently installed shell init scripts) *)ifnothas_rootthenOpamConsole.error_and_exit`Configuration_error"Opam has not been initialised, please run `opam init'";letconfig_lock=OpamFilename.flocklock_kind(OpamPath.config_lockroot)inletconfig=load_configglobal_lockrootinletswitches=List.filter(funsw->not(OpamSwitch.is_externalsw)||OpamFilename.exists_dir(OpamSwitch.get_rootrootsw))(OpamFile.Config.installed_switchesconfig)inletconfig=OpamFile.Config.with_installed_switchesswitchesconfiginletglobal_variables=List.fold_left(funacc(v,value)->OpamVariable.Map.addv(lazy(Some(OpamStd.Option.default(S"unknown")(Lazy.forcevalue))),(* Careful on changing it, it is used to determine user defined
variables on `config report`. See [OpamConfigCommand.help]. *)inferred_from_system)acc)OpamVariable.Map.empty(OpamSysPoll.variables)inletglobal_variables=List.fold_left(funacc(v,value,doc)->OpamVariable.Map.addv(lazy(Somevalue),doc)acc)global_variables(OpamFile.Config.global_variablesconfig)inleteval_variables=OpamFile.Config.eval_variablesconfiginletglobal_variables=letenv=lazy(OpamEnv.get_pure()|>OpamTypesBase.env_array)inList.fold_left(funacc(v,cmd,doc)->OpamVariable.Map.updatev(funprevious_value->(lazy(tryletret=OpamSystem.read_command_output~env:(Lazy.forceenv)~allow_stdin:falsecmdinSome(S(OpamStd.String.strip(String.concat"\n"ret)))withe->OpamStd.Exn.fatale;log"Failed to evaluate global variable %a: %a"(slogOpamVariable.to_string)v(slogPrintexc.to_string)e;Lazy.force(fstprevious_value))),doc)(lazyNone,"")acc)global_variableseval_variablesin{global_lock=config_lock;root;config;global_variables;}letswitchesgt=OpamFile.Config.installed_switchesgt.configletfold_switchesfgtacc=List.fold_left(funaccswitch->fswitch(OpamFile.SwitchSelections.safe_read(OpamPath.Switch.selectionsgt.rootswitch))acc)acc(OpamFile.Config.installed_switchesgt.config)letswitch_existsgtswitch=ifOpamSwitch.is_externalswitchthenOpamStateConfig.local_switch_existsgt.rootswitchelseList.memswitch(switchesgt)letall_installedgt=fold_switches(fun_selacc->OpamPackage.Set.unionaccsel.sel_installed)gtOpamPackage.Set.emptyletinstalled_versionsgtname=fold_switches(funswitchselacc->letinstalled=OpamPackage.packages_of_namesel.sel_installednameintryletnv=OpamPackage.Set.chooseinstalledintryOpamPackage.Map.addnv(switch::OpamPackage.Map.findnvacc)accwithNot_found->OpamPackage.Map.addnv[switch]accwithNot_found->acc)gtOpamPackage.Map.emptyletrepos_listgt=OpamFile.Config.repositoriesgt.configletunlockgt=OpamSystem.funlockgt.global_lock;(gt:>unlockedglobal_state)letwith_write_lock?dontblockgtf=letret,gt=OpamFilename.with_flock_upgrade`Lock_write?dontblockgt.global_lock@@fun_->f({gtwithglobal_lock=gt.global_lock}:rwglobal_state)(* We don't actually change the field value, but this makes restricting the
phantom lock type possible*)inret,{gtwithglobal_lock=gt.global_lock}letwith_lockf=letgt=loadlockintryletr=fgtinignore(unlockgt);rwithe->OpamStd.Exn.finalisee(fun()->ignore(unlockgt))letwritegt=OpamFile.Config.write(OpamPath.configgt.root)gt.configletfix_switch_listgt=letknown_switches0=switchesgtinletknown_switches=matchOpamStateConfig.get_switch_opt()with|None->known_switches0|Somesw->ifList.memswknown_switches0||not(switch_existsgtsw)thenknown_switches0elsesw::known_switches0inletknown_switches=List.filter(switch_existsgt)known_switchesinifknown_switches=known_switches0thengtelseletconfig=OpamFile.Config.with_installed_switchesknown_switchesgt.configinletgt={gtwithconfig}inifnotOpamCoreConfig.(!r.safe_mode)thentrysnd@@with_write_lock~dontblock:truegt@@fungt->writegt,gtwithOpamSystem.Locked->gtelsegt