public void InitSQLiteStore() { // Create it in a folder that doesn't already exist string storeName = nameof(InitSQLiteStore); string folder = Path.Combine(Path.GetTempPath(), DateTime.UtcNow.ToString("yyyyMMddHHmmss")); string dbSpec = Path.Combine(folder, storeName + ".ac-sqlite"); try { CmdStore cs = Init(dbSpec, StoreType.SQLite); SQLiteStore ss = (cs as SQLiteStore); Assert.IsNotNull(ss); Assert.IsTrue(Directory.Exists(folder)); Assert.IsTrue(File.Exists(dbSpec)); Assert.AreEqual <int>(Directory.GetFiles(folder).Length, 1); Assert.AreEqual <string>(storeName, cs.Name); Assert.AreEqual <string>(dbSpec, ss.FileName); } finally { Directory.Delete(folder, true); } }
public void InitMemoryStore() { const string storeName = nameof(InitMemoryStore); CmdStore cs = Init(storeName, StoreType.Memory); Assert.AreEqual <string>(storeName, cs.Name); }
/// <summary> /// Creates an instance of <see cref="AltCmdSession"/> /// that refers to a new instance of <see cref="MemoryStore"/>. /// </summary> /// <param name="storeName">The name for the new store.</param> /// <returns>The newly created command store</returns> protected AltCmdSession CreateSession(string storeName) { var cs = CmdStore.Create(storeName, StoreType.Memory); var ec = new ExecutionContext(cs); return(new AltCmdSession(ec)); }
CmdStore Init(string storeName, StoreType t) { CmdStore result = CmdStore.Create(storeName, t); Assert.IsNotNull(result); Assert.AreEqual <int>(1, result.Branches.Count); return(result); }
string GetCmdSummary(CmdStore cs, CmdData data, Branch branch) { if (data.CmdName == nameof(NameCmdLine)) { return(NameCmdLine.GetCommandLine(data)); } if (data.CmdName == nameof(ICreateBranch)) { string name = (data as ICreateBranch).Name; uint cc = (data as ICreateBranch).CommandCount; string result = $"branch {name} {cc}"; if (!name.Equals(branch.Name)) { result += $" (now called {branch.Name})"; } return(result); } if (data.CmdName == nameof(IMerge)) { IMerge m = (data as IMerge); string result = "merge "; Guid fromId = m.FromId; Branch fromBranch = cs.FindBranch(fromId); if (ReferenceEquals(fromBranch, branch.Parent)) { result += ".."; } else { result += fromBranch.Name; } result += $" [{m.MinCmd},{m.MaxCmd}]"; return(result); } return(data.CmdName); }
public override bool Execute(ExecutionContext context) { if (Count == 0) { Count = 20; } CmdStore cs = context.Store; if (All) { // Display with most recent first LinkedListNode <Cmd> cNode = cs.Stream.Cmds.Last; for (int i = 0; cNode != null && i < Count; i++, cNode = cNode.Previous) { Cmd c = cNode.Value; string branchPath = c.Branch.GetBranchPath(false); CmdData cd = c.Data; string summary = GetCmdSummary(cs, cd, c.Branch); Console.WriteLine($"{branchPath}[{cd.Sequence}] = {summary}"); } } else { BranchInfo ac = cs.Current.Info; uint minSeq = Count < ac.CommandCount ? ac.CommandCount - Count : 0; uint maxSeq = ac.CommandCount - 1; CmdData[] data = cs.ReadData(cs.Current, minSeq, maxSeq).ToArray(); foreach (CmdData cd in data.Reverse()) { string summary = GetCmdSummary(cs, cd, cs.Current); Console.WriteLine($"[{cd.Sequence}] = {summary}"); } } return(true); }
public void InitFileStore() { const string storeName = nameof(InitFileStore); string folder = Path.Combine(Path.GetTempPath(), storeName); try { CmdStore cs = Init(folder, StoreType.File); var fs = (cs as FileStore); Assert.IsNotNull(fs); Assert.IsTrue(Directory.Exists(folder)); Assert.IsTrue(File.Exists(Path.Combine(folder, "0.json"))); Assert.IsTrue(File.Exists(Path.Combine(folder, ".storeInfo"))); Assert.AreEqual <int>(Directory.GetFiles(folder).Length, 3); Assert.AreEqual <string>(storeName, cs.Name); Assert.AreEqual <string>(folder, fs.RootDirectoryName); } finally { Directory.Delete(folder, true); } }
void ListBranches(ExecutionContext ec) { if (ec.Store == null) { throw new ApplicationException("Store is undefined"); } CmdStore store = ec.Store; // Apply optional filter Guid curBranchId = store.Current.Info.BranchId; IEnumerable <Branch> toList = ApplyFilter(store.Branches.Values); uint numLocal = 0; uint numRemote = 0; uint totLocal = 0; uint totRemote = 0; foreach (Branch b in toList.OrderBy(x => x.GetBranchPath())) { if (b.IsRemote) { numRemote++; totRemote += b.Info.CommandCount; } else { numLocal++; totLocal += b.Info.CommandCount; } if (!All) { if (Remotes != b.IsRemote) { continue; } if (b.Info.IsCompleted) { continue; } } string prefix = b.Info.BranchId.Equals(curBranchId) ? "*" : " "; string suffix = String.Empty; string isRemote = " "; if (b.IsRemote) { // If every ancestor is remote, it's an upstream branch. Otherwise // its a downstream branch that has been pushed back to its origin isRemote = b.CanBranch ? "^" : "_"; } if (b.Parent != null) { if (b.BehindCount > 0) { suffix = $" (behind parent by {b.BehindCount}"; } if (b.AheadCount > 0) { if (suffix.Length > 0) { suffix += ", "; } else { suffix = " ("; } suffix += $"ahead of parent by {b.AheadCount}"; // If we've pushed, show where we got to (can't easily show a // number that's a subset of the AheadCount, since the branch // metadata doesn't hold the discount value as well) // TODO: Need to show how many within the AheadCount have // actually been pushed if (b.Info.LastPush != 0) { suffix += $" - pushed to [{b.Info.LastPush}]"; } } if (suffix.Length > 0) { suffix += ")"; } } Console.WriteLine($"{prefix} {isRemote}{b}{suffix}"); } Console.WriteLine(); string localMsg = $"{totLocal} command`s in {numLocal} local branch`es".TrimExtras(); string remotesMsg = $"{totRemote} command`s in {numRemote} remote branch`es".TrimExtras(); if (!All) { if (Remotes) { localMsg += " (not listed)"; } else { remotesMsg += " (not listed)"; } } Console.WriteLine(localMsg); if (totRemote > 0) { Console.WriteLine(remotesMsg); } }
public override bool Execute(ExecutionContext context) { // Convert the name of the branch we're merging from into it's // internal ID (the name might later change, but the ID won't) CmdStore cs = context.Store; if (From == "..") { if (cs.Current.Parent == null) { Console.WriteLine("The current branch does not have a parent branch"); return(false); } // Confirm that we are not already up to date if (cs.Current.BehindCount == 0) { Console.WriteLine($"Nothing to merge (at {context})"); return(false); } FromId = cs.Current.Info.ParentId; Debug.Assert(!FromId.Equals(Guid.Empty)); } else { // TODO: There is a bit of a problem with this. If a new branch has been // created in a clone, it will be regarded as a remote as soon as you do a // push (since I expect the push to update root metadata with a new store ID). // So if you make any further changes, yet another branch will be needed. // This makes sense, because a branch that has been pushed to the remote // could be modified there. That isn't necessarily bad (a new branch for // every push), but it may need to be presented to the user in another way. // Perhaps a push could have a --private option that would let you send // the command data, while disallowing any changes on the remote. You // would need to send a "release" command to make the pushes available. // Or, do it the other way around: make all pushed branches private by // default. The remote would still be able to merge from them, but would // not be able to mutate them. Which means there needs to be a property // in the Branch class to say it can be used only in a certain context. // But how to specify the context -- is it a machine name? If so, it would // be more tricky to anticipate copies of any one store. if (cs.Current.IsRemote) { Console.WriteLine("You are currently on a remote branch (use the push command instead)"); return(false); } Branch child = cs.Current.GetChild(From); if (child == null) { Console.WriteLine($"Cannot locate child branch called '{From}'"); return(false); } // Confirm the parent does not already have everything from the child if (child.AheadCount == 0) { Console.WriteLine($"Nothing to merge (at {context})"); return(false); } FromId = child.Id; } return(base.Execute(context)); }