mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-08 11:38:21 +02:00
Initial package management support
This commit is contained in:
parent
78138f5c5a
commit
4870c6fdd8
19 changed files with 2520 additions and 205 deletions
|
@ -10,12 +10,22 @@ namespace BeefBuild
|
||||||
{
|
{
|
||||||
class BuildApp : IDEApp
|
class BuildApp : IDEApp
|
||||||
{
|
{
|
||||||
|
public enum MainVerbState
|
||||||
|
{
|
||||||
|
None,
|
||||||
|
UpdateList,
|
||||||
|
End
|
||||||
|
}
|
||||||
|
|
||||||
const int cProgressSize = 30;
|
const int cProgressSize = 30;
|
||||||
int mProgressIdx = 0;
|
int mProgressIdx = 0;
|
||||||
public bool mIsTest;
|
public bool mIsTest;
|
||||||
public bool mTestIncludeIgnored;
|
public bool mTestIncludeIgnored;
|
||||||
public bool mDidRun;
|
public bool mDidRun;
|
||||||
public bool mWantsGenerate = false;
|
public bool mWantsGenerate = false;
|
||||||
|
public bool mHandledVerb;
|
||||||
|
public String mRunArgs ~ delete _;
|
||||||
|
MainVerbState mMainVerbState;
|
||||||
|
|
||||||
/*void Test()
|
/*void Test()
|
||||||
{
|
{
|
||||||
|
@ -112,20 +122,33 @@ namespace BeefBuild
|
||||||
OutputErrorLine("The project '{}' is not empty, but '-generate' was specified.", mWorkspace.mStartupProject.mProjectName);
|
OutputErrorLine("The project '{}' is not empty, but '-generate' was specified.", mWorkspace.mStartupProject.mProjectName);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!mFailed)
|
|
||||||
{
|
|
||||||
if (mIsTest)
|
|
||||||
{
|
|
||||||
RunTests(mTestIncludeIgnored, false);
|
|
||||||
}
|
|
||||||
else if (mVerb != .New)
|
|
||||||
Compile(.Normal, null);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override bool HandleCommandLineParam(String key, String value)
|
public override bool HandleCommandLineParam(String key, String value)
|
||||||
{
|
{
|
||||||
|
if (mRunArgs != null)
|
||||||
|
{
|
||||||
|
if (!mRunArgs.IsEmpty)
|
||||||
|
mRunArgs.Append(" ");
|
||||||
|
if (value != null)
|
||||||
|
{
|
||||||
|
String qKey = scope .(key);
|
||||||
|
String qValue = scope .(value);
|
||||||
|
IDEApp.QuoteIfNeeded(qKey);
|
||||||
|
IDEApp.QuoteIfNeeded(qValue);
|
||||||
|
mRunArgs.Append(qKey);
|
||||||
|
mRunArgs.Append('=');
|
||||||
|
mRunArgs.Append(qValue);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
String qKey = scope .(key);
|
||||||
|
IDEApp.QuoteIfNeeded(qKey);
|
||||||
|
mRunArgs.Append(qKey);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if (key.StartsWith("--"))
|
if (key.StartsWith("--"))
|
||||||
key.Remove(0, 1);
|
key.Remove(0, 1);
|
||||||
|
|
||||||
|
@ -133,6 +156,10 @@ namespace BeefBuild
|
||||||
{
|
{
|
||||||
switch (key)
|
switch (key)
|
||||||
{
|
{
|
||||||
|
case "-args":
|
||||||
|
if (mRunArgs == null)
|
||||||
|
mRunArgs = new .();
|
||||||
|
return true;
|
||||||
case "-new":
|
case "-new":
|
||||||
mVerb = .New;
|
mVerb = .New;
|
||||||
return true;
|
return true;
|
||||||
|
@ -157,12 +184,63 @@ namespace BeefBuild
|
||||||
case "-noir":
|
case "-noir":
|
||||||
mConfig_NoIR = true;
|
mConfig_NoIR = true;
|
||||||
return true;
|
return true;
|
||||||
|
case "-update":
|
||||||
|
if (mWantUpdateVersionLocks == null)
|
||||||
|
mWantUpdateVersionLocks = new .();
|
||||||
|
return true;
|
||||||
case "-version":
|
case "-version":
|
||||||
mVerb = .GetVersion;
|
mVerb = .GetVersion;
|
||||||
return true;
|
return true;
|
||||||
case "-crash":
|
case "-crash":
|
||||||
Runtime.FatalError("-crash specified on command line");
|
Runtime.FatalError("-crash specified on command line");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!key.StartsWith('-'))
|
||||||
|
{
|
||||||
|
switch (mMainVerbState)
|
||||||
|
{
|
||||||
|
case .None:
|
||||||
|
mMainVerbState = .End;
|
||||||
|
switch (key)
|
||||||
|
{
|
||||||
|
case "build":
|
||||||
|
mVerb = .None;
|
||||||
|
case "new":
|
||||||
|
mVerb = .New;
|
||||||
|
case "generate":
|
||||||
|
mWantsGenerate = true;
|
||||||
|
case "run":
|
||||||
|
if (mVerbosity == .Default)
|
||||||
|
mVerbosity = .Minimal;
|
||||||
|
mVerb = .Run;
|
||||||
|
case "test":
|
||||||
|
mIsTest = true;
|
||||||
|
case "testall":
|
||||||
|
mIsTest = true;
|
||||||
|
mTestIncludeIgnored = true;
|
||||||
|
case "clean":
|
||||||
|
mWantsClean = true;
|
||||||
|
case "version":
|
||||||
|
mVerb = .GetVersion;
|
||||||
|
case "crash":
|
||||||
|
Runtime.FatalError("-crash specified on command line");
|
||||||
|
case "update":
|
||||||
|
mVerb = .Update;
|
||||||
|
mWantUpdateVersionLocks = new .();
|
||||||
|
mMainVerbState = .UpdateList;
|
||||||
|
default:
|
||||||
|
mMainVerbState = .None;
|
||||||
|
}
|
||||||
|
if (mMainVerbState != .None)
|
||||||
|
return true;
|
||||||
|
case .UpdateList:
|
||||||
|
mWantUpdateVersionLocks.Add(new .(key));
|
||||||
|
return true;
|
||||||
|
case .End:
|
||||||
|
return false;
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -188,6 +266,11 @@ namespace BeefBuild
|
||||||
case "-platform":
|
case "-platform":
|
||||||
mPlatformName.Set(value);
|
mPlatformName.Set(value);
|
||||||
return true;
|
return true;
|
||||||
|
case "-update":
|
||||||
|
if (mWantUpdateVersionLocks == null)
|
||||||
|
mWantUpdateVersionLocks = new .();
|
||||||
|
mWantUpdateVersionLocks.Add(new .(value));
|
||||||
|
return true;
|
||||||
case "-verbosity":
|
case "-verbosity":
|
||||||
if (value == "quiet")
|
if (value == "quiet")
|
||||||
mVerbosity = .Quiet;
|
mVerbosity = .Quiet;
|
||||||
|
@ -281,33 +364,55 @@ namespace BeefBuild
|
||||||
{
|
{
|
||||||
base.Update(batchStart);
|
base.Update(batchStart);
|
||||||
|
|
||||||
if (mCompilingBeef)
|
if (mWorkspace.mProjectLoadState != .Loaded)
|
||||||
{
|
{
|
||||||
WriteProgress(mBfBuildCompiler.GetCompletionPercentage());
|
// Wait for workspace to complete loading
|
||||||
}
|
}
|
||||||
|
else
|
||||||
if ((!IsCompiling) && (!AreTestsRunning()))
|
|
||||||
{
|
{
|
||||||
if ((mVerb == .Run) && (!mDidRun) && (!mFailed))
|
if ((!mFailed) && (!mHandledVerb))
|
||||||
{
|
{
|
||||||
let curPath = scope String();
|
mHandledVerb = true;
|
||||||
Directory.GetCurrentDirectory(curPath);
|
if (mIsTest)
|
||||||
|
{
|
||||||
let workspaceOptions = gApp.GetCurWorkspaceOptions();
|
RunTests(mTestIncludeIgnored, false);
|
||||||
let options = gApp.GetCurProjectOptions(mWorkspace.mStartupProject);
|
}
|
||||||
let targetPaths = scope List<String>();
|
else if (mVerb == .Update)
|
||||||
defer ClearAndDeleteItems(targetPaths);
|
{
|
||||||
this.[Friend]GetTargetPaths(mWorkspace.mStartupProject, gApp.mPlatformName, workspaceOptions, options, targetPaths);
|
// No-op here
|
||||||
if (targetPaths.IsEmpty)
|
}
|
||||||
return;
|
else if (mVerb != .New)
|
||||||
|
Compile(.Normal, null);
|
||||||
ExecutionQueueCmd executionCmd = QueueRun(targetPaths[0], "", curPath);
|
|
||||||
executionCmd.mIsTargetRun = true;
|
|
||||||
mDidRun = true;
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Stop();
|
if (mCompilingBeef)
|
||||||
|
{
|
||||||
|
WriteProgress(mBfBuildCompiler.GetCompletionPercentage());
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((!IsCompiling) && (!AreTestsRunning()))
|
||||||
|
{
|
||||||
|
if ((mVerb == .Run) && (!mDidRun) && (!mFailed))
|
||||||
|
{
|
||||||
|
let curPath = scope String();
|
||||||
|
Directory.GetCurrentDirectory(curPath);
|
||||||
|
|
||||||
|
let workspaceOptions = gApp.GetCurWorkspaceOptions();
|
||||||
|
let options = gApp.GetCurProjectOptions(mWorkspace.mStartupProject);
|
||||||
|
let targetPaths = scope List<String>();
|
||||||
|
defer ClearAndDeleteItems(targetPaths);
|
||||||
|
this.[Friend]GetTargetPaths(mWorkspace.mStartupProject, gApp.mPlatformName, workspaceOptions, options, targetPaths);
|
||||||
|
if (targetPaths.IsEmpty)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ExecutionQueueCmd executionCmd = QueueRun(targetPaths[0], mRunArgs ?? "", curPath);
|
||||||
|
executionCmd.mIsTargetRun = true;
|
||||||
|
mDidRun = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Stop();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -123,6 +123,7 @@ namespace IDE
|
||||||
List<String> mConfigPathQueue = new List<String>() ~ DeleteContainerAndItems!(_);
|
List<String> mConfigPathQueue = new List<String>() ~ DeleteContainerAndItems!(_);
|
||||||
List<LibDirectory> mLibDirectories = new List<LibDirectory>() ~ DeleteContainerAndItems!(_);
|
List<LibDirectory> mLibDirectories = new List<LibDirectory>() ~ DeleteContainerAndItems!(_);
|
||||||
List<FileSystemWatcher> mWatchers = new .() ~ DeleteContainerAndItems!(_);
|
List<FileSystemWatcher> mWatchers = new .() ~ DeleteContainerAndItems!(_);
|
||||||
|
public String mManagedLibPath = new .() ~ delete _;
|
||||||
public bool mLibsChanged;
|
public bool mLibsChanged;
|
||||||
|
|
||||||
void LibsChanged()
|
void LibsChanged()
|
||||||
|
@ -221,6 +222,15 @@ namespace IDE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
data.GetString("ManagedLibDir", mManagedLibPath);
|
||||||
|
if ((mManagedLibPath.IsEmpty) && (!mLibDirectories.IsEmpty))
|
||||||
|
{
|
||||||
|
var libPath = Path.GetAbsolutePath(mLibDirectories[0].mPath, gApp.mInstallDir, .. scope .());
|
||||||
|
var managedPath = Path.GetAbsolutePath("../BeefManaged", libPath, .. scope .());
|
||||||
|
if (Directory.Exists(managedPath))
|
||||||
|
mManagedLibPath.Set(managedPath);
|
||||||
|
}
|
||||||
|
|
||||||
mConfigFiles.Add(configFile);
|
mConfigFiles.Add(configFile);
|
||||||
|
|
||||||
return .Ok;
|
return .Ok;
|
||||||
|
|
|
@ -76,6 +76,7 @@ namespace IDE
|
||||||
OpenOrNew,
|
OpenOrNew,
|
||||||
Test,
|
Test,
|
||||||
Run,
|
Run,
|
||||||
|
Update,
|
||||||
GetVersion
|
GetVersion
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -182,6 +183,7 @@ namespace IDE
|
||||||
public MainFrame mMainFrame;
|
public MainFrame mMainFrame;
|
||||||
public GlobalUndoManager mGlobalUndoManager = new GlobalUndoManager() ~ delete _;
|
public GlobalUndoManager mGlobalUndoManager = new GlobalUndoManager() ~ delete _;
|
||||||
public SourceControl mSourceControl = new SourceControl() ~ delete _;
|
public SourceControl mSourceControl = new SourceControl() ~ delete _;
|
||||||
|
public GitManager mGitManager = new .() ~ delete _;
|
||||||
|
|
||||||
public WidgetWindow mPopupWindow;
|
public WidgetWindow mPopupWindow;
|
||||||
public RecentFileSelector mRecentFileSelector;
|
public RecentFileSelector mRecentFileSelector;
|
||||||
|
@ -223,6 +225,7 @@ namespace IDE
|
||||||
public WakaTime mWakaTime ~ delete _;
|
public WakaTime mWakaTime ~ delete _;
|
||||||
|
|
||||||
public PackMan mPackMan = new PackMan() ~ delete _;
|
public PackMan mPackMan = new PackMan() ~ delete _;
|
||||||
|
public HashSet<String> mWantUpdateVersionLocks ~ DeleteContainerAndItems!(_);
|
||||||
public Settings mSettings = new Settings() ~ delete _;
|
public Settings mSettings = new Settings() ~ delete _;
|
||||||
public Workspace mWorkspace = new Workspace() ~ delete _;
|
public Workspace mWorkspace = new Workspace() ~ delete _;
|
||||||
public FileWatcher mFileWatcher = new FileWatcher() ~ delete _;
|
public FileWatcher mFileWatcher = new FileWatcher() ~ delete _;
|
||||||
|
@ -2145,6 +2148,91 @@ namespace IDE
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SaveWorkspaceLockData(bool force = false)
|
||||||
|
{
|
||||||
|
if ((mWorkspace.mProjectLockMap.IsEmpty) && (!force))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
StructuredData sd = scope StructuredData();
|
||||||
|
sd.CreateNew();
|
||||||
|
sd.Add("FileVersion", 1);
|
||||||
|
using (sd.CreateObject("Locks"))
|
||||||
|
{
|
||||||
|
List<String> projectNames = scope .(mWorkspace.mProjectLockMap.Keys);
|
||||||
|
projectNames.Sort();
|
||||||
|
|
||||||
|
for (var projectName in projectNames)
|
||||||
|
{
|
||||||
|
var lock = mWorkspace.mProjectLockMap[projectName];
|
||||||
|
switch (lock)
|
||||||
|
{
|
||||||
|
case .Git(let url, let tag, let hash):
|
||||||
|
using (sd.CreateObject(projectName))
|
||||||
|
{
|
||||||
|
using (sd.CreateObject("Git"))
|
||||||
|
{
|
||||||
|
sd.Add("URL", url);
|
||||||
|
sd.Add("Tag", tag);
|
||||||
|
sd.Add("Hash", hash);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String jsonString = scope String();
|
||||||
|
sd.ToTOML(jsonString);
|
||||||
|
|
||||||
|
String lockFileName = scope String();
|
||||||
|
GetWorkspaceLockFileName(lockFileName);
|
||||||
|
if (lockFileName.IsEmpty)
|
||||||
|
return false;
|
||||||
|
return SafeWriteTextFile(lockFileName, jsonString);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LoadWorkspaceLockData()
|
||||||
|
{
|
||||||
|
String lockFilePath = scope String();
|
||||||
|
GetWorkspaceLockFileName(lockFilePath);
|
||||||
|
if (lockFilePath.IsEmpty)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
var sd = scope StructuredData();
|
||||||
|
if (sd.Load(lockFilePath) case .Err)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (var projectName in sd.Enumerate("Locks"))
|
||||||
|
{
|
||||||
|
Workspace.Lock lock = default;
|
||||||
|
if (sd.Contains("Git"))
|
||||||
|
{
|
||||||
|
using (sd.Open("Git"))
|
||||||
|
{
|
||||||
|
var url = sd.GetString("URL", .. new .());
|
||||||
|
var tag = sd.GetString("Tag", .. new .());
|
||||||
|
var hash = sd.GetString("Hash", .. new .());
|
||||||
|
lock = .Git(url, tag, hash);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mWorkspace.SetLock(projectName, lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GetWorkspaceLockFileName(String outResult)
|
||||||
|
{
|
||||||
|
if (mWorkspace.mDir == null)
|
||||||
|
return false;
|
||||||
|
if (mWorkspace.mCompositeFile != null)
|
||||||
|
outResult.Append(mWorkspace.mCompositeFile.mFilePath, ".bfuser");
|
||||||
|
else
|
||||||
|
outResult.Append(mWorkspace.mDir, "/BeefSpace_Lock.toml");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void GetDefaultLayoutDataFileName(String outResult)
|
void GetDefaultLayoutDataFileName(String outResult)
|
||||||
{
|
{
|
||||||
outResult.Append(mInstallDir, "/DefaultLayout.toml");
|
outResult.Append(mInstallDir, "/DefaultLayout.toml");
|
||||||
|
@ -2377,6 +2465,17 @@ namespace IDE
|
||||||
project.mDependencies.Add(dep);
|
project.mDependencies.Add(dep);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void ProjectCreated(Project project)
|
||||||
|
{
|
||||||
|
mProjectPanel.InitProject(project, mProjectPanel.GetSelectedWorkspaceFolder());
|
||||||
|
mProjectPanel.Sort();
|
||||||
|
mWorkspace.FixOptions();
|
||||||
|
mWorkspace.mHasChanged = true;
|
||||||
|
|
||||||
|
mWorkspace.ClearProjectNameCache();
|
||||||
|
CurrentWorkspaceConfigChanged();
|
||||||
|
}
|
||||||
|
|
||||||
public Project CreateProject(String projName, String projDir, Project.TargetType targetType)
|
public Project CreateProject(String projName, String projDir, Project.TargetType targetType)
|
||||||
{
|
{
|
||||||
Project project = new Project();
|
Project project = new Project();
|
||||||
|
@ -2391,13 +2490,8 @@ namespace IDE
|
||||||
AddNewProjectToWorkspace(project);
|
AddNewProjectToWorkspace(project);
|
||||||
project.FinishCreate();
|
project.FinishCreate();
|
||||||
|
|
||||||
mProjectPanel.InitProject(project, mProjectPanel.GetSelectedWorkspaceFolder());
|
ProjectCreated(project);
|
||||||
mProjectPanel.Sort();
|
|
||||||
mWorkspace.FixOptions();
|
|
||||||
mWorkspace.mHasChanged = true;
|
|
||||||
|
|
||||||
mWorkspace.ClearProjectNameCache();
|
|
||||||
CurrentWorkspaceConfigChanged();
|
|
||||||
return project;
|
return project;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2517,6 +2611,8 @@ namespace IDE
|
||||||
|
|
||||||
mBookmarkManager.Clear();
|
mBookmarkManager.Clear();
|
||||||
|
|
||||||
|
mPackMan.CancelAll();
|
||||||
|
|
||||||
OutputLine("Workspace closed.");
|
OutputLine("Workspace closed.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2757,9 +2853,16 @@ namespace IDE
|
||||||
return .Err;
|
return .Err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void CheckDependenciesLoaded()
|
||||||
|
{
|
||||||
|
for (var project in mWorkspace.mProjects)
|
||||||
|
project.CheckDependenciesLoaded();
|
||||||
|
}
|
||||||
|
|
||||||
void FlushDeferredLoadProjects(bool addToUI = false)
|
void FlushDeferredLoadProjects(bool addToUI = false)
|
||||||
{
|
{
|
||||||
bool hasDeferredProjects = false;
|
bool hasDeferredProjects = false;
|
||||||
|
bool loadFailed = false;
|
||||||
|
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
|
@ -2767,11 +2870,29 @@ namespace IDE
|
||||||
for (int projectIdx = 0; projectIdx < mWorkspace.mProjects.Count; projectIdx++)
|
for (int projectIdx = 0; projectIdx < mWorkspace.mProjects.Count; projectIdx++)
|
||||||
{
|
{
|
||||||
var project = mWorkspace.mProjects[projectIdx];
|
var project = mWorkspace.mProjects[projectIdx];
|
||||||
|
|
||||||
|
if (project.mDeferState == .Searching)
|
||||||
|
{
|
||||||
|
if (mPackMan.mFailed)
|
||||||
|
{
|
||||||
|
// Just let it fail now
|
||||||
|
LoadFailed();
|
||||||
|
project.mDeferState = .None;
|
||||||
|
project.mFailed = true;
|
||||||
|
loadFailed = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
hasDeferredProjects = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if ((project.mDeferState == .ReadyToLoad) || (project.mDeferState == .Pending))
|
if ((project.mDeferState == .ReadyToLoad) || (project.mDeferState == .Pending))
|
||||||
{
|
{
|
||||||
hadLoad = true;
|
hadLoad = true;
|
||||||
|
|
||||||
var projectPath = project.mProjectPath;
|
var projectPath = project.mProjectPath;
|
||||||
|
|
||||||
if (project.mDeferState == .Pending)
|
if (project.mDeferState == .Pending)
|
||||||
{
|
{
|
||||||
hasDeferredProjects = true;
|
hasDeferredProjects = true;
|
||||||
|
@ -2794,9 +2915,26 @@ namespace IDE
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasDeferredProjects)
|
if (hasDeferredProjects)
|
||||||
|
{
|
||||||
mWorkspace.mProjectLoadState = .Preparing;
|
mWorkspace.mProjectLoadState = .Preparing;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
mWorkspace.mProjectLoadState = .Loaded;
|
mWorkspace.mProjectLoadState = .Loaded;
|
||||||
|
SaveWorkspaceLockData();
|
||||||
|
CheckDependenciesLoaded();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (loadFailed)
|
||||||
|
{
|
||||||
|
mProjectPanel.RebuildUI();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CancelWorkspaceLoading()
|
||||||
|
{
|
||||||
|
mPackMan.CancelAll();
|
||||||
|
FlushDeferredLoadProjects();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void LoadWorkspace(BeefVerb verb)
|
protected void LoadWorkspace(BeefVerb verb)
|
||||||
|
@ -2937,6 +3075,7 @@ namespace IDE
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
LoadWorkspaceLockData();
|
||||||
mWorkspace.mProjectFileEntries.Add(new .(workspaceFileName));
|
mWorkspace.mProjectFileEntries.Add(new .(workspaceFileName));
|
||||||
|
|
||||||
if (mVerb == .New)
|
if (mVerb == .New)
|
||||||
|
@ -3044,9 +3183,10 @@ namespace IDE
|
||||||
outRelaunchCmd.Append(" -safe");
|
outRelaunchCmd.Append(" -safe");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RetryProjectLoad(Project project)
|
public void RetryProjectLoad(Project project, bool reloadConfig)
|
||||||
{
|
{
|
||||||
LoadConfig();
|
if (reloadConfig)
|
||||||
|
LoadConfig();
|
||||||
|
|
||||||
var projectPath = project.mProjectPath;
|
var projectPath = project.mProjectPath;
|
||||||
if (!project.Load(projectPath))
|
if (!project.Load(projectPath))
|
||||||
|
@ -3054,6 +3194,8 @@ namespace IDE
|
||||||
Fail(scope String()..AppendF("Failed to load project '{0}' from '{1}'", project.mProjectName, projectPath));
|
Fail(scope String()..AppendF("Failed to load project '{0}' from '{1}'", project.mProjectName, projectPath));
|
||||||
LoadFailed();
|
LoadFailed();
|
||||||
project.mFailed = true;
|
project.mFailed = true;
|
||||||
|
FlushDeferredLoadProjects();
|
||||||
|
mProjectPanel?.RebuildUI();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -3061,7 +3203,7 @@ namespace IDE
|
||||||
mWorkspace.FixOptions();
|
mWorkspace.FixOptions();
|
||||||
|
|
||||||
project.mFailed = false;
|
project.mFailed = false;
|
||||||
mProjectPanel.RebuildUI();
|
mProjectPanel?.RebuildUI();
|
||||||
CurrentWorkspaceConfigChanged();
|
CurrentWorkspaceConfigChanged();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3080,7 +3222,17 @@ namespace IDE
|
||||||
String verConfigDir = mWorkspace.mDir;
|
String verConfigDir = mWorkspace.mDir;
|
||||||
|
|
||||||
if (let project = mWorkspace.FindProject(projectName))
|
if (let project = mWorkspace.FindProject(projectName))
|
||||||
|
{
|
||||||
|
switch (useVerSpec)
|
||||||
|
{
|
||||||
|
case .Git(let url, let ver):
|
||||||
|
if (ver != null)
|
||||||
|
mPackMan.UpdateGitConstraint(url, ver);
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
|
||||||
return project;
|
return project;
|
||||||
|
}
|
||||||
|
|
||||||
if (useVerSpec case .SemVer)
|
if (useVerSpec case .SemVer)
|
||||||
{
|
{
|
||||||
|
@ -3153,27 +3305,24 @@ namespace IDE
|
||||||
case .SemVer(let semVer):
|
case .SemVer(let semVer):
|
||||||
//
|
//
|
||||||
case .Git(let url, let ver):
|
case .Git(let url, let ver):
|
||||||
var verReference = new Project.VerReference();
|
|
||||||
verReference.mSrcProjectName = new String(projectName);
|
|
||||||
verReference.mVerSpec = _.Duplicate();
|
|
||||||
project.mVerReferences.Add(verReference);
|
|
||||||
|
|
||||||
var checkPath = scope String();
|
var checkPath = scope String();
|
||||||
if (mPackMan.CheckLock(projectName, checkPath))
|
if (mPackMan.CheckLock(projectName, checkPath))
|
||||||
{
|
{
|
||||||
projectFilePath = scope:: String(checkPath);
|
projectFilePath = scope:: String(checkPath);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
mPackMan.GetWithVersion(projectName, url, ver);
|
||||||
isDeferredLoad = true;
|
isDeferredLoad = true;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
Fail("Invalid version specifier");
|
Fail("Invalid version specifier");
|
||||||
return .Err(.InvalidVersionSpec);
|
return .Err(.InvalidVersionSpec);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((projectFilePath == null) && (!isDeferredLoad))
|
if ((projectFilePath == null) && (!isDeferredLoad))
|
||||||
{
|
|
||||||
return .Err(.NotFound);
|
return .Err(.NotFound);
|
||||||
}
|
|
||||||
|
|
||||||
if (isDeferredLoad)
|
if (isDeferredLoad)
|
||||||
{
|
{
|
||||||
|
@ -3197,6 +3346,59 @@ namespace IDE
|
||||||
return .Ok(project);
|
return .Ok(project);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void UpdateProjectVersionLocks(params Span<StringView> projectNames)
|
||||||
|
{
|
||||||
|
bool removedLock = false;
|
||||||
|
|
||||||
|
for (var projectName in projectNames)
|
||||||
|
{
|
||||||
|
if (var kv = gApp.mWorkspace.mProjectLockMap.GetAndRemoveAlt(projectName))
|
||||||
|
{
|
||||||
|
removedLock = true;
|
||||||
|
delete kv.key;
|
||||||
|
kv.value.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (removedLock)
|
||||||
|
{
|
||||||
|
if (SaveAll())
|
||||||
|
{
|
||||||
|
SaveWorkspaceLockData(true);
|
||||||
|
CloseOldBeefManaged();
|
||||||
|
ReloadWorkspace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateProjectVersionLocks(Span<String> projectNames)
|
||||||
|
{
|
||||||
|
List<StringView> svNames = scope .();
|
||||||
|
for (var name in projectNames)
|
||||||
|
svNames.Add(name);
|
||||||
|
UpdateProjectVersionLocks(params (Span<StringView>)svNames);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void NotifyProjectVersionLocks(Span<String> projectNames)
|
||||||
|
{
|
||||||
|
if (projectNames.IsEmpty)
|
||||||
|
return;
|
||||||
|
|
||||||
|
String message = scope .();
|
||||||
|
message.Append((projectNames.Length == 1) ? "Project " : "Projects ");
|
||||||
|
for (var projectName in projectNames)
|
||||||
|
{
|
||||||
|
if (@projectName.Index > 0)
|
||||||
|
message.Append(", ");
|
||||||
|
message.AppendF($"'{projectName}'");
|
||||||
|
}
|
||||||
|
|
||||||
|
message.Append((projectNames.Length == 1) ? " has " : " have ");
|
||||||
|
|
||||||
|
message.AppendF("modified version constraints. Use 'Update Version Lock' in the project or workspace right-click menus to apply the new constraints.");
|
||||||
|
MessageDialog("Version Constraints Modified", message, DarkTheme.sDarkTheme.mIconWarning);
|
||||||
|
}
|
||||||
|
|
||||||
protected void WorkspaceLoaded()
|
protected void WorkspaceLoaded()
|
||||||
{
|
{
|
||||||
scope AutoBeefPerf("IDE.WorkspaceLoaded");
|
scope AutoBeefPerf("IDE.WorkspaceLoaded");
|
||||||
|
@ -3848,9 +4050,9 @@ namespace IDE
|
||||||
return dialog;
|
return dialog;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void MessageDialog(String title, String text)
|
public void MessageDialog(String title, String text, Image icon = null)
|
||||||
{
|
{
|
||||||
Dialog dialog = ThemeFactory.mDefault.CreateDialog(title, text);
|
Dialog dialog = ThemeFactory.mDefault.CreateDialog(title, text, icon);
|
||||||
dialog.mDefaultButton = dialog.AddButton("OK");
|
dialog.mDefaultButton = dialog.AddButton("OK");
|
||||||
dialog.mEscButton = dialog.mDefaultButton;
|
dialog.mEscButton = dialog.mDefaultButton;
|
||||||
dialog.PopupWindow(mMainWindow);
|
dialog.PopupWindow(mMainWindow);
|
||||||
|
@ -7433,6 +7635,37 @@ namespace IDE
|
||||||
CloseDocument(activeDocumentPanel);
|
CloseDocument(activeDocumentPanel);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void CloseOldBeefManaged()
|
||||||
|
{
|
||||||
|
List<SourceViewPanel> pendingClosePanels = scope .();
|
||||||
|
WithSourceViewPanels(scope (sourceViewPanel) =>
|
||||||
|
{
|
||||||
|
if (sourceViewPanel.mProjectSource != null)
|
||||||
|
{
|
||||||
|
var checkHash = gApp.mPackMan.GetHashFromFilePath(sourceViewPanel.mFilePath, .. scope .());
|
||||||
|
if (!checkHash.IsEmpty)
|
||||||
|
{
|
||||||
|
bool foundHash = false;
|
||||||
|
|
||||||
|
if (gApp.mWorkspace.mProjectLockMap.TryGet(sourceViewPanel.mProjectSource.mProject.mProjectName, ?, var lock))
|
||||||
|
{
|
||||||
|
if (lock case .Git(let url, let tag, let hash))
|
||||||
|
{
|
||||||
|
if (hash == checkHash)
|
||||||
|
foundHash = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!foundHash)
|
||||||
|
pendingClosePanels.Add(sourceViewPanel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
for (var sourceViewPanel in pendingClosePanels)
|
||||||
|
CloseDocument(sourceViewPanel);
|
||||||
|
}
|
||||||
|
|
||||||
public SourceViewPanel ShowProjectItem(ProjectItem projectItem, bool showTemp = true, bool setFocus = true)
|
public SourceViewPanel ShowProjectItem(ProjectItem projectItem, bool showTemp = true, bool setFocus = true)
|
||||||
{
|
{
|
||||||
if (projectItem is ProjectSource)
|
if (projectItem is ProjectSource)
|
||||||
|
@ -7845,7 +8078,7 @@ namespace IDE
|
||||||
case "-autoshutdown":
|
case "-autoshutdown":
|
||||||
mDebugAutoShutdownCounter = 200;
|
mDebugAutoShutdownCounter = 200;
|
||||||
case "-new":
|
case "-new":
|
||||||
mVerb = .New;
|
mVerb = .Open;
|
||||||
case "-testNoExit":
|
case "-testNoExit":
|
||||||
mExitWhenTestScriptDone = false;
|
mExitWhenTestScriptDone = false;
|
||||||
case "-firstRun":
|
case "-firstRun":
|
||||||
|
@ -8090,15 +8323,16 @@ namespace IDE
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void OutputErrorLine(String format, params Object[] args)
|
public virtual void OutputErrorLine(StringView format, params Object[] args)
|
||||||
{
|
{
|
||||||
mWantShowOutput = true;
|
mWantShowOutput = true;
|
||||||
var errStr = scope String();
|
var errStr = scope String();
|
||||||
errStr.Append("ERROR: ", format);
|
errStr.Append("ERROR: ");
|
||||||
|
errStr.Append(format);
|
||||||
OutputLineSmart(errStr, params args);
|
OutputLineSmart(errStr, params args);
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void OutputWarnLine(String format, params Object[] args)
|
public virtual void OutputWarnLine(StringView format, params Object[] args)
|
||||||
{
|
{
|
||||||
var warnStr = scope String();
|
var warnStr = scope String();
|
||||||
warnStr.AppendF(format, params args);
|
warnStr.AppendF(format, params args);
|
||||||
|
@ -8113,7 +8347,7 @@ namespace IDE
|
||||||
OutputLine(outStr);
|
OutputLine(outStr);
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void OutputLineSmart(String format, params Object[] args)
|
public virtual void OutputLineSmart(StringView format, params Object[] args)
|
||||||
{
|
{
|
||||||
String outStr;
|
String outStr;
|
||||||
if (args.Count > 0)
|
if (args.Count > 0)
|
||||||
|
@ -10027,7 +10261,7 @@ namespace IDE
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
mWorkspace.ClearProjectNameCache();
|
mWorkspace.ClearProjectNameCache();
|
||||||
mProjectPanel.RehupProjects();
|
mProjectPanel?.RehupProjects();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*public string GetClangDepConfigName(Project project)
|
/*public string GetClangDepConfigName(Project project)
|
||||||
|
@ -10064,8 +10298,8 @@ namespace IDE
|
||||||
RemoveProjectItems(project);
|
RemoveProjectItems(project);
|
||||||
}
|
}
|
||||||
|
|
||||||
mBfResolveCompiler.QueueDeferredResolveAll();
|
mBfResolveCompiler?.QueueDeferredResolveAll();
|
||||||
mBfResolveCompiler.QueueRefreshViewCommand(.FullRefresh);
|
mBfResolveCompiler?.QueueRefreshViewCommand(.FullRefresh);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10093,11 +10327,14 @@ namespace IDE
|
||||||
{
|
{
|
||||||
mWantsBeefClean = true;
|
mWantsBeefClean = true;
|
||||||
|
|
||||||
|
var checkDeclName = (project.mProjectName !== project.mProjectNameDecl) && (mWorkspace.FindProject(project.mProjectNameDecl) == project);
|
||||||
|
|
||||||
for (var checkProject in mWorkspace.mProjects)
|
for (var checkProject in mWorkspace.mProjects)
|
||||||
{
|
{
|
||||||
for (var dep in checkProject.mDependencies)
|
for (var dep in checkProject.mDependencies)
|
||||||
{
|
{
|
||||||
if (dep.mProjectName == project.mProjectName)
|
if ((dep.mProjectName == project.mProjectName) ||
|
||||||
|
((checkDeclName) && (dep.mProjectName == project.mProjectNameDecl)))
|
||||||
{
|
{
|
||||||
dep.mProjectName.Set(newName);
|
dep.mProjectName.Set(newName);
|
||||||
checkProject.SetChanged();
|
checkProject.SetChanged();
|
||||||
|
@ -10115,14 +10352,27 @@ namespace IDE
|
||||||
}
|
}
|
||||||
|
|
||||||
project.mProjectName.Set(newName);
|
project.mProjectName.Set(newName);
|
||||||
|
if (project.mProjectNameDecl != project.mProjectName)
|
||||||
|
delete project.mProjectNameDecl;
|
||||||
|
project.mProjectNameDecl = project.mProjectName;
|
||||||
project.SetChanged();
|
project.SetChanged();
|
||||||
mWorkspace.ClearProjectNameCache();
|
mWorkspace.ClearProjectNameCache();
|
||||||
|
|
||||||
|
mProjectPanel.RebuildUI();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void RemoveProject(Project project)
|
public void RemoveProject(Project project)
|
||||||
{
|
{
|
||||||
RemoveProjectItems(project);
|
RemoveProjectItems(project);
|
||||||
|
|
||||||
|
if (mWorkspace.mProjectLockMap.GetAndRemove(project.mProjectName) case .Ok(let kv))
|
||||||
|
{
|
||||||
|
delete kv.key;
|
||||||
|
kv.value.Dispose();
|
||||||
|
if (mWorkspace.mProjectLockMap.IsEmpty)
|
||||||
|
SaveWorkspaceLockData(true);
|
||||||
|
}
|
||||||
|
|
||||||
project.mDeleted = true;
|
project.mDeleted = true;
|
||||||
mWorkspace.SetChanged();
|
mWorkspace.SetChanged();
|
||||||
mWorkspace.mProjects.Remove(project);
|
mWorkspace.mProjects.Remove(project);
|
||||||
|
@ -10911,7 +11161,7 @@ namespace IDE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void QuoteIfNeeded(String str)
|
protected static void QuoteIfNeeded(String str)
|
||||||
{
|
{
|
||||||
if (!str.Contains(' '))
|
if (!str.Contains(' '))
|
||||||
return;
|
return;
|
||||||
|
@ -12398,6 +12648,8 @@ namespace IDE
|
||||||
base.Init();
|
base.Init();
|
||||||
mSettings.Apply();
|
mSettings.Apply();
|
||||||
|
|
||||||
|
mGitManager.Init();
|
||||||
|
|
||||||
//Yoop();
|
//Yoop();
|
||||||
|
|
||||||
/*for (int i = 0; i < 100*1024*1024; i++)
|
/*for (int i = 0; i < 100*1024*1024; i++)
|
||||||
|
@ -14865,6 +15117,8 @@ namespace IDE
|
||||||
if (mLongUpdateProfileId != 0)
|
if (mLongUpdateProfileId != 0)
|
||||||
DoLongUpdateCheck();
|
DoLongUpdateCheck();
|
||||||
|
|
||||||
|
mGitManager.Update();
|
||||||
|
mPackMan.Update();
|
||||||
if (mWakaTime != null)
|
if (mWakaTime != null)
|
||||||
mWakaTime.Update();
|
mWakaTime.Update();
|
||||||
if (mFindResultsPanel != null)
|
if (mFindResultsPanel != null)
|
||||||
|
@ -15053,7 +15307,6 @@ namespace IDE
|
||||||
[Import("user32.lib"), CLink, CallingConvention(.Stdcall)]
|
[Import("user32.lib"), CLink, CallingConvention(.Stdcall)]
|
||||||
public static extern bool MessageBeep(MessageBeepType type);
|
public static extern bool MessageBeep(MessageBeepType type);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
|
|
|
@ -9,6 +9,7 @@ using Beefy;
|
||||||
using Beefy.gfx;
|
using Beefy.gfx;
|
||||||
using Beefy.theme.dark;
|
using Beefy.theme.dark;
|
||||||
using IDE.ui;
|
using IDE.ui;
|
||||||
|
using System.Diagnostics;
|
||||||
|
|
||||||
namespace IDE
|
namespace IDE
|
||||||
{
|
{
|
||||||
|
@ -128,6 +129,29 @@ namespace IDE
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void SafeKill(int processId)
|
||||||
|
{
|
||||||
|
var beefConExe = scope $"{gApp.mInstallDir}/BeefCon.exe";
|
||||||
|
|
||||||
|
ProcessStartInfo procInfo = scope ProcessStartInfo();
|
||||||
|
procInfo.UseShellExecute = false;
|
||||||
|
procInfo.SetFileName(beefConExe);
|
||||||
|
procInfo.SetArguments(scope $"{processId} kill");
|
||||||
|
procInfo.ActivateWindow = false;
|
||||||
|
|
||||||
|
var process = scope SpawnedProcess();
|
||||||
|
process.Start(procInfo).IgnoreError();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void SafeKill(SpawnedProcess process)
|
||||||
|
{
|
||||||
|
if (process.WaitFor(0))
|
||||||
|
return;
|
||||||
|
SafeKill(process.ProcessId);
|
||||||
|
if (!process.WaitFor(2000))
|
||||||
|
process.Kill();
|
||||||
|
}
|
||||||
|
|
||||||
public static bool IsDirectoryEmpty(StringView dirPath)
|
public static bool IsDirectoryEmpty(StringView dirPath)
|
||||||
{
|
{
|
||||||
for (let entry in Directory.Enumerate(scope String()..AppendF("{}/*.*", dirPath), .Directories | .Files))
|
for (let entry in Directory.Enumerate(scope String()..AppendF("{}/*.*", dirPath), .Directories | .Files))
|
||||||
|
|
|
@ -1091,9 +1091,13 @@ namespace IDE
|
||||||
public class GeneralOptions
|
public class GeneralOptions
|
||||||
{
|
{
|
||||||
[Reflect]
|
[Reflect]
|
||||||
|
public String mProjectNameDecl; // Points to mProjectNameDecl in Project
|
||||||
|
[Reflect]
|
||||||
public TargetType mTargetType;
|
public TargetType mTargetType;
|
||||||
[Reflect]
|
[Reflect]
|
||||||
public List<String> mAliases = new .() ~ DeleteContainerAndItems!(_);
|
public List<String> mAliases = new .() ~ DeleteContainerAndItems!(_);
|
||||||
|
[Reflect]
|
||||||
|
public SemVer mVersion = new SemVer("") ~ delete _;
|
||||||
}
|
}
|
||||||
|
|
||||||
public class BeefGlobalOptions
|
public class BeefGlobalOptions
|
||||||
|
@ -1321,6 +1325,7 @@ namespace IDE
|
||||||
{
|
{
|
||||||
public VerSpec mVerSpec ~ _.Dispose();
|
public VerSpec mVerSpec ~ _.Dispose();
|
||||||
public String mProjectName ~ delete _;
|
public String mProjectName ~ delete _;
|
||||||
|
public bool mDependencyChecked;
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum DeferState
|
public enum DeferState
|
||||||
|
@ -1337,13 +1342,20 @@ namespace IDE
|
||||||
public VerSpec mVerSpec ~ _.Dispose();
|
public VerSpec mVerSpec ~ _.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class ManagedInfo
|
||||||
|
{
|
||||||
|
public SemVer mVersion = new .("") ~ delete _;
|
||||||
|
public String mInfo ~ delete _;
|
||||||
|
}
|
||||||
|
|
||||||
public Monitor mMonitor = new Monitor() ~ delete _;
|
public Monitor mMonitor = new Monitor() ~ delete _;
|
||||||
public String mNamespace = new String() ~ delete _;
|
public String mNamespace = new String() ~ delete _;
|
||||||
public String mProjectDir = new String() ~ delete _;
|
public String mProjectDir = new String() ~ delete _;
|
||||||
public String mProjectName = new String() ~ delete _;
|
public String mProjectName = new String() ~ delete _;
|
||||||
|
public String mProjectNameDecl = mProjectName ~ { if (mProjectNameDecl != mProjectName) delete _; }
|
||||||
public String mProjectPath = new String() ~ delete _;
|
public String mProjectPath = new String() ~ delete _;
|
||||||
|
public ManagedInfo mManagedInfo ~ delete _;
|
||||||
public DeferState mDeferState;
|
public DeferState mDeferState;
|
||||||
public List<VerReference> mVerReferences = new .() ~ DeleteContainerAndItems!(_);
|
|
||||||
|
|
||||||
//public String mLastImportDir = new String() ~ delete _;
|
//public String mLastImportDir = new String() ~ delete _;
|
||||||
public bool mHasChanged;
|
public bool mHasChanged;
|
||||||
|
@ -1410,6 +1422,16 @@ namespace IDE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public SemVer Version
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (mManagedInfo != null)
|
||||||
|
return mManagedInfo.mVersion;
|
||||||
|
return mGeneralOptions.mVersion;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void SetupDefaultOptions(Options options)
|
void SetupDefaultOptions(Options options)
|
||||||
{
|
{
|
||||||
options.mBuildOptions.mOtherLinkFlags.Set("$(LinkFlags)");
|
options.mBuildOptions.mOtherLinkFlags.Set("$(LinkFlags)");
|
||||||
|
@ -1443,6 +1465,7 @@ namespace IDE
|
||||||
mGeneralOptions.mTargetType = .CustomBuild;
|
mGeneralOptions.mTargetType = .CustomBuild;
|
||||||
SetupDefaultConfigs();
|
SetupDefaultConfigs();
|
||||||
|
|
||||||
|
mGeneralOptions.mProjectNameDecl = mProjectNameDecl;
|
||||||
mBeefGlobalOptions.mStartupObject.Set("Program");
|
mBeefGlobalOptions.mStartupObject.Set("Program");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1526,6 +1549,21 @@ namespace IDE
|
||||||
Path.GetDirectoryPath(mProjectPath, mProjectDir);
|
Path.GetDirectoryPath(mProjectPath, mProjectDir);
|
||||||
if (structuredData.Load(ProjectFileName) case .Err)
|
if (structuredData.Load(ProjectFileName) case .Err)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
String managedText = scope .();
|
||||||
|
if (File.ReadAllText(scope $"{mProjectDir}/BeefManaged.toml", managedText) case .Ok)
|
||||||
|
{
|
||||||
|
mManagedInfo = new .();
|
||||||
|
mManagedInfo.mInfo = new .(managedText);
|
||||||
|
|
||||||
|
StructuredData msd = scope .();
|
||||||
|
if (msd.LoadFromString(managedText) case .Ok)
|
||||||
|
{
|
||||||
|
if (mManagedInfo.mVersion.mVersion == null)
|
||||||
|
mManagedInfo.mVersion.mVersion = new .();
|
||||||
|
msd.GetString("Version", mManagedInfo.mVersion.mVersion);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1615,7 +1653,8 @@ namespace IDE
|
||||||
using (data.CreateObject("Project"))
|
using (data.CreateObject("Project"))
|
||||||
{
|
{
|
||||||
if (!IsSingleFile)
|
if (!IsSingleFile)
|
||||||
data.Add("Name", mProjectName);
|
data.Add("Name", mProjectNameDecl);
|
||||||
|
data.ConditionalAdd("Version", mGeneralOptions.mVersion.mVersion);
|
||||||
data.ConditionalAdd("TargetType", mGeneralOptions.mTargetType, GetDefaultTargetType());
|
data.ConditionalAdd("TargetType", mGeneralOptions.mTargetType, GetDefaultTargetType());
|
||||||
data.ConditionalAdd("StartupObject", mBeefGlobalOptions.mStartupObject, IsSingleFile ? "Program" : "");
|
data.ConditionalAdd("StartupObject", mBeefGlobalOptions.mStartupObject, IsSingleFile ? "Program" : "");
|
||||||
var defaultNamespace = scope String();
|
var defaultNamespace = scope String();
|
||||||
|
@ -1955,7 +1994,24 @@ namespace IDE
|
||||||
using (data.Open("Project"))
|
using (data.Open("Project"))
|
||||||
{
|
{
|
||||||
if (!IsSingleFile)
|
if (!IsSingleFile)
|
||||||
data.GetString("Name", mProjectName);
|
{
|
||||||
|
var projectName = data.GetString("Name", .. scope .());
|
||||||
|
if ((!mProjectName.IsEmpty) && (projectName != mProjectName))
|
||||||
|
{
|
||||||
|
// If the name we specified clashes with the delclared project name in the config
|
||||||
|
if (mProjectNameDecl === mProjectName)
|
||||||
|
{
|
||||||
|
mProjectNameDecl = new .(projectName);
|
||||||
|
mGeneralOptions.mProjectNameDecl = mProjectNameDecl;
|
||||||
|
gApp.mWorkspace.ClearProjectNameCache();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
mProjectNameDecl.Set(projectName);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
mProjectName.Set(projectName);
|
||||||
|
}
|
||||||
|
data.GetString("Version", mGeneralOptions.mVersion.mVersion);
|
||||||
ReadStrings("Aliases", mGeneralOptions.mAliases);
|
ReadStrings("Aliases", mGeneralOptions.mAliases);
|
||||||
data.GetString("StartupObject", mBeefGlobalOptions.mStartupObject, IsSingleFile ? "Program" : "");
|
data.GetString("StartupObject", mBeefGlobalOptions.mStartupObject, IsSingleFile ? "Program" : "");
|
||||||
var defaultNamespace = scope String();
|
var defaultNamespace = scope String();
|
||||||
|
@ -2029,7 +2085,7 @@ namespace IDE
|
||||||
{
|
{
|
||||||
case .Ok(let project):
|
case .Ok(let project):
|
||||||
case .Err(let err):
|
case .Err(let err):
|
||||||
gApp.OutputLineSmart("ERROR: Unable to load project '{0}' specified in project '{1}'", dep.mProjectName, mProjectName);
|
// Give an error later
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2232,6 +2288,35 @@ namespace IDE
|
||||||
mRootFolder.StartWatching();
|
mRootFolder.StartWatching();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void CheckDependenciesLoaded()
|
||||||
|
{
|
||||||
|
for (var dep in mDependencies)
|
||||||
|
{
|
||||||
|
if (!dep.mDependencyChecked)
|
||||||
|
{
|
||||||
|
var project = gApp.mWorkspace.FindProject(dep.mProjectName);
|
||||||
|
if (project != null)
|
||||||
|
{
|
||||||
|
var projectVersion = project.Version;
|
||||||
|
if (!projectVersion.mVersion.IsEmpty)
|
||||||
|
{
|
||||||
|
if (dep.mVerSpec case .Git(let url, let ver))
|
||||||
|
{
|
||||||
|
if (!SemVer.IsVersionMatch(projectVersion, ver))
|
||||||
|
gApp.OutputLineSmart($"WARNING: Project '{mProjectName}' has version constraint '{ver}' for '{dep.mProjectName}' which is not satisfied by selected version '{projectVersion}'");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
gApp.OutputLineSmart("ERROR: Unable to load project '{0}' specified in project '{1}'", dep.mProjectName, mProjectName);
|
||||||
|
}
|
||||||
|
|
||||||
|
dep.mDependencyChecked = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void FinishCreate(bool allowCreateDir = true)
|
public void FinishCreate(bool allowCreateDir = true)
|
||||||
{
|
{
|
||||||
if (!mRootFolder.mIsWatching)
|
if (!mRootFolder.mIsWatching)
|
||||||
|
@ -2414,29 +2499,35 @@ namespace IDE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool HasDependency(String projectName, bool checkRecursively = true)
|
public VerSpec* GetDependency(String projectName, bool checkRecursively = true)
|
||||||
{
|
{
|
||||||
HashSet<Project> checkedProject = scope .();
|
HashSet<Project> checkedProject = scope .();
|
||||||
|
|
||||||
bool CheckDependency(Project project)
|
VerSpec* CheckDependency(Project project)
|
||||||
{
|
{
|
||||||
if (!checkedProject.Add(project))
|
if (!checkedProject.Add(project))
|
||||||
return false;
|
return null;
|
||||||
|
|
||||||
for (var dependency in project.mDependencies)
|
for (var dependency in project.mDependencies)
|
||||||
{
|
{
|
||||||
if (dependency.mProjectName == projectName)
|
if (dependency.mProjectName == projectName)
|
||||||
return true;
|
return &dependency.mVerSpec;
|
||||||
let depProject = gApp.mWorkspace.FindProject(dependency.mProjectName);
|
let depProject = gApp.mWorkspace.FindProject(dependency.mProjectName);
|
||||||
if ((depProject != null) && (checkRecursively) && (CheckDependency(depProject)))
|
if ((depProject != null) && (checkRecursively))
|
||||||
return true;
|
{
|
||||||
|
var verSpec = CheckDependency(depProject);
|
||||||
|
if (verSpec != null)
|
||||||
|
return verSpec;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return CheckDependency(this);
|
return CheckDependency(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool HasDependency(String projectName, bool checkRecursively = true) => GetDependency(projectName, checkRecursively) != null;
|
||||||
|
|
||||||
public void SetupDefault(Options options, String configName, String platformName)
|
public void SetupDefault(Options options, String configName, String platformName)
|
||||||
{
|
{
|
||||||
bool isRelease = configName.Contains("Release");
|
bool isRelease = configName.Contains("Release");
|
||||||
|
|
|
@ -223,7 +223,8 @@ namespace IDE
|
||||||
None,
|
None,
|
||||||
Loaded,
|
Loaded,
|
||||||
ReadyToLoad,
|
ReadyToLoad,
|
||||||
Preparing
|
Preparing,
|
||||||
|
Failed
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ConfigSelection : IHashable, IEquatable
|
public class ConfigSelection : IHashable, IEquatable
|
||||||
|
@ -488,26 +489,25 @@ namespace IDE
|
||||||
public VerSpec mVerSpec ~ _.Dispose();
|
public VerSpec mVerSpec ~ _.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
public class Lock
|
public enum Lock
|
||||||
{
|
{
|
||||||
public enum Location
|
case Cache;
|
||||||
{
|
case Local(String path);
|
||||||
case Cache;
|
case Git(String url, String tag, String hash);
|
||||||
case Local(String path);
|
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
|
{
|
||||||
|
switch (this)
|
||||||
{
|
{
|
||||||
switch (this)
|
case .Cache:
|
||||||
{
|
case .Local(let path):
|
||||||
case .Cache:
|
delete path;
|
||||||
case .Local(let path):
|
case Git(var url, var tag, var hash):
|
||||||
delete path;
|
delete url;
|
||||||
}
|
delete tag;
|
||||||
|
delete hash;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public String mVersion ~ delete _;
|
|
||||||
public Location mLocation ~ _.Dispose();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Monitor mMonitor = new Monitor() ~ delete _;
|
public Monitor mMonitor = new Monitor() ~ delete _;
|
||||||
|
@ -519,7 +519,15 @@ namespace IDE
|
||||||
public List<ProjectSpec> mProjectSpecs = new .() ~ DeleteContainerAndItems!(_);
|
public List<ProjectSpec> mProjectSpecs = new .() ~ DeleteContainerAndItems!(_);
|
||||||
public List<ProjectFileEntry> mProjectFileEntries = new .() ~ DeleteContainerAndItems!(_);
|
public List<ProjectFileEntry> mProjectFileEntries = new .() ~ DeleteContainerAndItems!(_);
|
||||||
public Dictionary<String, Project> mProjectNameMap = new .() ~ DeleteDictionaryAndKeys!(_);
|
public Dictionary<String, Project> mProjectNameMap = new .() ~ DeleteDictionaryAndKeys!(_);
|
||||||
public Dictionary<String, Lock> mProjectLockMap = new .() ~ DeleteDictionaryAndKeysAndValues!(_);
|
public Dictionary<String, Lock> mProjectLockMap = new .() ~
|
||||||
|
{
|
||||||
|
for (var kv in ref _)
|
||||||
|
{
|
||||||
|
delete kv.key;
|
||||||
|
kv.valueRef.Dispose();
|
||||||
|
}
|
||||||
|
delete _;
|
||||||
|
}
|
||||||
public Project mStartupProject;
|
public Project mStartupProject;
|
||||||
public bool mLoading;
|
public bool mLoading;
|
||||||
public bool mNeedsCreate;
|
public bool mNeedsCreate;
|
||||||
|
@ -578,6 +586,20 @@ namespace IDE
|
||||||
ClearAndDeleteItems(mPlatforms);
|
ClearAndDeleteItems(mPlatforms);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void SetLock(StringView projectName, Lock lock)
|
||||||
|
{
|
||||||
|
if (mProjectLockMap.TryAddAlt(projectName, var keyPtr, var valuePtr))
|
||||||
|
{
|
||||||
|
*keyPtr = new .(projectName);
|
||||||
|
*valuePtr = lock;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
valuePtr.Dispose();
|
||||||
|
*valuePtr = lock;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void GetPlatformList(List<String> outList)
|
public void GetPlatformList(List<String> outList)
|
||||||
{
|
{
|
||||||
if (mPlatforms.IsEmpty)
|
if (mPlatforms.IsEmpty)
|
||||||
|
@ -947,16 +969,33 @@ namespace IDE
|
||||||
{
|
{
|
||||||
using (mMonitor.Enter())
|
using (mMonitor.Enter())
|
||||||
{
|
{
|
||||||
|
int GetNamePriority(StringView name, Project project)
|
||||||
|
{
|
||||||
|
if (project.mProjectName == name)
|
||||||
|
return 2;
|
||||||
|
if (project.mProjectNameDecl == name)
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void Add(String name, Project project)
|
void Add(String name, Project project)
|
||||||
{
|
{
|
||||||
bool added = mProjectNameMap.TryAdd(name, var keyPtr, var valuePtr);
|
if (mProjectNameMap.TryAdd(name, var keyPtr, var valuePtr))
|
||||||
if (!added)
|
{
|
||||||
return;
|
*keyPtr = new String(name);
|
||||||
*keyPtr = new String(name);
|
*valuePtr = project;
|
||||||
*valuePtr = project;
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (GetNamePriority(name, project) > GetNamePriority(*keyPtr, *valuePtr))
|
||||||
|
*valuePtr = project;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Add(project.mProjectName, project);
|
Add(project.mProjectName, project);
|
||||||
|
|
||||||
|
if (project.mProjectNameDecl !== project.mProjectName)
|
||||||
|
Add(project.mProjectNameDecl, project);
|
||||||
|
|
||||||
for (var alias in project.mGeneralOptions.mAliases)
|
for (var alias in project.mGeneralOptions.mAliases)
|
||||||
Add(alias, project);
|
Add(alias, project);
|
||||||
|
@ -979,7 +1018,11 @@ namespace IDE
|
||||||
}
|
}
|
||||||
|
|
||||||
for (var project in mProjects)
|
for (var project in mProjects)
|
||||||
|
{
|
||||||
Add(project.mProjectName, project);
|
Add(project.mProjectName, project);
|
||||||
|
if (project.mProjectName != project.mProjectNameDecl)
|
||||||
|
Add(project.mProjectNameDecl, project);
|
||||||
|
}
|
||||||
|
|
||||||
for (var project in mProjects)
|
for (var project in mProjects)
|
||||||
{
|
{
|
||||||
|
|
|
@ -10,6 +10,87 @@ namespace IDE.ui
|
||||||
|
|
||||||
class BuildPropertiesDialog : TargetedPropertiesDialog
|
class BuildPropertiesDialog : TargetedPropertiesDialog
|
||||||
{
|
{
|
||||||
|
protected class DependencyEntry : IEquatable, IMultiValued
|
||||||
|
{
|
||||||
|
public bool mUse;
|
||||||
|
public String mURL ~ delete _;
|
||||||
|
public String mVersion ~ delete _;
|
||||||
|
|
||||||
|
public this()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public ~this()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public this(DependencyEntry val)
|
||||||
|
{
|
||||||
|
mUse = val.mUse;
|
||||||
|
if (val.mURL != null)
|
||||||
|
mURL = new .(val.mURL);
|
||||||
|
if (val.mVersion != null)
|
||||||
|
mVersion = new .(val.mVersion);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Equals(Object val)
|
||||||
|
{
|
||||||
|
if (var rhsDE = val as DependencyEntry)
|
||||||
|
{
|
||||||
|
return
|
||||||
|
(mUse == rhsDE.mUse) &&
|
||||||
|
(mURL == rhsDE.mURL) &&
|
||||||
|
(mVersion == rhsDE.mVersion);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void GetValue(int idx, String outValue)
|
||||||
|
{
|
||||||
|
if ((idx == 1) && (mURL != null))
|
||||||
|
outValue.Set(mURL);
|
||||||
|
if ((idx == 2) && (mVersion != null))
|
||||||
|
outValue.Set(mVersion);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool SetValue(int idx, StringView value)
|
||||||
|
{
|
||||||
|
if (idx == 1)
|
||||||
|
{
|
||||||
|
if (value.IsEmpty)
|
||||||
|
{
|
||||||
|
DeleteAndNullify!(mURL);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
String.NewOrSet!(mURL, value);
|
||||||
|
mURL.Trim();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (idx == 2)
|
||||||
|
{
|
||||||
|
if (value.IsEmpty)
|
||||||
|
{
|
||||||
|
DeleteAndNullify!(mVersion);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
String.NewOrSet!(mVersion, value);
|
||||||
|
mVersion.Trim();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Set(DependencyEntry value)
|
||||||
|
{
|
||||||
|
mUse = value.mUse;
|
||||||
|
SetValue(1, value.mURL);
|
||||||
|
SetValue(2, value.mVersion);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected class DistinctOptionBuilder
|
protected class DistinctOptionBuilder
|
||||||
{
|
{
|
||||||
BuildPropertiesDialog mDialog;
|
BuildPropertiesDialog mDialog;
|
||||||
|
|
|
@ -145,6 +145,7 @@ namespace IDE.ui
|
||||||
bool mImportFolderDeferred;
|
bool mImportFolderDeferred;
|
||||||
bool mImportProjectDeferred;
|
bool mImportProjectDeferred;
|
||||||
bool mImportInstalledDeferred;
|
bool mImportInstalledDeferred;
|
||||||
|
bool mImportRemoteDeferred;
|
||||||
public Dictionary<ListViewItem, ProjectItem> mListViewToProjectMap = new .() ~ delete _;
|
public Dictionary<ListViewItem, ProjectItem> mListViewToProjectMap = new .() ~ delete _;
|
||||||
public Dictionary<ProjectItem, ProjectListViewItem> mProjectToListViewMap = new .() ~ delete _;
|
public Dictionary<ProjectItem, ProjectListViewItem> mProjectToListViewMap = new .() ~ delete _;
|
||||||
public Dictionary<ListViewItem, WorkspaceFolder> mListViewToWorkspaceFolderMap = new .() ~ delete _;
|
public Dictionary<ListViewItem, WorkspaceFolder> mListViewToWorkspaceFolderMap = new .() ~ delete _;
|
||||||
|
@ -2904,6 +2905,15 @@ namespace IDE.ui
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ImportRemoteProject()
|
||||||
|
{
|
||||||
|
#if !CLI
|
||||||
|
RemoteProjectDialog dialog = new .();
|
||||||
|
dialog.Init();
|
||||||
|
dialog.PopupWindow(gApp.mMainWindow);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
public void ShowProjectProperties(Project project)
|
public void ShowProjectProperties(Project project)
|
||||||
{
|
{
|
||||||
var projectProperties = new ProjectProperties(project);
|
var projectProperties = new ProjectProperties(project);
|
||||||
|
@ -3081,6 +3091,14 @@ namespace IDE.ui
|
||||||
});
|
});
|
||||||
if (gApp.IsCompiling)
|
if (gApp.IsCompiling)
|
||||||
anItem.SetDisabled(true);
|
anItem.SetDisabled(true);
|
||||||
|
|
||||||
|
anItem = menu.AddItem("Add From Remote...");
|
||||||
|
anItem.mOnMenuItemSelected.Add(new (item) => {
|
||||||
|
mImportRemoteDeferred = true;
|
||||||
|
});
|
||||||
|
if (gApp.IsCompiling)
|
||||||
|
anItem.SetDisabled(true);
|
||||||
|
|
||||||
anItem = menu.AddItem("New Folder");
|
anItem = menu.AddItem("New Folder");
|
||||||
anItem.mOnMenuItemSelected.Add(new (item) => {
|
anItem.mOnMenuItemSelected.Add(new (item) => {
|
||||||
var workspaceFolder = GetSelectedWorkspaceFolder();
|
var workspaceFolder = GetSelectedWorkspaceFolder();
|
||||||
|
@ -3110,7 +3128,18 @@ namespace IDE.ui
|
||||||
}
|
}
|
||||||
else if (gApp.mWorkspace.IsInitialized)
|
else if (gApp.mWorkspace.IsInitialized)
|
||||||
{
|
{
|
||||||
|
var item = menu.AddItem("Update Version Locks");
|
||||||
|
item.mDisabled = gApp.mWorkspace.mProjectLockMap.IsEmpty;
|
||||||
|
item.mOnMenuItemSelected.Add(new (item) =>
|
||||||
|
{
|
||||||
|
List<StringView> projectNames = scope .();
|
||||||
|
for (var projectName in gApp.mWorkspace.mProjectLockMap.Keys)
|
||||||
|
projectNames.Add(projectName);
|
||||||
|
gApp.UpdateProjectVersionLocks(params (Span<StringView>)projectNames);
|
||||||
|
});
|
||||||
|
|
||||||
AddOpenContainingFolder();
|
AddOpenContainingFolder();
|
||||||
|
|
||||||
menu.AddItem();
|
menu.AddItem();
|
||||||
|
|
||||||
AddWorkspaceMenuItems();
|
AddWorkspaceMenuItems();
|
||||||
|
@ -3140,7 +3169,7 @@ namespace IDE.ui
|
||||||
{
|
{
|
||||||
var projectItem = GetSelectedProjectItem();
|
var projectItem = GetSelectedProjectItem();
|
||||||
if (projectItem != null)
|
if (projectItem != null)
|
||||||
gApp.RetryProjectLoad(projectItem.mProject);
|
gApp.RetryProjectLoad(projectItem.mProject, true);
|
||||||
});
|
});
|
||||||
menu.AddItem();
|
menu.AddItem();
|
||||||
//handled = true;
|
//handled = true;
|
||||||
|
@ -3168,6 +3197,18 @@ namespace IDE.ui
|
||||||
SetAsStartupProject(projectItem.mProject);
|
SetAsStartupProject(projectItem.mProject);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
item = menu.AddItem("Update Version Lock");
|
||||||
|
item.mDisabled = (projectItem == null) || (!gApp.mWorkspace.mProjectLockMap.ContainsKey(projectItem.mProject.mProjectName));
|
||||||
|
item.mOnMenuItemSelected.Add(new (item) =>
|
||||||
|
{
|
||||||
|
var projectItem = GetSelectedProjectItem();
|
||||||
|
if (projectItem != null)
|
||||||
|
{
|
||||||
|
let project = projectItem.mProject;
|
||||||
|
gApp.UpdateProjectVersionLocks(project.mProjectName);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
item = menu.AddItem("Lock Project");
|
item = menu.AddItem("Lock Project");
|
||||||
if (projectItem.mProject.mLocked)
|
if (projectItem.mProject.mLocked)
|
||||||
item.mIconImage = DarkTheme.sDarkTheme.GetImage(.Check);
|
item.mIconImage = DarkTheme.sDarkTheme.GetImage(.Check);
|
||||||
|
@ -3570,6 +3611,12 @@ namespace IDE.ui
|
||||||
ImportInstalledProject();
|
ImportInstalledProject();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (mImportRemoteDeferred)
|
||||||
|
{
|
||||||
|
mImportRemoteDeferred= false;
|
||||||
|
ImportRemoteProject();
|
||||||
|
}
|
||||||
|
|
||||||
ValidateCutClipboard();
|
ValidateCutClipboard();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,13 +10,12 @@ using Beefy.events;
|
||||||
using Beefy.theme.dark;
|
using Beefy.theme.dark;
|
||||||
using Beefy.gfx;
|
using Beefy.gfx;
|
||||||
using Beefy.geom;
|
using Beefy.geom;
|
||||||
|
using IDE.Util;
|
||||||
|
|
||||||
namespace IDE.ui
|
namespace IDE.ui
|
||||||
{
|
{
|
||||||
public class ProjectProperties : BuildPropertiesDialog
|
public class ProjectProperties : BuildPropertiesDialog
|
||||||
{
|
{
|
||||||
ValueContainer<String> mVC;
|
|
||||||
|
|
||||||
enum CategoryType
|
enum CategoryType
|
||||||
{
|
{
|
||||||
General, ///
|
General, ///
|
||||||
|
@ -27,6 +26,7 @@ namespace IDE.ui
|
||||||
Dependencies,
|
Dependencies,
|
||||||
Beef_Global,
|
Beef_Global,
|
||||||
Platform,
|
Platform,
|
||||||
|
Managed,
|
||||||
|
|
||||||
Targeted, ///
|
Targeted, ///
|
||||||
Beef_Targeted,
|
Beef_Targeted,
|
||||||
|
@ -36,10 +36,11 @@ namespace IDE.ui
|
||||||
|
|
||||||
COUNT
|
COUNT
|
||||||
}
|
}
|
||||||
|
|
||||||
public Project mProject;
|
public Project mProject;
|
||||||
Dictionary<String, ValueContainer<bool>> mDependencyValuesMap ~ DeleteDictionaryAndKeysAndValues!(_);
|
Dictionary<String, DependencyEntry> mDependencyValuesMap ~ DeleteDictionaryAndKeysAndValues!(_);
|
||||||
Project.Options[] mCurProjectOptions ~ delete _;
|
Project.Options[] mCurProjectOptions ~ delete _;
|
||||||
|
List<String> mUpdateProjectLocks = new .() ~ DeleteContainerAndItems!(_);
|
||||||
float mLockFlashPct;
|
float mLockFlashPct;
|
||||||
public int32 mNewDebugSessionCountdown;
|
public int32 mNewDebugSessionCountdown;
|
||||||
|
|
||||||
|
@ -96,6 +97,7 @@ namespace IDE.ui
|
||||||
AddCategoryItem(globalItem, "Dependencies");
|
AddCategoryItem(globalItem, "Dependencies");
|
||||||
AddCategoryItem(globalItem, "Beef");
|
AddCategoryItem(globalItem, "Beef");
|
||||||
AddCategoryItem(globalItem, "Platform");
|
AddCategoryItem(globalItem, "Platform");
|
||||||
|
AddCategoryItem(globalItem, "Managed");
|
||||||
globalItem.Open(true, true);
|
globalItem.Open(true, true);
|
||||||
|
|
||||||
var targetedItem = AddCategoryItem(root, "Targeted");
|
var targetedItem = AddCategoryItem(root, "Targeted");
|
||||||
|
@ -149,7 +151,8 @@ namespace IDE.ui
|
||||||
case .General,
|
case .General,
|
||||||
.Project,
|
.Project,
|
||||||
.Dependencies,
|
.Dependencies,
|
||||||
.Beef_Global:
|
.Beef_Global,
|
||||||
|
.Managed:
|
||||||
return .None;
|
return .None;
|
||||||
case .Platform:
|
case .Platform:
|
||||||
return .Platform;
|
return .Platform;
|
||||||
|
@ -432,6 +435,7 @@ namespace IDE.ui
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
case .Managed:
|
||||||
case .Build, .Debugging, .Beef_Targeted:
|
case .Build, .Debugging, .Beef_Targeted:
|
||||||
DeleteDistinctBuildOptions();
|
DeleteDistinctBuildOptions();
|
||||||
DistinctBuildOptions defaultTypeOptions = scope:: .();
|
DistinctBuildOptions defaultTypeOptions = scope:: .();
|
||||||
|
@ -530,7 +534,9 @@ namespace IDE.ui
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
mCurPropertiesTargets = new Object[1];
|
mCurPropertiesTargets = new Object[1];
|
||||||
if (categoryType == .Project)
|
if (categoryType == .Managed)
|
||||||
|
mCurPropertiesTargets[0] = mProject.mManagedInfo;
|
||||||
|
else if (categoryType == .Project)
|
||||||
mCurPropertiesTargets[0] = mProject.mGeneralOptions;
|
mCurPropertiesTargets[0] = mProject.mGeneralOptions;
|
||||||
else if (categoryType == .Beef_Global)
|
else if (categoryType == .Beef_Global)
|
||||||
mCurPropertiesTargets[0] = mProject.mBeefGlobalOptions;
|
mCurPropertiesTargets[0] = mProject.mBeefGlobalOptions;
|
||||||
|
@ -600,6 +606,8 @@ namespace IDE.ui
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (categoryType == CategoryType.Managed)
|
||||||
|
PopulateManagedOptions();
|
||||||
else if (categoryType == CategoryType.Build)
|
else if (categoryType == CategoryType.Build)
|
||||||
PopulateBuildOptions();
|
PopulateBuildOptions();
|
||||||
else if (categoryType == CategoryType.Beef_Global )
|
else if (categoryType == CategoryType.Beef_Global )
|
||||||
|
@ -619,6 +627,8 @@ namespace IDE.ui
|
||||||
void PopulateGeneralOptions()
|
void PopulateGeneralOptions()
|
||||||
{
|
{
|
||||||
var root = (DarkListViewItem)mPropPage.mPropertiesListView.GetRoot();
|
var root = (DarkListViewItem)mPropPage.mPropertiesListView.GetRoot();
|
||||||
|
var (listViewItem, propEntry) = AddPropertiesItem(root, "Project Name", "mProjectNameDecl");
|
||||||
|
AddPropertiesItem(root, "Project Name Aliases", "mAliases");
|
||||||
AddPropertiesItem(root, "Target Type", "mTargetType", scope String[]
|
AddPropertiesItem(root, "Target Type", "mTargetType", scope String[]
|
||||||
(
|
(
|
||||||
"Console Application",
|
"Console Application",
|
||||||
|
@ -627,9 +637,21 @@ namespace IDE.ui
|
||||||
"Custom Build",
|
"Custom Build",
|
||||||
"Test"
|
"Test"
|
||||||
));
|
));
|
||||||
AddPropertiesItem(root, "Project Name Aliases", "mAliases");
|
AddPropertiesItem(root, "Version", "mVersion.mVersion");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PopulateManagedOptions()
|
||||||
|
{
|
||||||
|
if (mCurPropertiesTargets[0] == null)
|
||||||
|
return;
|
||||||
|
var root = (DarkListViewItem)mPropPage.mPropertiesListView.GetRoot();
|
||||||
|
var (listViewItem, propEntry) = AddPropertiesItem(root, "Version", "mVersion.mVersion");
|
||||||
|
propEntry.mReadOnly = true;
|
||||||
|
(listViewItem, propEntry) = AddPropertiesItem(root, "Info", "mInfo");
|
||||||
|
propEntry.mAllowMultiline = true;
|
||||||
|
propEntry.mReadOnly = true;
|
||||||
|
}
|
||||||
|
|
||||||
void PopulateWindowsOptions()
|
void PopulateWindowsOptions()
|
||||||
{
|
{
|
||||||
var root = (DarkListViewItem)mPropPage.mPropertiesListView.GetRoot();
|
var root = (DarkListViewItem)mPropPage.mPropertiesListView.GetRoot();
|
||||||
|
@ -696,7 +718,21 @@ namespace IDE.ui
|
||||||
|
|
||||||
void PopulateDependencyOptions()
|
void PopulateDependencyOptions()
|
||||||
{
|
{
|
||||||
mDependencyValuesMap = new Dictionary<String, ValueContainer<bool>>();
|
mPropPage.mPropertiesListView.mColumns[0].Label = "Project";
|
||||||
|
mPropPage.mPropertiesListView.mColumns[0].mMinWidth = GS!(100);
|
||||||
|
mPropPage.mPropertiesListView.mColumns[0].mWidth = GS!(180);
|
||||||
|
|
||||||
|
mPropPage.mPropertiesListView.mColumns[1].Label = "";
|
||||||
|
mPropPage.mPropertiesListView.mColumns[1].mMinWidth = GS!(20);
|
||||||
|
mPropPage.mPropertiesListView.mColumns[1].mWidth = GS!(20);
|
||||||
|
|
||||||
|
mPropPage.mPropertiesListView.AddColumn(180, "Remote URL");
|
||||||
|
mPropPage.mPropertiesListView.mColumns[2].mMinWidth = GS!(100);
|
||||||
|
|
||||||
|
mPropPage.mPropertiesListView.AddColumn(180, "Ver Constraint");
|
||||||
|
mPropPage.mPropertiesListView.mColumns[3].mMinWidth = GS!(100);
|
||||||
|
|
||||||
|
mDependencyValuesMap = new .();
|
||||||
|
|
||||||
var root = (DarkListViewItem)mPropPage.mPropertiesListView.GetRoot();
|
var root = (DarkListViewItem)mPropPage.mPropertiesListView.GetRoot();
|
||||||
var category = root;
|
var category = root;
|
||||||
|
@ -719,63 +755,184 @@ namespace IDE.ui
|
||||||
projectNames.Sort(scope (a, b) => String.Compare(a, b, true));
|
projectNames.Sort(scope (a, b) => String.Compare(a, b, true));
|
||||||
|
|
||||||
for (var projectName in projectNames)
|
for (var projectName in projectNames)
|
||||||
{
|
{
|
||||||
var dependencyContainer = new ValueContainer<bool>();
|
var project = gApp.mWorkspace.FindProject(projectName);
|
||||||
dependencyContainer.mValue = mProject.HasDependency(projectName, false);
|
|
||||||
mDependencyValuesMap[new String(projectName)] = dependencyContainer;
|
var dependencyEntry = new DependencyEntry();
|
||||||
|
var verSpec = mProject.GetDependency(projectName, false);
|
||||||
|
if (verSpec != null)
|
||||||
|
{
|
||||||
|
dependencyEntry.mUse = true;
|
||||||
|
if (verSpec case .Git(let url, let ver))
|
||||||
|
{
|
||||||
|
dependencyEntry.mURL = new .(url);
|
||||||
|
if (ver != null)
|
||||||
|
dependencyEntry.mVersion = new .(ver.mVersion);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mDependencyValuesMap[new String(projectName)] = dependencyEntry;
|
||||||
|
|
||||||
var (listViewItem, propItem) = AddPropertiesItem(category, projectName);
|
var (listViewItem, propItem) = AddPropertiesItem(category, projectName);
|
||||||
if (IDEApp.sApp.mWorkspace.FindProject(projectName) == null)
|
if (IDEApp.sApp.mWorkspace.FindProject(projectName) == null)
|
||||||
listViewItem.mTextColor = Color.Mult(DarkTheme.COLOR_TEXT, 0xFFFF6060);
|
listViewItem.mTextColor = Color.Mult(DarkTheme.COLOR_TEXT, 0xFFFF6060);
|
||||||
|
|
||||||
var subItem = listViewItem.CreateSubItem(1);
|
var subItem = (DarkListViewItem)listViewItem.CreateSubItem(1);
|
||||||
|
|
||||||
var checkbox = new DarkCheckBox();
|
var checkbox = new DarkCheckBox();
|
||||||
checkbox.Checked = dependencyContainer.mValue;
|
checkbox.Checked = dependencyEntry.mUse;
|
||||||
checkbox.Resize(0, 0, DarkTheme.sUnitSize, DarkTheme.sUnitSize);
|
checkbox.Resize(0, 0, DarkTheme.sUnitSize, DarkTheme.sUnitSize);
|
||||||
subItem.AddWidget(checkbox);
|
subItem.AddWidget(checkbox);
|
||||||
|
|
||||||
PropEntry[] propEntries = new PropEntry[1];
|
PropEntry[] propEntries = new PropEntry[1];
|
||||||
|
|
||||||
PropEntry propEntry = new PropEntry();
|
PropEntry propEntry = new PropEntry();
|
||||||
propEntry.mTarget = dependencyContainer;
|
propEntry.mTarget = dependencyEntry;
|
||||||
//propEntry.mFieldInfo = dependencyContainer.GetType().GetField("mValue").Value;
|
propEntry.mOrigValue = Variant.Create(dependencyEntry);
|
||||||
propEntry.mOrigValue = Variant.Create(dependencyContainer.mValue);
|
propEntry.mCurValue = Variant.Create(new DependencyEntry(dependencyEntry), true);
|
||||||
propEntry.mCurValue = propEntry.mOrigValue;
|
|
||||||
|
|
||||||
propEntry.mListViewItem = listViewItem;
|
propEntry.mListViewItem = listViewItem;
|
||||||
propEntry.mCheckBox = checkbox;
|
propEntry.mCheckBox = checkbox;
|
||||||
propEntry.mApplyAction = new () =>
|
propEntry.mApplyAction = new () =>
|
||||||
{
|
{
|
||||||
if (propEntry.mCurValue.Get<bool>())
|
bool updateProjectLock = false;
|
||||||
|
|
||||||
|
var dependencyEntry = propEntry.mCurValue.Get<DependencyEntry>();
|
||||||
|
if (dependencyEntry.mUse)
|
||||||
{
|
{
|
||||||
if (!mProject.HasDependency(listViewItem.mLabel))
|
VerSpec verSpec = default;
|
||||||
|
if (dependencyEntry.mURL != null)
|
||||||
|
verSpec = .Git(new .(dependencyEntry.mURL), (dependencyEntry.mVersion != null) ? new .(dependencyEntry.mVersion) : null);
|
||||||
|
else if (dependencyEntry.mVersion != null)
|
||||||
|
verSpec = .SemVer(new .(dependencyEntry.mVersion));
|
||||||
|
else
|
||||||
|
verSpec = .SemVer(new .("*"));
|
||||||
|
|
||||||
|
var verSpecPtr = mProject.GetDependency(listViewItem.mLabel);
|
||||||
|
if (verSpecPtr == null)
|
||||||
{
|
{
|
||||||
|
if (verSpec case .Git(let url, let ver))
|
||||||
|
updateProjectLock = true;
|
||||||
|
|
||||||
var dep = new Project.Dependency();
|
var dep = new Project.Dependency();
|
||||||
dep.mProjectName = new String(listViewItem.mLabel);
|
dep.mProjectName = new String(listViewItem.mLabel);
|
||||||
dep.mVerSpec = .SemVer(new .("*"));
|
dep.mVerSpec = verSpec;
|
||||||
mProject.mDependencies.Add(dep);
|
mProject.mDependencies.Add(dep);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (*verSpecPtr != verSpec)
|
||||||
|
{
|
||||||
|
if ((*verSpecPtr case .Git) ||
|
||||||
|
(verSpecPtr case .Git))
|
||||||
|
updateProjectLock = true;
|
||||||
|
verSpecPtr.Dispose();
|
||||||
|
*verSpecPtr = verSpec;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int idx = mProject.mDependencies.FindIndex(scope (dep) => dep.mProjectName == listViewItem.mLabel);
|
int idx = mProject.mDependencies.FindIndex(scope (dep) => dep.mProjectName == listViewItem.mLabel);
|
||||||
if (idx != -1)
|
if (idx != -1)
|
||||||
{
|
{
|
||||||
|
var dep = mProject.mDependencies[idx];
|
||||||
|
if (dep.mVerSpec case .Git)
|
||||||
|
updateProjectLock = true;
|
||||||
delete mProject.mDependencies[idx];
|
delete mProject.mDependencies[idx];
|
||||||
mProject.mDependencies.RemoveAt(idx);
|
mProject.mDependencies.RemoveAt(idx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
propEntry.mOrigValue = propEntry.mCurValue;
|
|
||||||
|
var origDependencyEntry = propEntry.mOrigValue.Get<DependencyEntry>();
|
||||||
|
origDependencyEntry.Set(dependencyEntry);
|
||||||
|
|
||||||
|
if (updateProjectLock)
|
||||||
|
mUpdateProjectLocks.Add(new .(listViewItem.Label));
|
||||||
};
|
};
|
||||||
|
|
||||||
checkbox.mOnMouseUp.Add(new (evt) => { PropEntry.DisposeVariant(ref propEntry.mCurValue); propEntry.mCurValue = Variant.Create(checkbox.Checked); });
|
checkbox.mOnMouseUp.Add(new (evt) =>
|
||||||
|
{
|
||||||
|
var dependencyEntry = propEntry.mCurValue.Get<DependencyEntry>();
|
||||||
|
dependencyEntry.mUse = !dependencyEntry.mUse;
|
||||||
|
if (dependencyEntry.mUse)
|
||||||
|
{
|
||||||
|
var projectName = listViewItem.Label;
|
||||||
|
|
||||||
|
for (var projectSpec in gApp.mWorkspace.mProjectSpecs)
|
||||||
|
{
|
||||||
|
if (projectSpec.mProjectName == projectName)
|
||||||
|
{
|
||||||
|
if (projectSpec.mVerSpec case .Git(let url, let ver))
|
||||||
|
{
|
||||||
|
dependencyEntry.SetValue(1, url);
|
||||||
|
dependencyEntry.SetValue(2, ver.mVersion);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var propEntries = mPropPage.mPropEntries[listViewItem];
|
||||||
|
UpdatePropertyValue(propEntries);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DeleteAndNullify!(dependencyEntry.mURL);
|
||||||
|
DeleteAndNullify!(dependencyEntry.mVersion);
|
||||||
|
var propEntries = mPropPage.mPropEntries[listViewItem];
|
||||||
|
UpdatePropertyValue(propEntries);
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
subItem = (.)listViewItem.GetOrCreateSubItem(2);
|
||||||
|
if (dependencyEntry.mURL != null)
|
||||||
|
subItem.Label = dependencyEntry.mURL;
|
||||||
|
subItem.mOnMouseDown.Add(new => DepPropValueClicked);
|
||||||
|
|
||||||
|
subItem = (.)listViewItem.GetOrCreateSubItem(3);
|
||||||
|
if (dependencyEntry.mVersion != null)
|
||||||
|
{
|
||||||
|
subItem.Label = dependencyEntry.mVersion;
|
||||||
|
if (project != null)
|
||||||
|
{
|
||||||
|
var version = project.Version;
|
||||||
|
if (!version.IsEmpty)
|
||||||
|
{
|
||||||
|
if (!SemVer.IsVersionMatch(version.mVersion, dependencyEntry.mVersion))
|
||||||
|
subItem.mTextColor = Color.Mult(DarkTheme.COLOR_TEXT, 0xFFFFFF60);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
subItem.mOnMouseDown.Add(new => DepPropValueClicked);
|
||||||
|
|
||||||
propEntries[0] = propEntry;
|
propEntries[0] = propEntry;
|
||||||
mPropPage.mPropEntries[listViewItem] = propEntries;
|
mPropPage.mPropEntries[listViewItem] = propEntries;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void DepPropValueClicked(MouseEvent theEvent)
|
||||||
|
{
|
||||||
|
DarkListViewItem clickedItem = (DarkListViewItem)theEvent.mSender;
|
||||||
|
if (clickedItem.mColumnIdx == 0)
|
||||||
|
{
|
||||||
|
clickedItem.mListView.SetFocus();
|
||||||
|
clickedItem.mListView.GetRoot().SelectItemExclusively(clickedItem);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (theEvent.mX != -1)
|
||||||
|
{
|
||||||
|
clickedItem.mListView.GetRoot().SelectItemExclusively(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
DarkListViewItem item = (DarkListViewItem)clickedItem;
|
||||||
|
DarkListViewItem rootItem = (DarkListViewItem)clickedItem.GetSubItem(0);
|
||||||
|
|
||||||
|
PropEntry[] propertyEntries = mPropPage.mPropEntries[rootItem];
|
||||||
|
if (propertyEntries[0].mDisabled)
|
||||||
|
return;
|
||||||
|
EditValue(item, propertyEntries, clickedItem.mColumnIdx - 1);
|
||||||
|
}
|
||||||
|
|
||||||
protected override Object[] PhysAddNewDistinctBuildOptions()
|
protected override Object[] PhysAddNewDistinctBuildOptions()
|
||||||
{
|
{
|
||||||
if (mCurProjectOptions == null)
|
if (mCurProjectOptions == null)
|
||||||
|
@ -985,6 +1142,8 @@ namespace IDE.ui
|
||||||
/*if (!AssertNotCompilingOrRunning())
|
/*if (!AssertNotCompilingOrRunning())
|
||||||
return false;*/
|
return false;*/
|
||||||
|
|
||||||
|
String newProjectName = scope .();
|
||||||
|
|
||||||
using (mProject.mMonitor.Enter())
|
using (mProject.mMonitor.Enter())
|
||||||
{
|
{
|
||||||
for (var targetedConfigData in mConfigDatas)
|
for (var targetedConfigData in mConfigDatas)
|
||||||
|
@ -1000,9 +1159,18 @@ namespace IDE.ui
|
||||||
for (var propEntry in propEntries)
|
for (var propEntry in propEntries)
|
||||||
{
|
{
|
||||||
if (propEntry.HasChanged())
|
if (propEntry.HasChanged())
|
||||||
{
|
{
|
||||||
configDataHadChange = true;
|
if ((propEntry.mFieldInfo != default) && (propEntry.mFieldInfo.Name == "mProjectNameDecl"))
|
||||||
propEntry.ApplyValue();
|
{
|
||||||
|
var newName = propEntry.mCurValue.Get<String>();
|
||||||
|
newProjectName.Append(newName);
|
||||||
|
newProjectName.Trim();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
configDataHadChange = true;
|
||||||
|
propEntry.ApplyValue();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (propPage == mPropPage)
|
if (propPage == mPropPage)
|
||||||
|
@ -1060,6 +1228,9 @@ namespace IDE.ui
|
||||||
ClearTargetedData();
|
ClearTargetedData();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!newProjectName.IsEmpty)
|
||||||
|
gApp.RenameProject(mProject, newProjectName);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1081,6 +1252,7 @@ namespace IDE.ui
|
||||||
{
|
{
|
||||||
base.Close();
|
base.Close();
|
||||||
SetWorkspaceData(false);
|
SetWorkspaceData(false);
|
||||||
|
gApp.NotifyProjectVersionLocks(mUpdateProjectLocks);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void PopupWindow(WidgetWindow parentWindow, float offsetX = 0, float offsetY = 0)
|
public override void PopupWindow(WidgetWindow parentWindow, float offsetX = 0, float offsetY = 0)
|
||||||
|
|
|
@ -114,6 +114,12 @@ namespace IDE.ui
|
||||||
|
|
||||||
public class PropertiesDialog : IDEDialog
|
public class PropertiesDialog : IDEDialog
|
||||||
{
|
{
|
||||||
|
public interface IMultiValued
|
||||||
|
{
|
||||||
|
void GetValue(int idx, String outValue);
|
||||||
|
bool SetValue(int idx, StringView value);
|
||||||
|
}
|
||||||
|
|
||||||
class OwnedStringList : List<String>
|
class OwnedStringList : List<String>
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -215,6 +221,7 @@ namespace IDE.ui
|
||||||
public String mRelPath ~ delete _;
|
public String mRelPath ~ delete _;
|
||||||
public bool mIsTypeWildcard;
|
public bool mIsTypeWildcard;
|
||||||
public bool mAllowMultiline;
|
public bool mAllowMultiline;
|
||||||
|
public bool mReadOnly;
|
||||||
public Insets mEditInsets ~ delete _;
|
public Insets mEditInsets ~ delete _;
|
||||||
|
|
||||||
public ~this()
|
public ~this()
|
||||||
|
@ -305,6 +312,18 @@ namespace IDE.ui
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
else if (type.IsObject)
|
||||||
|
{
|
||||||
|
var lhsObj = lhs.Get<Object>();
|
||||||
|
var rhsObj = rhs.Get<Object>();
|
||||||
|
|
||||||
|
if ((var lhsEq = lhsObj as IEquatable) && (var rhsEq = rhsObj as IEquatable))
|
||||||
|
{
|
||||||
|
return lhsEq.Equals(rhsEq);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
else // Could be an int or enum
|
else // Could be an int or enum
|
||||||
return Variant.Equals!<int32>(lhs, rhs);
|
return Variant.Equals!<int32>(lhs, rhs);
|
||||||
}
|
}
|
||||||
|
@ -815,7 +834,7 @@ namespace IDE.ui
|
||||||
|
|
||||||
if (mPropEditWidget != null)
|
if (mPropEditWidget != null)
|
||||||
{
|
{
|
||||||
DarkListViewItem editItem = (DarkListViewItem)mEditingListViewItem.GetSubItem(1);
|
DarkListViewItem editItem = (DarkListViewItem)mEditingListViewItem;
|
||||||
let propEntry = mEditingProps[0];
|
let propEntry = mEditingProps[0];
|
||||||
|
|
||||||
float xPos;
|
float xPos;
|
||||||
|
@ -871,7 +890,7 @@ namespace IDE.ui
|
||||||
editWidget.GetText(newValue);
|
editWidget.GetText(newValue);
|
||||||
newValue.Trim();
|
newValue.Trim();
|
||||||
|
|
||||||
DarkListViewItem item = (DarkListViewItem)mEditingListViewItem;
|
DarkListViewItem rootItem = (DarkListViewItem)mEditingListViewItem.GetSubItem(0);
|
||||||
//DarkListViewItem valueItem = (DarkListViewItem)item.GetSubItem(1);
|
//DarkListViewItem valueItem = (DarkListViewItem)item.GetSubItem(1);
|
||||||
|
|
||||||
if (!editWidget.mEditWidgetContent.HasUndoData())
|
if (!editWidget.mEditWidgetContent.HasUndoData())
|
||||||
|
@ -920,14 +939,14 @@ namespace IDE.ui
|
||||||
{
|
{
|
||||||
//
|
//
|
||||||
}
|
}
|
||||||
else if (editingProp.mListViewItem != item)
|
else if (editingProp.mListViewItem != rootItem)
|
||||||
{
|
{
|
||||||
List<String> curEntries = editingProp.mCurValue.Get<List<String>>();
|
List<String> curEntries = editingProp.mCurValue.Get<List<String>>();
|
||||||
List<String> entries = new List<String>(curEntries.GetEnumerator());
|
List<String> entries = new List<String>(curEntries.GetEnumerator());
|
||||||
|
|
||||||
for (int32 childIdx = 0; childIdx < editingProp.mListViewItem.GetChildCount(); childIdx++)
|
for (int32 childIdx = 0; childIdx < editingProp.mListViewItem.GetChildCount(); childIdx++)
|
||||||
{
|
{
|
||||||
if (item == editingProp.mListViewItem.GetChildAtIndex(childIdx))
|
if (rootItem == editingProp.mListViewItem.GetChildAtIndex(childIdx))
|
||||||
{
|
{
|
||||||
if (childIdx >= entries.Count)
|
if (childIdx >= entries.Count)
|
||||||
entries.Add(new String(newValue));
|
entries.Add(new String(newValue));
|
||||||
|
@ -1027,6 +1046,11 @@ namespace IDE.ui
|
||||||
setValue = false;
|
setValue = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if ((curVariantType.IsObject) && (var multiValue = prevValue.Get<Object>() as IMultiValued))
|
||||||
|
{
|
||||||
|
multiValue.SetValue(mEditingListViewItem.mColumnIdx - 1, newValue);
|
||||||
|
setValue = false;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
editingProp.mCurValue = Variant.Create(new String(newValue), true);
|
editingProp.mCurValue = Variant.Create(new String(newValue), true);
|
||||||
|
|
||||||
|
@ -1247,37 +1271,49 @@ namespace IDE.ui
|
||||||
if (ewc.mIsMultiline)
|
if (ewc.mIsMultiline)
|
||||||
editWidget.InitScrollbars(false, true);
|
editWidget.InitScrollbars(false, true);
|
||||||
|
|
||||||
|
if (propEntry.mReadOnly)
|
||||||
|
editWidget.mEditWidgetContent.mIsReadOnly = true;
|
||||||
|
|
||||||
editWidget.mScrollContentInsets.Set(GS!(3), GS!(3), GS!(1), GS!(3));
|
editWidget.mScrollContentInsets.Set(GS!(3), GS!(3), GS!(1), GS!(3));
|
||||||
editWidget.Content.mTextInsets.Set(GS!(-3), GS!(2), 0, GS!(2));
|
editWidget.Content.mTextInsets.Set(GS!(-3), GS!(2), 0, GS!(2));
|
||||||
//editWidget.RehupSize();
|
//editWidget.RehupSize();
|
||||||
if (subValueIdx != -1)
|
if (subValueIdx != -1)
|
||||||
{
|
{
|
||||||
List<String> stringList = propEntry.mCurValue.Get<List<String>>();
|
var obj = propEntry.mCurValue.Get<Object>();
|
||||||
if (subValueIdx < stringList.Count)
|
if (var multiValued = obj as IMultiValued)
|
||||||
editWidget.SetText(stringList[subValueIdx]);
|
{
|
||||||
|
var label = multiValued.GetValue(subValueIdx, .. scope .());
|
||||||
|
editWidget.SetText(label);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
List<String> stringList = obj as List<String>;
|
||||||
|
if (subValueIdx < stringList.Count)
|
||||||
|
editWidget.SetText(stringList[subValueIdx]);
|
||||||
|
|
||||||
MoveItemWidget moveItemWidget;
|
MoveItemWidget moveItemWidget;
|
||||||
if (subValueIdx > 0)
|
if (subValueIdx > 0)
|
||||||
{
|
{
|
||||||
moveItemWidget = new MoveItemWidget();
|
moveItemWidget = new MoveItemWidget();
|
||||||
editWidget.AddWidget(moveItemWidget);
|
editWidget.AddWidget(moveItemWidget);
|
||||||
moveItemWidget.Resize(6, editWidget.mY - GS!(16), GS!(20), GS!(20));
|
moveItemWidget.Resize(6, editWidget.mY - GS!(16), GS!(20), GS!(20));
|
||||||
moveItemWidget.mArrowDir = -1;
|
moveItemWidget.mArrowDir = -1;
|
||||||
moveItemWidget.mOnMouseDown.Add(new (evt) => { MoveEditingItem(subValueIdx, -1); });
|
moveItemWidget.mOnMouseDown.Add(new (evt) => { MoveEditingItem(subValueIdx, -1); });
|
||||||
if (!ewc.mIsMultiline)
|
if (!ewc.mIsMultiline)
|
||||||
editWidget.mOnKeyDown.Add(new (evt) => { if (evt.mKeyCode == KeyCode.Up) MoveEditingItem(subValueIdx, -1); });
|
editWidget.mOnKeyDown.Add(new (evt) => { if (evt.mKeyCode == KeyCode.Up) MoveEditingItem(subValueIdx, -1); });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (subValueIdx < stringList.Count - 1)
|
if (subValueIdx < stringList.Count - 1)
|
||||||
{
|
{
|
||||||
moveItemWidget = new MoveItemWidget();
|
moveItemWidget = new MoveItemWidget();
|
||||||
editWidget.AddWidget(moveItemWidget);
|
editWidget.AddWidget(moveItemWidget);
|
||||||
moveItemWidget.Resize(6, editWidget.mY + GS!(16), GS!(20), GS!(20));
|
moveItemWidget.Resize(6, editWidget.mY + GS!(16), GS!(20), GS!(20));
|
||||||
moveItemWidget.mArrowDir = 1;
|
moveItemWidget.mArrowDir = 1;
|
||||||
moveItemWidget.mOnMouseDown.Add(new (evt) => { MoveEditingItem(subValueIdx, 1); });
|
moveItemWidget.mOnMouseDown.Add(new (evt) => { MoveEditingItem(subValueIdx, 1); });
|
||||||
if (!ewc.mIsMultiline)
|
if (!ewc.mIsMultiline)
|
||||||
editWidget.mOnKeyDown.Add(new (evt) => { if (evt.mKeyCode == KeyCode.Down) MoveEditingItem(subValueIdx, 1); });
|
editWidget.mOnKeyDown.Add(new (evt) => { if (evt.mKeyCode == KeyCode.Down) MoveEditingItem(subValueIdx, 1); });
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -1363,8 +1399,8 @@ namespace IDE.ui
|
||||||
hasChanged = true;
|
hasChanged = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (propEntry.mFieldInfo == default(FieldInfo))
|
/*if (propEntry.mFieldInfo == default(FieldInfo))
|
||||||
return;
|
return;*/
|
||||||
|
|
||||||
var curVariantType = propEntry.mCurValue.VariantType;
|
var curVariantType = propEntry.mCurValue.VariantType;
|
||||||
|
|
||||||
|
@ -1516,6 +1552,15 @@ namespace IDE.ui
|
||||||
valueItem.Label = allValues;
|
valueItem.Label = allValues;
|
||||||
FixLabel(valueItem);
|
FixLabel(valueItem);
|
||||||
}
|
}
|
||||||
|
else if ((curVariantType.IsObject) && (var multiValue = propEntry.mCurValue.Get<Object>() as IMultiValued))
|
||||||
|
{
|
||||||
|
for (int columnIdx in 1..<propEntry.mListViewItem.mSubItems.Count)
|
||||||
|
{
|
||||||
|
var subItem = propEntry.mListViewItem.GetSubItem(columnIdx);
|
||||||
|
var label = multiValue.GetValue(columnIdx - 1, .. scope .());
|
||||||
|
subItem.Label = label;
|
||||||
|
}
|
||||||
|
}
|
||||||
else if (propEntry.mCheckBox != null)
|
else if (propEntry.mCheckBox != null)
|
||||||
{
|
{
|
||||||
propEntry.mCheckBox.Checked = propEntry.mCurValue.Get<bool>();
|
propEntry.mCheckBox.Checked = propEntry.mCurValue.Get<bool>();
|
||||||
|
@ -2026,9 +2071,10 @@ namespace IDE.ui
|
||||||
clickedItem.mListView.GetRoot().SelectItemExclusively(null);
|
clickedItem.mListView.GetRoot().SelectItemExclusively(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
DarkListViewItem item = (DarkListViewItem)clickedItem.GetSubItem(0);
|
DarkListViewItem item = (DarkListViewItem)clickedItem;
|
||||||
|
DarkListViewItem rootItem = (DarkListViewItem)item.GetSubItem(0);
|
||||||
|
|
||||||
PropEntry[] propertyEntries = mPropPage.mPropEntries[item];
|
PropEntry[] propertyEntries = mPropPage.mPropEntries[rootItem];
|
||||||
if (propertyEntries[0].mDisabled)
|
if (propertyEntries[0].mDisabled)
|
||||||
return;
|
return;
|
||||||
EditValue(item, propertyEntries);
|
EditValue(item, propertyEntries);
|
||||||
|
@ -2039,7 +2085,7 @@ namespace IDE.ui
|
||||||
var propEntry = propEntries[0];
|
var propEntry = propEntries[0];
|
||||||
DarkListViewItem parentItem = propEntry.mListViewItem;
|
DarkListViewItem parentItem = propEntry.mListViewItem;
|
||||||
DarkListViewItem clickedItem = (DarkListViewItem)parentItem.GetChildAtIndex(idx);
|
DarkListViewItem clickedItem = (DarkListViewItem)parentItem.GetChildAtIndex(idx);
|
||||||
DarkListViewItem item = (DarkListViewItem)clickedItem.GetSubItem(0);
|
DarkListViewItem item = (DarkListViewItem)clickedItem.GetSubItem(1);
|
||||||
EditValue(item, propEntries, idx);
|
EditValue(item, propEntries, idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
179
IDE/src/ui/RemoteProjectDialog.bf
Normal file
179
IDE/src/ui/RemoteProjectDialog.bf
Normal file
|
@ -0,0 +1,179 @@
|
||||||
|
#pragma warning disable 168
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using System.IO;
|
||||||
|
using Beefy;
|
||||||
|
using Beefy.gfx;
|
||||||
|
using Beefy.theme.dark;
|
||||||
|
using Beefy.widgets;
|
||||||
|
using Beefy.theme;
|
||||||
|
using IDE.Util;
|
||||||
|
|
||||||
|
namespace IDE.ui
|
||||||
|
{
|
||||||
|
public class RemoteProjectDialog : IDEDialog
|
||||||
|
{
|
||||||
|
public EditWidget mURLEdit;
|
||||||
|
public EditWidget mVersionEdit;
|
||||||
|
public DarkComboBox mTargetComboBox;
|
||||||
|
static String[1] sApplicationTypeNames =
|
||||||
|
.("Git");
|
||||||
|
public bool mNameChanged;
|
||||||
|
public String mDirBase ~ delete _;
|
||||||
|
|
||||||
|
public this()
|
||||||
|
{
|
||||||
|
mTitle = new String("Add Remote Project");
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void CalcSize()
|
||||||
|
{
|
||||||
|
mWidth = GS!(320);
|
||||||
|
mHeight = GS!(200);
|
||||||
|
}
|
||||||
|
|
||||||
|
enum CreateFlags
|
||||||
|
{
|
||||||
|
None,
|
||||||
|
NonEmptyDirOkay = 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CreateProject(CreateFlags createFlags = .None)
|
||||||
|
{
|
||||||
|
var app = IDEApp.sApp;
|
||||||
|
String url = scope String();
|
||||||
|
mURLEdit.GetText(url);
|
||||||
|
url.Trim();
|
||||||
|
|
||||||
|
if (url.IsEmpty)
|
||||||
|
{
|
||||||
|
mURLEdit.SetFocus();
|
||||||
|
app.Fail("Invalid URL");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var projName = Path.GetFileName(url, .. scope .());
|
||||||
|
|
||||||
|
var version = mVersionEdit.GetText(.. scope .())..Trim();
|
||||||
|
|
||||||
|
var otherProject = app.mWorkspace.FindProject(projName);
|
||||||
|
if (otherProject != null)
|
||||||
|
{
|
||||||
|
mURLEdit.SetFocus();
|
||||||
|
app.Fail("A project with this name already exists in the workspace.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
VerSpec verSpec = .Git(url, scope .(version));
|
||||||
|
if (var project = gApp.AddProject(projName, verSpec))
|
||||||
|
{
|
||||||
|
//gApp.ProjectCreated(project);
|
||||||
|
app.mWorkspace.SetChanged();
|
||||||
|
|
||||||
|
gApp.[Friend]FlushDeferredLoadProjects(true);
|
||||||
|
//gApp.RetryProjectLoad(project, false);
|
||||||
|
//gApp.AddProjectToWorkspace(project);
|
||||||
|
|
||||||
|
var projectSpec = new Workspace.ProjectSpec();
|
||||||
|
projectSpec.mProjectName = new .(project.mProjectName);
|
||||||
|
projectSpec.mVerSpec = .Git(new .(url), new .(version));
|
||||||
|
gApp.mWorkspace.mProjectSpecs.Add(projectSpec);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateProjectName()
|
||||||
|
{
|
||||||
|
if (!mNameChanged)
|
||||||
|
{
|
||||||
|
String path = scope .();
|
||||||
|
mURLEdit.GetText(path);
|
||||||
|
path.Trim();
|
||||||
|
if ((path.EndsWith('\\')) || (path.EndsWith('/')))
|
||||||
|
path.RemoveFromEnd(1);
|
||||||
|
|
||||||
|
String projName = scope .();
|
||||||
|
Path.GetFileName(path, projName);
|
||||||
|
mVersionEdit.SetText(projName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Init()
|
||||||
|
{
|
||||||
|
mDefaultButton = AddButton("Create", new (evt) =>
|
||||||
|
{
|
||||||
|
if (!CreateProject()) evt.mCloseDialog = false;
|
||||||
|
});
|
||||||
|
mEscButton = AddButton("Cancel", new (evt) => Close());
|
||||||
|
|
||||||
|
if (gApp.mWorkspace.IsInitialized)
|
||||||
|
mDirBase = new String(gApp.mWorkspace.mDir);
|
||||||
|
else
|
||||||
|
mDirBase = new String();
|
||||||
|
mURLEdit = new DarkEditWidget();
|
||||||
|
|
||||||
|
AddEdit(mURLEdit);
|
||||||
|
mURLEdit.mOnContentChanged.Add(new (dlg) =>
|
||||||
|
{
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
mVersionEdit = AddEdit("");
|
||||||
|
mVersionEdit.mOnContentChanged.Add(new (dlg) =>
|
||||||
|
{
|
||||||
|
if (mVersionEdit.mHasFocus)
|
||||||
|
mNameChanged = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
mTargetComboBox = new DarkComboBox();
|
||||||
|
mTargetComboBox.Label = sApplicationTypeNames[0];
|
||||||
|
mTargetComboBox.mPopulateMenuAction.Add(new (dlg) =>
|
||||||
|
{
|
||||||
|
for (var applicationTypeName in sApplicationTypeNames)
|
||||||
|
{
|
||||||
|
var item = dlg.AddItem(applicationTypeName);
|
||||||
|
item.mOnMenuItemSelected.Add(new (item) =>
|
||||||
|
{
|
||||||
|
mTargetComboBox.Label = item.mLabel;
|
||||||
|
MarkDirty();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
AddWidget(mTargetComboBox);
|
||||||
|
mTabWidgets.Add(mTargetComboBox);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void PopupWindow(WidgetWindow parentWindow, float offsetX = 0, float offsetY = 0)
|
||||||
|
{
|
||||||
|
base.PopupWindow(parentWindow, offsetX, offsetY);
|
||||||
|
mURLEdit.SetFocus();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void ResizeComponents()
|
||||||
|
{
|
||||||
|
base.ResizeComponents();
|
||||||
|
|
||||||
|
float curY = mHeight - GS!(30) - mButtonBottomMargin;
|
||||||
|
mVersionEdit.Resize(GS!(16), curY - GS!(36), mWidth - GS!(16) * 2, GS!(24));
|
||||||
|
|
||||||
|
curY -= GS!(50);
|
||||||
|
mURLEdit.Resize(GS!(16), curY - GS!(36), mWidth - GS!(16) * 2, GS!(24));
|
||||||
|
|
||||||
|
curY -= GS!(60);
|
||||||
|
mTargetComboBox.Resize(GS!(16), curY - GS!(36), mWidth - GS!(16) * 2, GS!(28));
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Draw(Graphics g)
|
||||||
|
{
|
||||||
|
base.Draw(g);
|
||||||
|
|
||||||
|
g.DrawString("Remote Project URL", mURLEdit.mX, mURLEdit.mY - GS!(20));
|
||||||
|
g.DrawString("Version Constraint (Blank for HEAD)", mVersionEdit.mX, mVersionEdit.mY - GS!(20));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -414,7 +414,8 @@ namespace IDE.ui
|
||||||
|
|
||||||
if (mGettingSymbolInfo)
|
if (mGettingSymbolInfo)
|
||||||
{
|
{
|
||||||
gApp.Fail("Cannot rename symbols here");
|
if (gApp.mWorkspace.mProjectLoadState == .Loaded)
|
||||||
|
gApp.Fail("Cannot rename symbols here");
|
||||||
mGettingSymbolInfo = false;
|
mGettingSymbolInfo = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -430,6 +431,12 @@ namespace IDE.ui
|
||||||
if ((mKind == Kind.ShowFileReferences) || (mResolveParams.mLocalId != -1))
|
if ((mKind == Kind.ShowFileReferences) || (mResolveParams.mLocalId != -1))
|
||||||
{
|
{
|
||||||
mParser = IDEApp.sApp.mBfResolveSystem.FindParser(mSourceViewPanel.mProjectSource);
|
mParser = IDEApp.sApp.mBfResolveSystem.FindParser(mSourceViewPanel.mProjectSource);
|
||||||
|
if (mParser == null)
|
||||||
|
{
|
||||||
|
mGettingSymbolInfo = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if ((mResolveParams != null) && (mResolveParams.mLocalId != -1))
|
if ((mResolveParams != null) && (mResolveParams.mLocalId != -1))
|
||||||
mParser.SetAutocomplete(mCursorPos);
|
mParser.SetAutocomplete(mCursorPos);
|
||||||
else
|
else
|
||||||
|
|
|
@ -1932,7 +1932,7 @@ namespace IDE.ui
|
||||||
}
|
}
|
||||||
else if (resolveType == ResolveType.GetCurrentLocation)
|
else if (resolveType == ResolveType.GetCurrentLocation)
|
||||||
{
|
{
|
||||||
PrimaryNavigationBar.SetLocation(autocompleteInfo);
|
PrimaryNavigationBar.SetLocation(autocompleteInfo ?? "");
|
||||||
}
|
}
|
||||||
else if ((resolveType == .Autocomplete) || (resolveType == .GetFixits))
|
else if ((resolveType == .Autocomplete) || (resolveType == .GetFixits))
|
||||||
{
|
{
|
||||||
|
|
|
@ -22,7 +22,7 @@ namespace IDE.ui
|
||||||
public DarkButton mSafeModeButton;
|
public DarkButton mSafeModeButton;
|
||||||
public bool mWasCompiling;
|
public bool mWasCompiling;
|
||||||
public int mEvalCount;
|
public int mEvalCount;
|
||||||
public ImageWidget mCancelSymSrvButton;
|
public ImageWidget mCancelButton;
|
||||||
public int mDirtyDelay;
|
public int mDirtyDelay;
|
||||||
public int mStatusBoxUpdateCnt = -1;
|
public int mStatusBoxUpdateCnt = -1;
|
||||||
|
|
||||||
|
@ -117,8 +117,8 @@ namespace IDE.ui
|
||||||
mConfigComboBox.Resize(mWidth - btnLeft, GS!(0), GS!(120), GS!(24));
|
mConfigComboBox.Resize(mWidth - btnLeft, GS!(0), GS!(120), GS!(24));
|
||||||
mPlatformComboBox.Resize(mWidth - btnLeft - GS!(120), GS!(0), GS!(120), GS!(24));
|
mPlatformComboBox.Resize(mWidth - btnLeft - GS!(120), GS!(0), GS!(120), GS!(24));
|
||||||
|
|
||||||
if (mCancelSymSrvButton != null)
|
if (mCancelButton != null)
|
||||||
mCancelSymSrvButton.Resize(GS!(546), 0, GS!(20), GS!(20));
|
mCancelButton.Resize(GS!(546), 0, GS!(20), GS!(20));
|
||||||
|
|
||||||
if (mSafeModeButton != null)
|
if (mSafeModeButton != null)
|
||||||
{
|
{
|
||||||
|
@ -182,19 +182,31 @@ namespace IDE.ui
|
||||||
else
|
else
|
||||||
mEvalCount = 0;
|
mEvalCount = 0;
|
||||||
|
|
||||||
|
void ShowCancelButton()
|
||||||
|
{
|
||||||
|
if (mCancelButton == null)
|
||||||
|
{
|
||||||
|
mCancelButton = new ImageWidget();
|
||||||
|
mCancelButton.mImage = DarkTheme.sDarkTheme.GetImage(.Close);
|
||||||
|
mCancelButton.mOverImage = DarkTheme.sDarkTheme.GetImage(.CloseOver);
|
||||||
|
mCancelButton.mOnMouseClick.Add(new (evt) =>
|
||||||
|
{
|
||||||
|
if (gApp.mWorkspace.mProjectLoadState == .Preparing)
|
||||||
|
{
|
||||||
|
gApp.CancelWorkspaceLoading();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
gApp.mDebugger.CancelSymSrv();
|
||||||
|
});
|
||||||
|
AddWidget(mCancelButton);
|
||||||
|
ResizeComponents();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (debugState == .SearchingSymSrv)
|
if (debugState == .SearchingSymSrv)
|
||||||
{
|
{
|
||||||
MarkDirtyEx();
|
MarkDirtyEx();
|
||||||
|
ShowCancelButton();
|
||||||
if (mCancelSymSrvButton == null)
|
|
||||||
{
|
|
||||||
mCancelSymSrvButton = new ImageWidget();
|
|
||||||
mCancelSymSrvButton.mImage = DarkTheme.sDarkTheme.GetImage(.Close);
|
|
||||||
mCancelSymSrvButton.mOverImage = DarkTheme.sDarkTheme.GetImage(.CloseOver);
|
|
||||||
mCancelSymSrvButton.mOnMouseClick.Add(new (evt) => { gApp.mDebugger.CancelSymSrv(); });
|
|
||||||
AddWidget(mCancelSymSrvButton);
|
|
||||||
ResizeComponents();
|
|
||||||
}
|
|
||||||
|
|
||||||
float len = GS!(200);
|
float len = GS!(200);
|
||||||
float x = GS!(350);
|
float x = GS!(350);
|
||||||
|
@ -209,15 +221,45 @@ namespace IDE.ui
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (gApp.mWorkspace.mProjectLoadState == .Preparing)
|
||||||
|
{
|
||||||
|
MarkDirtyEx();
|
||||||
|
ShowCancelButton();
|
||||||
|
|
||||||
|
float len = GS!(200);
|
||||||
|
float x = GS!(350);
|
||||||
|
Rect completionRect = Rect(x, GS!(1), len, GS!(17));
|
||||||
|
|
||||||
|
String status = scope .();
|
||||||
|
|
||||||
|
for (var workItem in gApp.mPackMan.mWorkItems)
|
||||||
|
{
|
||||||
|
if (workItem.mGitInstance == null)
|
||||||
|
break;
|
||||||
|
|
||||||
|
//DrawCompletion(workItem.mGitInstance.mProgress);
|
||||||
|
status.AppendF($"Retrieving {workItem.mProjectName}: {(int)(workItem.mGitInstance.mProgress * 100)}%");
|
||||||
|
}
|
||||||
|
|
||||||
|
Point mousePos;
|
||||||
|
if (DarkTooltipManager.CheckMouseover(this, 25, out mousePos, true))
|
||||||
|
{
|
||||||
|
if (completionRect.Contains(mousePos.x, mousePos.y))
|
||||||
|
{
|
||||||
|
if (!status.IsEmpty)
|
||||||
|
DarkTooltipManager.ShowTooltip(status, this, mousePos.x, mousePos.y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if ((DarkTooltipManager.sTooltip != null) && (DarkTooltipManager.sTooltip.mRelWidget == this))
|
if ((DarkTooltipManager.sTooltip != null) && (DarkTooltipManager.sTooltip.mRelWidget == this))
|
||||||
DarkTooltipManager.sTooltip.Close();
|
DarkTooltipManager.sTooltip.Close();
|
||||||
|
|
||||||
if (mCancelSymSrvButton != null)
|
if (mCancelButton != null)
|
||||||
{
|
{
|
||||||
RemoveAndDelete(mCancelSymSrvButton);
|
RemoveAndDelete(mCancelButton);
|
||||||
mCancelSymSrvButton = null;
|
mCancelButton = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -367,6 +409,16 @@ namespace IDE.ui
|
||||||
|
|
||||||
float statusLabelPos = (int)GS!(-1.3f);
|
float statusLabelPos = (int)GS!(-1.3f);
|
||||||
|
|
||||||
|
void DrawCompletion(float pct)
|
||||||
|
{
|
||||||
|
Rect completionRect = Rect(GS!(200), GS!(2), GS!(120), GS!(15));
|
||||||
|
using (g.PushColor(0xFF000000))
|
||||||
|
g.FillRect(completionRect.mX, completionRect.mY, completionRect.mWidth, completionRect.mHeight);
|
||||||
|
completionRect.Inflate(GS!(-1), GS!(-1));
|
||||||
|
using (g.PushColor(0xFF00FF00))
|
||||||
|
g.FillRect(completionRect.mX, completionRect.mY, completionRect.mWidth * pct, completionRect.mHeight);
|
||||||
|
}
|
||||||
|
|
||||||
//completionPct = 0.4f;
|
//completionPct = 0.4f;
|
||||||
if ((gApp.mDebugger?.mIsComptimeDebug == true) &&
|
if ((gApp.mDebugger?.mIsComptimeDebug == true) &&
|
||||||
((gApp.mDebugger.IsPaused()) || (debugState == .DebugEval)))
|
((gApp.mDebugger.IsPaused()) || (debugState == .DebugEval)))
|
||||||
|
@ -375,12 +427,7 @@ namespace IDE.ui
|
||||||
}
|
}
|
||||||
else if (completionPct.HasValue)
|
else if (completionPct.HasValue)
|
||||||
{
|
{
|
||||||
Rect completionRect = Rect(GS!(200), GS!(2), GS!(120), GS!(15));
|
DrawCompletion(completionPct.Value);
|
||||||
using (g.PushColor(0xFF000000))
|
|
||||||
g.FillRect(completionRect.mX, completionRect.mY, completionRect.mWidth, completionRect.mHeight);
|
|
||||||
completionRect.Inflate(GS!(-1), GS!(-1));
|
|
||||||
using (g.PushColor(0xFF00FF00))
|
|
||||||
g.FillRect(completionRect.mX, completionRect.mY, completionRect.mWidth * completionPct.Value, completionRect.mHeight);
|
|
||||||
}
|
}
|
||||||
else if ((gApp.mDebugger.mIsRunning) && (gApp.HaveSourcesChanged()))
|
else if ((gApp.mDebugger.mIsRunning) && (gApp.HaveSourcesChanged()))
|
||||||
{
|
{
|
||||||
|
@ -394,7 +441,7 @@ namespace IDE.ui
|
||||||
g.DrawString("Source Changed", GS!(200), statusLabelPos, FontAlign.Centered, GS!(120));
|
g.DrawString("Source Changed", GS!(200), statusLabelPos, FontAlign.Centered, GS!(120));
|
||||||
}
|
}
|
||||||
|
|
||||||
void DrawStatusBox(StringView str, int32 updateCnt = -1)
|
void DrawStatusBox(StringView str, int32 updateCnt = -1, bool showCancelButton = false)
|
||||||
{
|
{
|
||||||
if (mStatusBoxUpdateCnt == -1)
|
if (mStatusBoxUpdateCnt == -1)
|
||||||
mStatusBoxUpdateCnt = 0;
|
mStatusBoxUpdateCnt = 0;
|
||||||
|
@ -415,8 +462,18 @@ namespace IDE.ui
|
||||||
using (g.PushColor(Color.FromHSV(0.1f, 0.5f, (float)Math.Max(pulsePct * 0.15f + 0.3f, 0.3f))))
|
using (g.PushColor(Color.FromHSV(0.1f, 0.5f, (float)Math.Max(pulsePct * 0.15f + 0.3f, 0.3f))))
|
||||||
g.FillRect(completionRect.mX, completionRect.mY, completionRect.mWidth, completionRect.mHeight);
|
g.FillRect(completionRect.mX, completionRect.mY, completionRect.mWidth, completionRect.mHeight);
|
||||||
|
|
||||||
if (mCancelSymSrvButton != null)
|
if (mCancelButton != null)
|
||||||
mCancelSymSrvButton.mX = completionRect.Right - GS!(16);
|
{
|
||||||
|
if (showCancelButton)
|
||||||
|
{
|
||||||
|
mCancelButton.SetVisible(true);
|
||||||
|
mCancelButton.mX = completionRect.Right - GS!(16);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
mCancelButton.SetVisible(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
using (g.PushColor(DarkTheme.COLOR_TEXT))
|
using (g.PushColor(DarkTheme.COLOR_TEXT))
|
||||||
g.DrawString(str, x, statusLabelPos, FontAlign.Centered, len);
|
g.DrawString(str, x, statusLabelPos, FontAlign.Centered, len);
|
||||||
|
@ -429,10 +486,6 @@ namespace IDE.ui
|
||||||
chordState.Append(", <Awaiting Key>...");
|
chordState.Append(", <Awaiting Key>...");
|
||||||
DrawStatusBox(chordState);
|
DrawStatusBox(chordState);
|
||||||
}
|
}
|
||||||
else if (mCancelSymSrvButton != null)
|
|
||||||
{
|
|
||||||
DrawStatusBox("Retrieving Debug Symbols... ");
|
|
||||||
}
|
|
||||||
else if (mEvalCount > 20)
|
else if (mEvalCount > 20)
|
||||||
{
|
{
|
||||||
DrawStatusBox("Evaluating Expression");
|
DrawStatusBox("Evaluating Expression");
|
||||||
|
@ -451,10 +504,16 @@ namespace IDE.ui
|
||||||
}
|
}
|
||||||
else if (gApp.mWorkspace.mProjectLoadState == .Preparing)
|
else if (gApp.mWorkspace.mProjectLoadState == .Preparing)
|
||||||
{
|
{
|
||||||
DrawStatusBox("Loading Projects");
|
DrawStatusBox("Loading Projects", -1, true);
|
||||||
|
}
|
||||||
|
else if (mCancelButton != null)
|
||||||
|
{
|
||||||
|
DrawStatusBox("Retrieving Debug Symbols... ", -1, true);
|
||||||
}
|
}
|
||||||
else if (gApp.mDeferredShowSource != null)
|
else if (gApp.mDeferredShowSource != null)
|
||||||
|
{
|
||||||
DrawStatusBox("Queued Showing Source");
|
DrawStatusBox("Queued Showing Source");
|
||||||
|
}
|
||||||
else
|
else
|
||||||
mStatusBoxUpdateCnt = -1;
|
mStatusBoxUpdateCnt = -1;
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,7 @@ using Beefy.theme.dark;
|
||||||
using Beefy.theme;
|
using Beefy.theme;
|
||||||
using Beefy.events;
|
using Beefy.events;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
using IDE.Util;
|
||||||
|
|
||||||
//#define A
|
//#define A
|
||||||
//#define B
|
//#define B
|
||||||
|
@ -40,6 +41,7 @@ namespace IDE.ui
|
||||||
enum CategoryType
|
enum CategoryType
|
||||||
{
|
{
|
||||||
General,
|
General,
|
||||||
|
Dependencies,
|
||||||
Beef_Global,
|
Beef_Global,
|
||||||
|
|
||||||
Targeted,
|
Targeted,
|
||||||
|
@ -53,6 +55,7 @@ namespace IDE.ui
|
||||||
|
|
||||||
ConfigDataGroup mCurConfigDataGroup;
|
ConfigDataGroup mCurConfigDataGroup;
|
||||||
Workspace.Options[] mCurWorkspaceOptions ~ delete _;
|
Workspace.Options[] mCurWorkspaceOptions ~ delete _;
|
||||||
|
List<String> mUpdateProjectLocks = new .() ~ DeleteContainerAndItems!(_);
|
||||||
|
|
||||||
public this()
|
public this()
|
||||||
{
|
{
|
||||||
|
@ -62,8 +65,9 @@ namespace IDE.ui
|
||||||
|
|
||||||
var root = (DarkListViewItem)mCategorySelector.GetRoot();
|
var root = (DarkListViewItem)mCategorySelector.GetRoot();
|
||||||
var globalItem = AddCategoryItem(root, "General");
|
var globalItem = AddCategoryItem(root, "General");
|
||||||
var item = AddCategoryItem(globalItem, "Beef");
|
var item = AddCategoryItem(globalItem, "Dependencies");
|
||||||
item.Focused = true;
|
item.Focused = true;
|
||||||
|
AddCategoryItem(globalItem, "Beef");
|
||||||
globalItem.Open(true, true);
|
globalItem.Open(true, true);
|
||||||
|
|
||||||
var targetedItem = AddCategoryItem(root, "Targeted");
|
var targetedItem = AddCategoryItem(root, "Targeted");
|
||||||
|
@ -124,6 +128,7 @@ namespace IDE.ui
|
||||||
{
|
{
|
||||||
case .General,
|
case .General,
|
||||||
//.Targeted,
|
//.Targeted,
|
||||||
|
.Dependencies,
|
||||||
.Beef_Global:
|
.Beef_Global:
|
||||||
return .None;
|
return .None;
|
||||||
default:
|
default:
|
||||||
|
@ -454,7 +459,9 @@ namespace IDE.ui
|
||||||
mPropPage.mPropertiesListView.mShowColumnGrid = true;
|
mPropPage.mPropertiesListView.mShowColumnGrid = true;
|
||||||
mPropPage.mPropertiesListView.mShowGridLines = true;
|
mPropPage.mPropertiesListView.mShowGridLines = true;
|
||||||
|
|
||||||
if (categoryType == CategoryType.Beef_Global)
|
if (categoryType == CategoryType.Dependencies)
|
||||||
|
PopulateDependencyOptions();
|
||||||
|
else if (categoryType == CategoryType.Beef_Global)
|
||||||
PopulateBeefGlobalOptions();
|
PopulateBeefGlobalOptions();
|
||||||
else if (categoryType == CategoryType.Build)
|
else if (categoryType == CategoryType.Build)
|
||||||
PopulateBuildOptions();
|
PopulateBuildOptions();
|
||||||
|
@ -705,6 +712,230 @@ namespace IDE.ui
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PopulateDependencyOptions()
|
||||||
|
{
|
||||||
|
mPropPage.mPropertiesListView.mColumns[0].Label = "Project";
|
||||||
|
mPropPage.mPropertiesListView.mColumns[0].mMinWidth = GS!(100);
|
||||||
|
mPropPage.mPropertiesListView.mColumns[0].mWidth = GS!(180);
|
||||||
|
|
||||||
|
mPropPage.mPropertiesListView.mColumns[1].Label = "";
|
||||||
|
mPropPage.mPropertiesListView.mColumns[1].mMinWidth = GS!(20);
|
||||||
|
mPropPage.mPropertiesListView.mColumns[1].mWidth = GS!(20);
|
||||||
|
|
||||||
|
mPropPage.mPropertiesListView.AddColumn(180, "Remote URL");
|
||||||
|
mPropPage.mPropertiesListView.mColumns[2].mMinWidth = GS!(100);
|
||||||
|
|
||||||
|
mPropPage.mPropertiesListView.AddColumn(180, "Ver Constraint");
|
||||||
|
mPropPage.mPropertiesListView.mColumns[3].mMinWidth = GS!(100);
|
||||||
|
|
||||||
|
//mDependencyValuesMap = new .();
|
||||||
|
|
||||||
|
var root = (DarkListViewItem)mPropPage.mPropertiesListView.GetRoot();
|
||||||
|
var category = root;
|
||||||
|
|
||||||
|
List<String> projectNames = scope List<String>();
|
||||||
|
for (int32 projectIdx = 0; projectIdx < IDEApp.sApp.mWorkspace.mProjects.Count; projectIdx++)
|
||||||
|
{
|
||||||
|
var project = IDEApp.sApp.mWorkspace.mProjects[projectIdx];
|
||||||
|
/*if (project == mProject)
|
||||||
|
continue;*/
|
||||||
|
projectNames.Add(project.mProjectName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*for (var dep in mProject.mDependencies)
|
||||||
|
{
|
||||||
|
if (!projectNames.Contains(dep.mProjectName))
|
||||||
|
projectNames.Add(dep.mProjectName);
|
||||||
|
}*/
|
||||||
|
|
||||||
|
|
||||||
|
projectNames.Sort(scope (a, b) => String.Compare(a, b, true));
|
||||||
|
|
||||||
|
for (var projectName in projectNames)
|
||||||
|
{
|
||||||
|
var dependencyEntry = new DependencyEntry();
|
||||||
|
|
||||||
|
for (var projectSpec in gApp.mWorkspace.mProjectSpecs)
|
||||||
|
{
|
||||||
|
if (projectSpec.mProjectName == projectName)
|
||||||
|
{
|
||||||
|
dependencyEntry.mUse = true;
|
||||||
|
if (projectSpec.mVerSpec case .Git(let url, let ver))
|
||||||
|
{
|
||||||
|
dependencyEntry.mURL = new .(url);
|
||||||
|
if (ver != null)
|
||||||
|
dependencyEntry.mVersion = new .(ver.mVersion);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*var verSpec = mProject.GetDependency(projectName, false);
|
||||||
|
if (verSpec != null)
|
||||||
|
{
|
||||||
|
dependencyEntry.mUse = true;
|
||||||
|
if (verSpec case .Git(let url, let ver))
|
||||||
|
{
|
||||||
|
dependencyEntry.mURL = new .(url);
|
||||||
|
if (ver != null)
|
||||||
|
dependencyEntry.mVersion = new .(ver.mVersion);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mDependencyValuesMap[new String(projectName)] = dependencyEntry;*/
|
||||||
|
|
||||||
|
var (listViewItem, propItem) = AddPropertiesItem(category, projectName);
|
||||||
|
if (IDEApp.sApp.mWorkspace.FindProject(projectName) == null)
|
||||||
|
listViewItem.mTextColor = Color.Mult(DarkTheme.COLOR_TEXT, 0xFFFF6060);
|
||||||
|
|
||||||
|
var subItem = (DarkListViewItem)listViewItem.CreateSubItem(1);
|
||||||
|
|
||||||
|
var checkbox = new DarkCheckBox();
|
||||||
|
checkbox.Checked = dependencyEntry.mUse;
|
||||||
|
checkbox.Resize(0, 0, DarkTheme.sUnitSize, DarkTheme.sUnitSize);
|
||||||
|
subItem.AddWidget(checkbox);
|
||||||
|
|
||||||
|
PropEntry[] propEntries = new PropEntry[1];
|
||||||
|
|
||||||
|
PropEntry propEntry = new PropEntry();
|
||||||
|
propEntry.mTarget = dependencyEntry;
|
||||||
|
propEntry.mOrigValue = Variant.Create(dependencyEntry, true);
|
||||||
|
propEntry.mCurValue = Variant.Create(new DependencyEntry(dependencyEntry), true);
|
||||||
|
|
||||||
|
propEntry.mListViewItem = listViewItem;
|
||||||
|
propEntry.mCheckBox = checkbox;
|
||||||
|
propEntry.mApplyAction = new () =>
|
||||||
|
{
|
||||||
|
bool updateProjectLock = false;
|
||||||
|
|
||||||
|
var dependencyEntry = propEntry.mCurValue.Get<DependencyEntry>();
|
||||||
|
|
||||||
|
VerSpec verSpec = default;
|
||||||
|
if (dependencyEntry.mUse)
|
||||||
|
{
|
||||||
|
if (dependencyEntry.mURL != null)
|
||||||
|
verSpec = .Git(new .(dependencyEntry.mURL), (dependencyEntry.mVersion != null) ? new .(dependencyEntry.mVersion) : null);
|
||||||
|
else if (dependencyEntry.mVersion != null)
|
||||||
|
verSpec = .SemVer(new .(dependencyEntry.mVersion));
|
||||||
|
else
|
||||||
|
verSpec = .SemVer(new .("*"));
|
||||||
|
}
|
||||||
|
|
||||||
|
FindBlock: do
|
||||||
|
{
|
||||||
|
for (var projectSpec in gApp.mWorkspace.mProjectSpecs)
|
||||||
|
{
|
||||||
|
if (projectSpec.mProjectName == projectName)
|
||||||
|
{
|
||||||
|
if (!dependencyEntry.mUse)
|
||||||
|
{
|
||||||
|
if (projectSpec.mVerSpec case .Git)
|
||||||
|
updateProjectLock = true;
|
||||||
|
@projectSpec.Remove();
|
||||||
|
delete projectSpec;
|
||||||
|
break FindBlock;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (projectSpec.mVerSpec != verSpec)
|
||||||
|
{
|
||||||
|
if ((projectSpec.mVerSpec case .Git) ||
|
||||||
|
(verSpec case .Git))
|
||||||
|
updateProjectLock = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
projectSpec.mVerSpec.Dispose();
|
||||||
|
projectSpec.mVerSpec = verSpec;
|
||||||
|
break FindBlock;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dependencyEntry.mUse)
|
||||||
|
{
|
||||||
|
Workspace.ProjectSpec projectSpec = new .();
|
||||||
|
projectSpec.mProjectName = new .(projectName);
|
||||||
|
projectSpec.mVerSpec = verSpec;
|
||||||
|
gApp.mWorkspace.mProjectSpecs.Add(projectSpec);
|
||||||
|
if (verSpec case .Git)
|
||||||
|
updateProjectLock = true;
|
||||||
|
var origDependencyEntry = propEntry.mOrigValue.Get<DependencyEntry>();
|
||||||
|
origDependencyEntry.Set(dependencyEntry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (updateProjectLock)
|
||||||
|
mUpdateProjectLocks.Add(new .(listViewItem.Label));
|
||||||
|
};
|
||||||
|
|
||||||
|
checkbox.mOnMouseUp.Add(new (evt) =>
|
||||||
|
{
|
||||||
|
var dependencyEntry = propEntry.mCurValue.Get<DependencyEntry>();
|
||||||
|
dependencyEntry.mUse = !dependencyEntry.mUse;
|
||||||
|
if (dependencyEntry.mUse)
|
||||||
|
{
|
||||||
|
var projectName = listViewItem.Label;
|
||||||
|
|
||||||
|
for (var projectSpec in gApp.mWorkspace.mProjectSpecs)
|
||||||
|
{
|
||||||
|
if (projectSpec.mProjectName == projectName)
|
||||||
|
{
|
||||||
|
if (projectSpec.mVerSpec case .Git(let url, let ver))
|
||||||
|
{
|
||||||
|
dependencyEntry.SetValue(1, url);
|
||||||
|
dependencyEntry.SetValue(2, ver.mVersion);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var propEntries = mPropPage.mPropEntries[listViewItem];
|
||||||
|
UpdatePropertyValue(propEntries);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DeleteAndNullify!(dependencyEntry.mURL);
|
||||||
|
DeleteAndNullify!(dependencyEntry.mVersion);
|
||||||
|
var propEntries = mPropPage.mPropEntries[listViewItem];
|
||||||
|
UpdatePropertyValue(propEntries);
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
subItem = (.)listViewItem.GetOrCreateSubItem(2);
|
||||||
|
if (dependencyEntry.mURL != null)
|
||||||
|
subItem.Label = dependencyEntry.mURL;
|
||||||
|
subItem.mOnMouseDown.Add(new => DepPropValueClicked);
|
||||||
|
|
||||||
|
subItem = (.)listViewItem.GetOrCreateSubItem(3);
|
||||||
|
if (dependencyEntry.mVersion != null)
|
||||||
|
subItem.Label = dependencyEntry.mVersion;
|
||||||
|
subItem.mOnMouseDown.Add(new => DepPropValueClicked);
|
||||||
|
|
||||||
|
propEntries[0] = propEntry;
|
||||||
|
mPropPage.mPropEntries[listViewItem] = propEntries;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void DepPropValueClicked(MouseEvent theEvent)
|
||||||
|
{
|
||||||
|
DarkListViewItem clickedItem = (DarkListViewItem)theEvent.mSender;
|
||||||
|
if (clickedItem.mColumnIdx == 0)
|
||||||
|
{
|
||||||
|
clickedItem.mListView.SetFocus();
|
||||||
|
clickedItem.mListView.GetRoot().SelectItemExclusively(clickedItem);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (theEvent.mX != -1)
|
||||||
|
{
|
||||||
|
clickedItem.mListView.GetRoot().SelectItemExclusively(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
DarkListViewItem item = (DarkListViewItem)clickedItem;
|
||||||
|
DarkListViewItem rootItem = (DarkListViewItem)clickedItem.GetSubItem(0);
|
||||||
|
|
||||||
|
PropEntry[] propertyEntries = mPropPage.mPropEntries[rootItem];
|
||||||
|
if (propertyEntries[0].mDisabled)
|
||||||
|
return;
|
||||||
|
EditValue(item, propertyEntries, clickedItem.mColumnIdx - 1);
|
||||||
|
}
|
||||||
|
|
||||||
void PopulateBeefGlobalOptions()
|
void PopulateBeefGlobalOptions()
|
||||||
{
|
{
|
||||||
var root = (DarkListViewItem)mPropPage.mPropertiesListView.GetRoot();
|
var root = (DarkListViewItem)mPropPage.mPropertiesListView.GetRoot();
|
||||||
|
@ -939,6 +1170,7 @@ namespace IDE.ui
|
||||||
{
|
{
|
||||||
base.Close();
|
base.Close();
|
||||||
SetWorkspaceData(false);
|
SetWorkspaceData(false);
|
||||||
|
gApp.NotifyProjectVersionLocks(mUpdateProjectLocks);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void CalcSize()
|
public override void CalcSize()
|
||||||
|
|
326
IDE/src/util/GitManager.bf
Normal file
326
IDE/src/util/GitManager.bf
Normal file
|
@ -0,0 +1,326 @@
|
||||||
|
#pragma warning disable 168
|
||||||
|
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System;
|
||||||
|
using System.Threading;
|
||||||
|
using System.IO;
|
||||||
|
using System.Collections;
|
||||||
|
|
||||||
|
namespace IDE.util;
|
||||||
|
|
||||||
|
class GitManager
|
||||||
|
{
|
||||||
|
public enum Error
|
||||||
|
{
|
||||||
|
Unknown
|
||||||
|
}
|
||||||
|
|
||||||
|
public class GitInstance : RefCounted
|
||||||
|
{
|
||||||
|
public class TagInfo
|
||||||
|
{
|
||||||
|
public String mHash ~ delete _;
|
||||||
|
public String mTag ~ delete _;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GitManager mGitManager;
|
||||||
|
public bool mFailed;
|
||||||
|
public bool mDone;
|
||||||
|
public bool mStarted;
|
||||||
|
public bool mRemoved;
|
||||||
|
|
||||||
|
public String mArgs ~ delete _;
|
||||||
|
public String mPath ~ delete _;
|
||||||
|
public float mProgress;
|
||||||
|
public float mProgressRecv;
|
||||||
|
public float mProgressDeltas;
|
||||||
|
public float mProgressFiles;
|
||||||
|
|
||||||
|
public Stopwatch mStopwatch = new .()..Start() ~ delete _;
|
||||||
|
|
||||||
|
public SpawnedProcess mProcess ~ delete _;
|
||||||
|
public Monitor mMonitor = new .() ~ delete _;
|
||||||
|
public List<String> mDeferredOutput = new .() ~ DeleteContainerAndItems!(_);
|
||||||
|
public List<TagInfo> mTagInfos = new .() ~ DeleteContainerAndItems!(_);
|
||||||
|
|
||||||
|
public Thread mOutputThread ~ delete _;
|
||||||
|
public Thread mErrorThread ~ delete _;
|
||||||
|
|
||||||
|
public this(GitManager gitManager)
|
||||||
|
{
|
||||||
|
mGitManager = gitManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ~this()
|
||||||
|
{
|
||||||
|
IDEUtils.SafeKill(mProcess);
|
||||||
|
mOutputThread?.Join();
|
||||||
|
mErrorThread?.Join();
|
||||||
|
|
||||||
|
if (!mRemoved)
|
||||||
|
mGitManager.mGitInstances.Remove(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Init(StringView args, StringView path)
|
||||||
|
{
|
||||||
|
mArgs = new .(args);
|
||||||
|
if (path != default)
|
||||||
|
mPath = new .(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Start()
|
||||||
|
{
|
||||||
|
if (mStarted)
|
||||||
|
return;
|
||||||
|
mStarted = true;
|
||||||
|
|
||||||
|
ProcessStartInfo psi = scope ProcessStartInfo();
|
||||||
|
|
||||||
|
String gitPath = scope .();
|
||||||
|
#if BF_PLATFORM_WINDOWS
|
||||||
|
Path.GetAbsolutePath(gApp.mInstallDir, "git/cmd/git.exe", gitPath);
|
||||||
|
if (!File.Exists(gitPath))
|
||||||
|
gitPath.Clear();
|
||||||
|
|
||||||
|
if (gitPath.IsEmpty)
|
||||||
|
{
|
||||||
|
Path.GetAbsolutePath(gApp.mInstallDir, "../../bin/git/cmd/git.exe", gitPath);
|
||||||
|
if (!File.Exists(gitPath))
|
||||||
|
gitPath.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gitPath.IsEmpty)
|
||||||
|
{
|
||||||
|
Path.GetAbsolutePath(gApp.mInstallDir, "../../../bin/git/cmd/git.exe", gitPath);
|
||||||
|
if (!File.Exists(gitPath))
|
||||||
|
gitPath.Clear();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (gitPath.IsEmpty)
|
||||||
|
gitPath.Set("git");
|
||||||
|
|
||||||
|
psi.SetFileName(gitPath);
|
||||||
|
psi.SetArguments(mArgs);
|
||||||
|
if (mPath != null)
|
||||||
|
psi.SetWorkingDirectory(mPath);
|
||||||
|
psi.UseShellExecute = false;
|
||||||
|
psi.RedirectStandardError = true;
|
||||||
|
psi.RedirectStandardOutput = true;
|
||||||
|
psi.CreateNoWindow = true;
|
||||||
|
|
||||||
|
mProcess = new SpawnedProcess();
|
||||||
|
if (mProcess.Start(psi) case .Err)
|
||||||
|
{
|
||||||
|
gApp.OutputErrorLine("Failed to execute Git");
|
||||||
|
mFailed = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mOutputThread = new Thread(new => ReadOutputThread);
|
||||||
|
mOutputThread.Start(false);
|
||||||
|
|
||||||
|
mErrorThread = new Thread(new => ReadErrorThread);
|
||||||
|
mErrorThread.Start(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ReadOutputThread()
|
||||||
|
{
|
||||||
|
FileStream fileStream = scope FileStream();
|
||||||
|
if (mProcess.AttachStandardOutput(fileStream) case .Err)
|
||||||
|
return;
|
||||||
|
StreamReader streamReader = scope StreamReader(fileStream, null, false, 4096);
|
||||||
|
|
||||||
|
int count = 0;
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
count++;
|
||||||
|
var buffer = scope String();
|
||||||
|
if (streamReader.ReadLine(buffer) case .Err)
|
||||||
|
break;
|
||||||
|
using (mMonitor.Enter())
|
||||||
|
{
|
||||||
|
mDeferredOutput.Add(new .(buffer));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ReadErrorThread()
|
||||||
|
{
|
||||||
|
FileStream fileStream = scope FileStream();
|
||||||
|
if (mProcess.AttachStandardError(fileStream) case .Err)
|
||||||
|
return;
|
||||||
|
StreamReader streamReader = scope StreamReader(fileStream, null, false, 4096);
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
var buffer = scope String();
|
||||||
|
if (streamReader.ReadLine(buffer) case .Err)
|
||||||
|
break;
|
||||||
|
|
||||||
|
using (mMonitor.Enter())
|
||||||
|
{
|
||||||
|
//mDeferredOutput.Add(new $"{mStopwatch.ElapsedMilliseconds / 1000.0:0.0}: {buffer}");
|
||||||
|
mDeferredOutput.Add(new .(buffer));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Update()
|
||||||
|
{
|
||||||
|
using (mMonitor.Enter())
|
||||||
|
{
|
||||||
|
while (!mDeferredOutput.IsEmpty)
|
||||||
|
{
|
||||||
|
var line = mDeferredOutput.PopFront();
|
||||||
|
defer delete line;
|
||||||
|
//Debug.WriteLine($"GIT: {line}");
|
||||||
|
|
||||||
|
if (line.StartsWith("Cloning into "))
|
||||||
|
{
|
||||||
|
// May be starting a submodule
|
||||||
|
mProgressRecv = 0;
|
||||||
|
mProgressDeltas = 0;
|
||||||
|
mProgressFiles = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (line.StartsWith("remote: Counting objects"))
|
||||||
|
{
|
||||||
|
mProgressRecv = 0.001f;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (line.StartsWith("Receiving objects: "))
|
||||||
|
{
|
||||||
|
var pctStr = line.Substring("Receiving objects: ".Length, 3)..Trim();
|
||||||
|
mProgressRecv = float.Parse(pctStr).GetValueOrDefault() / 100.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (line.StartsWith("Resolving deltas: "))
|
||||||
|
{
|
||||||
|
var pctStr = line.Substring("Resolving deltas: ".Length, 3)..Trim();
|
||||||
|
mProgressDeltas = float.Parse(pctStr).GetValueOrDefault() / 100.0f;
|
||||||
|
mProgressRecv = 1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (line.StartsWith("Updating files: "))
|
||||||
|
{
|
||||||
|
var pctStr = line.Substring("Updating files: ".Length, 3)..Trim();
|
||||||
|
mProgressFiles = float.Parse(pctStr).GetValueOrDefault() / 100.0f;
|
||||||
|
mProgressRecv = 1.0f;
|
||||||
|
mProgressDeltas = 1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
StringView version = default;
|
||||||
|
|
||||||
|
int refTagIdx = line.IndexOf("\trefs/tags/");
|
||||||
|
if (refTagIdx == 40)
|
||||||
|
version = line.Substring(40 + "\trefs/tags/".Length);
|
||||||
|
|
||||||
|
if ((line.Length == 45) && (line.EndsWith("HEAD")))
|
||||||
|
version = "HEAD";
|
||||||
|
|
||||||
|
if (!version.IsEmpty)
|
||||||
|
{
|
||||||
|
TagInfo tagInfo = new .();
|
||||||
|
tagInfo.mHash = new .(line, 0, 40);
|
||||||
|
tagInfo.mTag = new .(version);
|
||||||
|
mTagInfos.Add(tagInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float pct = 0;
|
||||||
|
if (mProgressRecv > 0)
|
||||||
|
pct = 0.1f + (mProgressRecv * 0.3f) + (mProgressDeltas * 0.4f) + (mProgressFiles * 0.2f);
|
||||||
|
|
||||||
|
if (pct > mProgress)
|
||||||
|
{
|
||||||
|
mProgress = pct;
|
||||||
|
//Debug.WriteLine($"Completed Pct: {pct}");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mProcess.WaitFor(0))
|
||||||
|
{
|
||||||
|
if (mProcess.ExitCode != 0)
|
||||||
|
mFailed = true;
|
||||||
|
mDone = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Cancel()
|
||||||
|
{
|
||||||
|
if (!mProcess.WaitFor(0))
|
||||||
|
{
|
||||||
|
//Debug.WriteLine($"GitManager Cancel {mProcess.ProcessId}");
|
||||||
|
IDEUtils.SafeKill(mProcess);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public const int sMaxActiveGitInstances = 4;
|
||||||
|
|
||||||
|
public List<GitInstance> mGitInstances = new .() ~
|
||||||
|
{
|
||||||
|
for (var gitInstance in _)
|
||||||
|
gitInstance.ReleaseRef();
|
||||||
|
delete _;
|
||||||
|
};
|
||||||
|
|
||||||
|
public void Init()
|
||||||
|
{
|
||||||
|
//StartGit("-v");
|
||||||
|
|
||||||
|
//Repository repository = Clone("https://github.com/llvm/llvm-project", "c:/temp/__LLVM");
|
||||||
|
|
||||||
|
//Repository repository = Clone("https://github.com/Starpelly/raylib-beef", "c:/temp/__RAYLIB");
|
||||||
|
/*while (true)
|
||||||
|
{
|
||||||
|
Thread.Sleep(500);
|
||||||
|
Debug.WriteLine($"Repository {repository.mStatus} {repository.GetCompletedPct()}");
|
||||||
|
}*/
|
||||||
|
}
|
||||||
|
|
||||||
|
public GitInstance StartGit(StringView cmd, StringView path = default)
|
||||||
|
{
|
||||||
|
//Debug.WriteLine($"GIT STARTING: {cmd} in {path}");
|
||||||
|
|
||||||
|
GitInstance gitInst = new .(this);
|
||||||
|
gitInst.Init(cmd, path);
|
||||||
|
mGitInstances.Add(gitInst);
|
||||||
|
return gitInst;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GitInstance Clone(StringView url, StringView path)
|
||||||
|
{
|
||||||
|
return StartGit(scope $"clone -v --progress --recurse-submodules {url} \"{path}\"");
|
||||||
|
}
|
||||||
|
|
||||||
|
public GitInstance Checkout(StringView path, StringView hash)
|
||||||
|
{
|
||||||
|
return StartGit(scope $"checkout -b BeefManaged {hash}", path);
|
||||||
|
}
|
||||||
|
|
||||||
|
public GitInstance GetTags(StringView url)
|
||||||
|
{
|
||||||
|
return StartGit(scope $"ls-remote {url}");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Update()
|
||||||
|
{
|
||||||
|
for (var gitInstance in mGitInstances)
|
||||||
|
{
|
||||||
|
if (@gitInstance.Index >= sMaxActiveGitInstances)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (!gitInstance.mStarted)
|
||||||
|
gitInstance.Start();
|
||||||
|
gitInstance.Update();
|
||||||
|
|
||||||
|
if (gitInstance.mDone)
|
||||||
|
{
|
||||||
|
@gitInstance.Remove();
|
||||||
|
gitInstance.mRemoved = true;
|
||||||
|
gitInstance.ReleaseRef();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,35 +1,397 @@
|
||||||
|
#pragma warning disable 168
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using IDE.Util;
|
using IDE.Util;
|
||||||
|
using System.Collections;
|
||||||
#if BF_PLATFORM_WINDOWS
|
using System.Security.Cryptography;
|
||||||
using static Git.GitApi;
|
using System.IO;
|
||||||
#define SUPPORT_GIT
|
using Beefy.utils;
|
||||||
#endif
|
using System.Threading;
|
||||||
|
|
||||||
namespace IDE.util
|
namespace IDE.util
|
||||||
{
|
{
|
||||||
class PackMan
|
class PackMan
|
||||||
{
|
{
|
||||||
class GitHelper
|
public class WorkItem
|
||||||
{
|
{
|
||||||
static bool sInitialized;
|
public enum Kind
|
||||||
|
|
||||||
public this()
|
|
||||||
{
|
{
|
||||||
if (!sInitialized)
|
None,
|
||||||
{
|
FindVersion,
|
||||||
#if SUPPORT_GIT
|
Clone,
|
||||||
#unwarn
|
Checkout
|
||||||
var result = git_libgit2_init();
|
|
||||||
sInitialized = true;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Kind mKind;
|
||||||
|
public String mProjectName ~ delete _;
|
||||||
|
public String mURL ~ delete _;
|
||||||
|
public List<String> mConstraints ~ DeleteContainerAndItems!(_);
|
||||||
|
public String mTag ~ delete _;
|
||||||
|
public String mHash ~ delete _;
|
||||||
|
public String mPath ~ delete _;
|
||||||
|
public GitManager.GitInstance mGitInstance ~ _?.ReleaseRef();
|
||||||
|
|
||||||
|
public ~this()
|
||||||
|
{
|
||||||
|
mGitInstance?.Cancel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<WorkItem> mWorkItems = new .() ~ DeleteContainerAndItems!(_);
|
||||||
|
public bool mInitialized;
|
||||||
|
public String mManagedPath ~ delete _;
|
||||||
|
public bool mFailed;
|
||||||
|
|
||||||
|
public void Fail(StringView error)
|
||||||
|
{
|
||||||
|
gApp.OutputErrorLine(error);
|
||||||
|
|
||||||
|
if (!mFailed)
|
||||||
|
{
|
||||||
|
mFailed = true;
|
||||||
|
gApp.[Friend]FlushDeferredLoadProjects();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool CheckInit()
|
||||||
|
{
|
||||||
|
if (mInitialized)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (gApp.mBeefConfig.mManagedLibPath.IsEmpty)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
mManagedPath = new .(gApp.mBeefConfig.mManagedLibPath);
|
||||||
|
mInitialized = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void GetPath(StringView url, StringView hash, String outPath)
|
||||||
|
{
|
||||||
|
//var urlHash = SHA256.Hash(url.ToRawData()).ToString(.. scope .());
|
||||||
|
//outPath.AppendF($"{mManagedPath}/{urlHash}/{hash}");
|
||||||
|
outPath.AppendF($"{mManagedPath}/{hash}");
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool CheckLock(StringView projectName, String outPath)
|
public bool CheckLock(StringView projectName, String outPath)
|
||||||
{
|
{
|
||||||
|
if (!CheckInit())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (gApp.mWantUpdateVersionLocks != null)
|
||||||
|
{
|
||||||
|
if ((gApp.mWantUpdateVersionLocks.IsEmpty) || (gApp.mWantUpdateVersionLocks.ContainsAlt(projectName)))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!gApp.mWorkspace.mProjectLockMap.TryGetAlt(projectName, ?, var lock))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
switch (lock)
|
||||||
|
{
|
||||||
|
case .Git(let url, let tag, let hash):
|
||||||
|
var path = GetPath(url, hash, .. scope .());
|
||||||
|
var managedFilePath = scope $"{path}/BeefManaged.toml";
|
||||||
|
if (File.Exists(managedFilePath))
|
||||||
|
{
|
||||||
|
outPath.Append(path);
|
||||||
|
outPath.Append("/BeefProj.toml");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void CloneCompleted(StringView projectName, StringView url, StringView tag, StringView hash, StringView path)
|
||||||
|
{
|
||||||
|
gApp.mWorkspace.SetLock(projectName, .Git(new .(url), new .(tag), new .(hash)));
|
||||||
|
|
||||||
|
StructuredData sd = scope .();
|
||||||
|
sd.CreateNew();
|
||||||
|
sd.Add("FileVersion", 1);
|
||||||
|
sd.Add("Version", tag);
|
||||||
|
sd.Add("GitURL", url);
|
||||||
|
sd.Add("GitTag", tag);
|
||||||
|
sd.Add("GitHash", hash);
|
||||||
|
var tomlText = sd.ToTOML(.. scope .());
|
||||||
|
var managedFilePath = scope $"{path}/BeefManaged.toml";
|
||||||
|
File.WriteAllText(managedFilePath, tomlText).IgnoreError();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void GetWithHash(StringView projectName, StringView url, StringView tag, StringView hash)
|
||||||
|
{
|
||||||
|
if (!CheckInit())
|
||||||
|
return;
|
||||||
|
|
||||||
|
String destPath = GetPath(url, hash, .. scope .());
|
||||||
|
var urlPath = Path.GetDirectoryPath(destPath, .. scope .());
|
||||||
|
Directory.CreateDirectory(urlPath).IgnoreError();
|
||||||
|
if (Directory.Exists(destPath))
|
||||||
|
{
|
||||||
|
var managedFilePath = scope $"{destPath}/BeefManaged.toml";
|
||||||
|
if (File.Exists(managedFilePath))
|
||||||
|
{
|
||||||
|
if (gApp.mVerbosity >= .Normal)
|
||||||
|
{
|
||||||
|
if (tag.IsEmpty)
|
||||||
|
gApp.OutputLine($"Git selecting library '{projectName}' at {hash.Substring(0, 7)}");
|
||||||
|
else
|
||||||
|
gApp.OutputLine($"Git selecting library '{projectName}' tag '{tag}' at {hash.Substring(0, 7)}");
|
||||||
|
}
|
||||||
|
|
||||||
|
CloneCompleted(projectName, url, tag, hash, destPath);
|
||||||
|
ProjectReady(projectName, destPath);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String tempDir = new $"{destPath}__{(int32)Internal.GetTickCountMicro():X}";
|
||||||
|
|
||||||
|
//if (Directory.DelTree(destPath) case .Err)
|
||||||
|
if (Directory.Move(destPath, tempDir) case .Err)
|
||||||
|
{
|
||||||
|
delete tempDir;
|
||||||
|
Fail(scope $"Failed to remove directory '{destPath}'");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ThreadPool.QueueUserWorkItem(new () =>
|
||||||
|
{
|
||||||
|
Directory.DelTree(tempDir);
|
||||||
|
}
|
||||||
|
~
|
||||||
|
{
|
||||||
|
delete tempDir;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gApp.mVerbosity >= .Normal)
|
||||||
|
{
|
||||||
|
if (tag.IsEmpty)
|
||||||
|
gApp.OutputLine($"Git cloning library '{projectName}' at {hash.Substring(0, 7)}...");
|
||||||
|
else
|
||||||
|
gApp.OutputLine($"Git cloning library '{projectName}' tag '{tag}' at {hash.Substring(0, 7)}");
|
||||||
|
}
|
||||||
|
|
||||||
|
WorkItem workItem = new .();
|
||||||
|
workItem.mKind = .Clone;
|
||||||
|
workItem.mProjectName = new .(projectName);
|
||||||
|
workItem.mURL = new .(url);
|
||||||
|
workItem.mTag = new .(tag);
|
||||||
|
workItem.mHash = new .(hash);
|
||||||
|
workItem.mPath = new .(destPath);
|
||||||
|
mWorkItems.Add(workItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void GetWithVersion(StringView projectName, StringView url, SemVer semVer)
|
||||||
|
{
|
||||||
|
if (!CheckInit())
|
||||||
|
return;
|
||||||
|
|
||||||
|
bool ignoreLock = false;
|
||||||
|
if (gApp.mWantUpdateVersionLocks != null)
|
||||||
|
{
|
||||||
|
if ((gApp.mWantUpdateVersionLocks.IsEmpty) || (gApp.mWantUpdateVersionLocks.ContainsAlt(projectName)))
|
||||||
|
ignoreLock = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((!ignoreLock) && (gApp.mWorkspace.mProjectLockMap.TryGetAlt(projectName, ?, var lock)))
|
||||||
|
{
|
||||||
|
switch (lock)
|
||||||
|
{
|
||||||
|
case .Git(let checkURL, let tag, let hash):
|
||||||
|
if (checkURL == url)
|
||||||
|
GetWithHash(projectName, url, tag, hash);
|
||||||
|
return;
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gApp.mVerbosity >= .Normal)
|
||||||
|
gApp.OutputLine($"Git retrieving version list for '{projectName}'");
|
||||||
|
|
||||||
|
WorkItem workItem = new .();
|
||||||
|
workItem.mKind = .FindVersion;
|
||||||
|
workItem.mProjectName = new .(projectName);
|
||||||
|
workItem.mURL = new .(url);
|
||||||
|
if (semVer != null)
|
||||||
|
workItem.mConstraints = new .() { new String(semVer.mVersion) };
|
||||||
|
mWorkItems.Add(workItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateGitConstraint(StringView url, SemVer semVer)
|
||||||
|
{
|
||||||
|
for (var workItem in mWorkItems)
|
||||||
|
{
|
||||||
|
if ((workItem.mKind == .FindVersion) && (workItem.mURL == url))
|
||||||
|
{
|
||||||
|
if (workItem.mConstraints == null)
|
||||||
|
workItem.mConstraints = new .();
|
||||||
|
workItem.mConstraints.Add(new String(semVer.mVersion));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Checkout(StringView projectName, StringView url, StringView path, StringView tag, StringView hash)
|
||||||
|
{
|
||||||
|
if (!CheckInit())
|
||||||
|
return;
|
||||||
|
|
||||||
|
WorkItem workItem = new .();
|
||||||
|
workItem.mKind = .Checkout;
|
||||||
|
workItem.mProjectName = new .(projectName);
|
||||||
|
workItem.mURL = new .(url);
|
||||||
|
workItem.mTag = new .(tag);
|
||||||
|
workItem.mHash = new .(hash);
|
||||||
|
workItem.mPath = new .(path);
|
||||||
|
mWorkItems.Add(workItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ProjectReady(StringView projectName, StringView path)
|
||||||
|
{
|
||||||
|
if (var project = gApp.mWorkspace.FindProject(projectName))
|
||||||
|
{
|
||||||
|
String projectPath = scope $"{path}/BeefProj.toml";
|
||||||
|
|
||||||
|
project.mProjectPath.Set(projectPath);
|
||||||
|
gApp.RetryProjectLoad(project, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Update()
|
||||||
|
{
|
||||||
|
bool executingGit = false;
|
||||||
|
|
||||||
|
// First handle active git items
|
||||||
|
for (var workItem in mWorkItems)
|
||||||
|
{
|
||||||
|
if (workItem.mGitInstance == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!workItem.mGitInstance.mDone)
|
||||||
|
{
|
||||||
|
executingGit = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!workItem.mGitInstance.mFailed)
|
||||||
|
{
|
||||||
|
switch (workItem.mKind)
|
||||||
|
{
|
||||||
|
case .FindVersion:
|
||||||
|
gApp.CompilerLog("");
|
||||||
|
|
||||||
|
StringView bestTag = default;
|
||||||
|
StringView bestHash = default;
|
||||||
|
|
||||||
|
for (var tag in workItem.mGitInstance.mTagInfos)
|
||||||
|
{
|
||||||
|
if ((tag.mTag == "HEAD") && (workItem.mConstraints == null))
|
||||||
|
bestHash = tag.mHash;
|
||||||
|
else if (workItem.mConstraints != null)
|
||||||
|
{
|
||||||
|
bool hasMatch = false;
|
||||||
|
for (var constraint in workItem.mConstraints)
|
||||||
|
{
|
||||||
|
if (SemVer.IsVersionMatch(tag.mTag, constraint))
|
||||||
|
{
|
||||||
|
hasMatch = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasMatch)
|
||||||
|
{
|
||||||
|
if ((bestTag.IsEmpty) || (SemVer.Compare(tag.mTag, bestTag) > 0))
|
||||||
|
{
|
||||||
|
bestTag = tag.mTag;
|
||||||
|
bestHash = tag.mHash;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bestHash != default)
|
||||||
|
{
|
||||||
|
GetWithHash(workItem.mProjectName, workItem.mURL, bestTag, bestHash);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
String constraints = scope .();
|
||||||
|
for (var constraint in workItem.mConstraints)
|
||||||
|
{
|
||||||
|
if (!constraints.IsEmpty)
|
||||||
|
constraints.Append(", ");
|
||||||
|
constraints.Append('\'');
|
||||||
|
constraints.Append(constraint);
|
||||||
|
constraints.Append('\'');
|
||||||
|
}
|
||||||
|
|
||||||
|
Fail(scope $"Failed to locate version for '{workItem.mProjectName}' with constraints '{constraints}'");
|
||||||
|
}
|
||||||
|
case .Clone:
|
||||||
|
Checkout(workItem.mProjectName, workItem.mURL, workItem.mPath, workItem.mTag, workItem.mHash);
|
||||||
|
case .Checkout:
|
||||||
|
CloneCompleted(workItem.mProjectName, workItem.mURL, workItem.mTag, workItem.mHash, workItem.mPath);
|
||||||
|
ProjectReady(workItem.mProjectName, workItem.mPath);
|
||||||
|
|
||||||
|
if (gApp.mVerbosity >= .Normal)
|
||||||
|
gApp.OutputLine($"Git cloning library '{workItem.mProjectName}' done.");
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@workItem.Remove();
|
||||||
|
delete workItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!executingGit)
|
||||||
|
{
|
||||||
|
// First handle active git items
|
||||||
|
for (var workItem in mWorkItems)
|
||||||
|
{
|
||||||
|
if (workItem.mGitInstance != null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
switch (workItem.mKind)
|
||||||
|
{
|
||||||
|
case .FindVersion:
|
||||||
|
workItem.mGitInstance = gApp.mGitManager.GetTags(workItem.mURL)..AddRef();
|
||||||
|
case .Checkout:
|
||||||
|
workItem.mGitInstance = gApp.mGitManager.Checkout(workItem.mPath, workItem.mHash)..AddRef();
|
||||||
|
case .Clone:
|
||||||
|
workItem.mGitInstance = gApp.mGitManager.Clone(workItem.mURL, workItem.mPath)..AddRef();
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void GetHashFromFilePath(StringView filePath, String path)
|
||||||
|
{
|
||||||
|
if (mManagedPath == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!filePath.StartsWith(mManagedPath))
|
||||||
|
return;
|
||||||
|
|
||||||
|
StringView hashPart = filePath.Substring(mManagedPath.Length);
|
||||||
|
if (hashPart.Length < 42)
|
||||||
|
return;
|
||||||
|
|
||||||
|
hashPart.RemoveFromStart(1);
|
||||||
|
hashPart.Length = 40;
|
||||||
|
path.Append(hashPart);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CancelAll()
|
||||||
|
{
|
||||||
|
if (mWorkItems.IsEmpty)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Fail("Aborted project transfer");
|
||||||
|
mWorkItems.ClearAndDeleteItems();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,10 +2,51 @@ using System;
|
||||||
|
|
||||||
namespace IDE.Util
|
namespace IDE.Util
|
||||||
{
|
{
|
||||||
|
[Reflect]
|
||||||
class SemVer
|
class SemVer
|
||||||
{
|
{
|
||||||
|
public struct Parts
|
||||||
|
{
|
||||||
|
public enum Kind
|
||||||
|
{
|
||||||
|
case Empty;
|
||||||
|
case Num(int32 val);
|
||||||
|
case Wild;
|
||||||
|
|
||||||
|
public int32 NumOrDefault
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (this case .Num(let val))
|
||||||
|
return val;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Kind[3] mPart;
|
||||||
|
public StringView mPreRelease;
|
||||||
|
|
||||||
|
public Kind Major => mPart[0];
|
||||||
|
public Kind Minor => mPart[1];
|
||||||
|
public Kind Patch => mPart[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
enum CompareKind
|
||||||
|
{
|
||||||
|
Caret, // Default
|
||||||
|
Tilde,
|
||||||
|
Equal,
|
||||||
|
Gt,
|
||||||
|
Gte,
|
||||||
|
Lt,
|
||||||
|
Lte
|
||||||
|
}
|
||||||
|
|
||||||
public String mVersion ~ delete _;
|
public String mVersion ~ delete _;
|
||||||
|
|
||||||
|
public bool IsEmpty => String.IsNullOrEmpty(mVersion);
|
||||||
|
|
||||||
public this()
|
public this()
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -27,5 +68,240 @@ namespace IDE.Util
|
||||||
mVersion = new String(ver);
|
mVersion = new String(ver);
|
||||||
return .Ok;
|
return .Ok;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Result<Parts> GetParts(StringView version)
|
||||||
|
{
|
||||||
|
int startIdx = 0;
|
||||||
|
int partIdx = 0;
|
||||||
|
|
||||||
|
if (version.IsEmpty)
|
||||||
|
return .Err;
|
||||||
|
|
||||||
|
if (version.StartsWith("V", .OrdinalIgnoreCase))
|
||||||
|
startIdx++;
|
||||||
|
|
||||||
|
Parts parts = .();
|
||||||
|
|
||||||
|
Result<void> SetPart(Parts.Kind kind)
|
||||||
|
{
|
||||||
|
if (partIdx >= 3)
|
||||||
|
return .Err;
|
||||||
|
parts.mPart[partIdx] = kind;
|
||||||
|
partIdx++;
|
||||||
|
return .Ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result<void> FlushPart(int i)
|
||||||
|
{
|
||||||
|
StringView partStr = version.Substring(startIdx, i - startIdx);
|
||||||
|
if (!partStr.IsEmpty)
|
||||||
|
{
|
||||||
|
int32 partNum = Try!(int32.Parse(partStr));
|
||||||
|
Try!(SetPart(.Num(partNum)));
|
||||||
|
}
|
||||||
|
return .Ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i in startIdx ..< version.Length)
|
||||||
|
{
|
||||||
|
char8 c = version[i];
|
||||||
|
if (c.IsWhiteSpace)
|
||||||
|
return .Err;
|
||||||
|
|
||||||
|
if (c == '.')
|
||||||
|
{
|
||||||
|
Try!(FlushPart(i));
|
||||||
|
startIdx = i + 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if (c.IsNumber)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if (c == '-')
|
||||||
|
{
|
||||||
|
if (partIdx == 0)
|
||||||
|
return .Err;
|
||||||
|
parts.mPreRelease = version.Substring(i);
|
||||||
|
return .Ok(parts);
|
||||||
|
}
|
||||||
|
else if (c == '*')
|
||||||
|
{
|
||||||
|
Try!(SetPart(.Wild));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return .Err;
|
||||||
|
}
|
||||||
|
Try!(FlushPart(version.Length));
|
||||||
|
|
||||||
|
return parts;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Result<Parts> GetParts()
|
||||||
|
{
|
||||||
|
return GetParts(mVersion);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool IsVersionMatch(StringView fullVersion, StringView wildcard)
|
||||||
|
{
|
||||||
|
int commaPos = wildcard.IndexOf(',');
|
||||||
|
if (commaPos != -1)
|
||||||
|
return IsVersionMatch(fullVersion, wildcard.Substring(0, commaPos)..Trim()) && IsVersionMatch(fullVersion, wildcard.Substring(commaPos + 1)..Trim());
|
||||||
|
|
||||||
|
var wildcard;
|
||||||
|
|
||||||
|
wildcard.Trim();
|
||||||
|
CompareKind compareKind = .Caret;
|
||||||
|
if (wildcard.StartsWith('^'))
|
||||||
|
{
|
||||||
|
compareKind = .Caret;
|
||||||
|
wildcard.RemoveFromStart(1);
|
||||||
|
}
|
||||||
|
else if (wildcard.StartsWith('~'))
|
||||||
|
{
|
||||||
|
compareKind = .Tilde;
|
||||||
|
wildcard.RemoveFromStart(1);
|
||||||
|
}
|
||||||
|
else if (wildcard.StartsWith('='))
|
||||||
|
{
|
||||||
|
compareKind = .Equal;
|
||||||
|
wildcard.RemoveFromStart(1);
|
||||||
|
}
|
||||||
|
else if (wildcard.StartsWith('>'))
|
||||||
|
{
|
||||||
|
compareKind = .Gt;
|
||||||
|
wildcard.RemoveFromStart(1);
|
||||||
|
if (wildcard.StartsWith('='))
|
||||||
|
{
|
||||||
|
compareKind = .Gte;
|
||||||
|
wildcard.RemoveFromStart(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (wildcard.StartsWith('<'))
|
||||||
|
{
|
||||||
|
compareKind = .Lt;
|
||||||
|
wildcard.RemoveFromStart(1);
|
||||||
|
if (wildcard.StartsWith('='))
|
||||||
|
{
|
||||||
|
compareKind = .Lte;
|
||||||
|
wildcard.RemoveFromStart(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
wildcard.Trim();
|
||||||
|
|
||||||
|
// Does we include equality?
|
||||||
|
if ((compareKind != .Gt) && (compareKind != .Lt))
|
||||||
|
{
|
||||||
|
if (fullVersion == wildcard)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Parts full;
|
||||||
|
if (!(GetParts(fullVersion) case .Ok(out full)))
|
||||||
|
return false;
|
||||||
|
Parts wild;
|
||||||
|
if (!(GetParts(wildcard) case .Ok(out wild)))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Don't allow a general wildcard to match a pre-prelease
|
||||||
|
if ((!full.mPreRelease.IsEmpty) && (full.mPreRelease != wild.mPreRelease))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (int partIdx < 3)
|
||||||
|
{
|
||||||
|
if (wild.mPart[partIdx] case .Wild)
|
||||||
|
return true;
|
||||||
|
int comp = full.mPart[partIdx].NumOrDefault <=> wild.mPart[partIdx].NumOrDefault;
|
||||||
|
switch (compareKind)
|
||||||
|
{
|
||||||
|
case .Caret:
|
||||||
|
if ((full.mPart[partIdx].NumOrDefault > 0) || (wild.mPart[partIdx].NumOrDefault > 0))
|
||||||
|
{
|
||||||
|
if (comp != 0)
|
||||||
|
return false;
|
||||||
|
// First number matches, now make sure we are at least a high enough version on the other numbers
|
||||||
|
compareKind = .Gte;
|
||||||
|
}
|
||||||
|
case .Tilde:
|
||||||
|
if (wild.mPart[partIdx] case .Empty)
|
||||||
|
return true;
|
||||||
|
if (partIdx == 2)
|
||||||
|
{
|
||||||
|
if (comp < 0)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else if (comp != 0)
|
||||||
|
return false;
|
||||||
|
case .Equal:
|
||||||
|
if (wild.mPart[partIdx] case .Empty)
|
||||||
|
return true;
|
||||||
|
if (comp != 0)
|
||||||
|
return false;
|
||||||
|
case .Gt:
|
||||||
|
if (comp > 0)
|
||||||
|
return true;
|
||||||
|
if (partIdx == 2)
|
||||||
|
return false;
|
||||||
|
if (comp < 0)
|
||||||
|
return false;
|
||||||
|
case .Gte:
|
||||||
|
if (comp < 0)
|
||||||
|
return false;
|
||||||
|
case .Lt:
|
||||||
|
if (comp < 0)
|
||||||
|
return true;
|
||||||
|
if (partIdx == 2)
|
||||||
|
return false;
|
||||||
|
if (comp > 0)
|
||||||
|
return false;
|
||||||
|
case .Lte:
|
||||||
|
if (comp > 0)
|
||||||
|
return false;
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool IsVersionMatch(SemVer fullVersion, SemVer wildcard) => IsVersionMatch(fullVersion.mVersion, wildcard.mVersion);
|
||||||
|
|
||||||
|
public static Result<int> Compare(StringView lhs, StringView rhs)
|
||||||
|
{
|
||||||
|
Parts lhsParts;
|
||||||
|
if (!(GetParts(lhs) case .Ok(out lhsParts)))
|
||||||
|
return .Err;
|
||||||
|
Parts rhsParts;
|
||||||
|
if (!(GetParts(rhs) case .Ok(out rhsParts)))
|
||||||
|
return .Err;
|
||||||
|
|
||||||
|
int comp = 0;
|
||||||
|
for (int partIdx < 3)
|
||||||
|
{
|
||||||
|
comp = lhsParts.mPart[partIdx].NumOrDefault <=> rhsParts.mPart[partIdx].NumOrDefault;
|
||||||
|
if (comp != 0)
|
||||||
|
return comp;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Don't allow a general wildcard to match a pre-prelease
|
||||||
|
if ((!lhsParts.mPreRelease.IsEmpty) || (!rhsParts.mPreRelease.IsEmpty))
|
||||||
|
{
|
||||||
|
if (lhsParts.mPreRelease.IsEmpty)
|
||||||
|
return 1;
|
||||||
|
if (rhsParts.mPreRelease.IsEmpty)
|
||||||
|
return -1;
|
||||||
|
return lhsParts.mPreRelease <=> rhsParts.mPreRelease;
|
||||||
|
}
|
||||||
|
|
||||||
|
return comp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void ToString(String strBuffer)
|
||||||
|
{
|
||||||
|
strBuffer.Append(mVersion);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int operator<=>(Self lhs, Self rhs) => (lhs?.mVersion ?? "") <=> (rhs?.mVersion ?? "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,6 +39,8 @@ namespace IDE.Util
|
||||||
case .Path(let path):
|
case .Path(let path):
|
||||||
return .Path(new String(path));
|
return .Path(new String(path));
|
||||||
case .Git(let url, let ver):
|
case .Git(let url, let ver):
|
||||||
|
if (ver == null)
|
||||||
|
return .Git(new String(url), null);
|
||||||
return .Git(new String(url), new SemVer(ver));
|
return .Git(new String(url), new SemVer(ver));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -113,7 +115,7 @@ namespace IDE.Util
|
||||||
using (data.CreateObject(name))
|
using (data.CreateObject(name))
|
||||||
{
|
{
|
||||||
data.Add("Git", path);
|
data.Add("Git", path);
|
||||||
if (ver != null)
|
if ((ver != null) && (!ver.mVersion.IsEmpty))
|
||||||
data.Add("Version", ver.mVersion);
|
data.Add("Version", ver.mVersion);
|
||||||
}
|
}
|
||||||
case .SemVer(var ver):
|
case .SemVer(var ver):
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue