#include "Core.h" String GetLocalDir() { return ConfigFile("UppLocal"); } String LocalPath(const String& filename) { return AppendFileName(GetLocalDir(), filename); } String FollowCygwinSymlink(const String& file) { for(String fn = file;;) { if(fn.IsEmpty()) return fn; FileIn fi(fn); if(!fi.IsOpen()) return fn; char buffer[10]; if(!fi.GetAll(buffer, 10) || memcmp(buffer, "!", 10)) return fn; fn = NormalizePath(LoadStream(fi), GetFileDirectory(fn)); } } Vector SplitDirs(const char *s) { #ifdef PLATFORM_POSIX return Split(s, [](int c) { return findarg(c, ';', ':') >= 0 ? c : 0; }); #else return Split(s, ';'); #endif } static String varsname = "default"; String GetVarsName() { return varsname; } String VarFilePath(String name) { return ConfigFile(name + ".var"); } String VarFilePath() { String p = varsname; if(IsFullPath(varsname)) return varsname; return VarFilePath(GetVarsName()); } bool SaveVarFile(const char *filename, const VectorMap& var) { FileOut out(filename); for(int i = 0; i < var.GetCount(); i++) out << var.GetKey(i) << " = " << AsCString(var[i]) << ";\n"; out.Close(); return !out.IsError(); } bool LoadVarFile(const char *name, VectorMap& _var) { try { VectorMap var; String env = LoadFile(name); try { CParser p(env); while(!p.IsEof()) { String v = p.ReadId(); p.Char('='); if(p.IsString()) var.GetAdd(v) = p.ReadString(); else { String ln; while(p.PeekChar() != '\r' && p.PeekChar() != '\n' && p.PeekChar() != ';') ln.Cat(p.GetChar()); var.GetAdd(v) = ln; p.Spaces(); } p.Char(';'); } } catch(CParser::Error) {} _var = pick(var); return true; } catch(...) { return false; } } bool Nest::Save(const char *path) { return SaveVarFile(path, var); } bool Nest::Load(const char *path) { InvalidatePackageCache(); return LoadVarFile(path, var); } String Nest::Get(const String& id) { return var.Get(id, String()); } void Nest::Set(const String& id, const String& val) { var.GetAdd(id) = val; InvalidatePackageCache(); } String Nest::PackagePath0(const String& name) { String uppfile = NativePath(name); if(IsFullPath(uppfile)) return NormalizePath(uppfile); Vector d = GetUppDirs(); String p; for(int i = 0; i < d.GetCount(); i++) { p = NormalizePath(AppendFileName(AppendFileName(d[i], uppfile), GetFileName(uppfile)) + ".upp"); if(FileExists(p)) return p; } return d.GetCount() ? NormalizePath(AppendFileName(AppendFileName(d[0], uppfile), GetFileName(uppfile)) + ".upp") : ""; } String Nest::PackagePath(const String& name) { int q = package_cache.Find(name); if(q < 0) { String h = PackagePath0(name); package_cache.Add(name, h); return h; } return package_cache[q]; } Nest& MainNest() { return Single(); } bool SaveVars(const char *name) { if(!MainNest().Save(VarFilePath(name))) return false; varsname = name; return true; } #ifdef PLATFORM_POSIX String GetDefaultUppOut() { String out; String p = GetExeFolder(); while(p.GetCount() > 1 && DirectoryExists(p)) { String h = AppendFileName(p, ".cache"); if(DirectoryExists(h)) { out = h; break; } p = GetFileFolder(p); } out = Nvl(out, GetHomeDirFile(".cache")) + "/upp.out"; RealizeDirectory(out); return out; } #else String GetDefaultUppOut() { return ConfigFile("out"); } #endif String GetUppOut() { return Nvl(GetVar("OUTPUT"), GetDefaultUppOut()); } String DefaultHubFilePath() { return ConfigFile("UppHub.path"); } bool hubdir_resolved; void SetHubDir(const String& path) { SaveChangedFile(DefaultHubFilePath(), path); hubdir_resolved = false; } static String override_hub_dir; void OverrideHubDir(const String& path) { override_hub_dir = path; } String GetHubDir() { if(override_hub_dir.GetCount()) return override_hub_dir; static String d; if(hubdir_resolved) return d; hubdir_resolved = true; d = GetVar("UPPHUB"); if(d.GetCount() == 0 || !DirectoryExists(d)) { d = LoadFile(DefaultHubFilePath()); if(d.GetCount() == 0 || !DirectoryExists(d)) { d = ConfigFile("UppHub"); RealizeDirectory(d); } } d = NormalizePath(d); return d; } bool InUppHub(const String& p) { return p.StartsWith(GetHubDir()); } bool LoadVars(const char *name) { varsname = (name && *name ? name : "default"); return MainNest().Load(VarFilePath()); } String GetVar(const String& var) { return MainNest().Get(var); } void SetVar(const String& var, const String& val, bool save) { MainNest().Set(var, val); if(save) SaveVars(GetVarsName()); } bool hub_loaded; String main_nest; void SetMainNest(const String& n) { main_nest = n; } String GetAssemblyId() { String id = GetVarsName(); Vector s = SplitDirs(GetVar("UPP")); if(s.GetCount() && main_nest.GetCount() && s[0] != main_nest) id << "_" << GetFileName(main_nest); return id; } Vector GetUppDirsRaw() { Vector s = SplitDirs(GetVar("UPP")); static Vector hub_dirs; if(!hub_loaded) { hub_dirs.Clear(); for(const FindFile& ff : FindFile(GetHubDir() + "/*.*")) if(ff.IsFolder()) hub_dirs.Add(ff.GetPath()); hub_loaded = true; } s.Append(hub_dirs); return s; } Vector GetUppDirs() { Vector s = GetUppDirsRaw(); if(main_nest.GetCount() && (s.GetCount() == 0 || main_nest != s[0])) s.Insert(0, main_nest); return s; } bool IsHubDir(const String& path) { return NormalizePath(path).StartsWith(GetHubDir()); } void Nest::InvalidatePackageCache() { package_cache.Clear(); hub_loaded = false; } String GetUppDir() { Vector s = GetUppDirs(); #ifdef PLATFORM_WIN32 return s.GetCount() == 0 ? GetFileFolder(GetExeFilePath()) : s[0]; #endif #ifdef PLATFORM_POSIX return s.GetCount() == 0 ? GetHomeDirectory() : s[0]; #endif }