/// <summary> /// Loads a command store using the metadata for one of the branches /// in the store. /// </summary> /// <param name="sqliteFilename">The file specification of the SQLite database /// to load.</param> /// <param name="cs">Details for a clone command that should be used /// to initialize the root metadata for a newly cloned store (specify /// null if this store previously existed).</param> /// <returns>The loaded command store.</returns> public static SQLiteStore Load(string sqliteFilename, ICloneStore cs = null) { var db = new SQLiteDatabase(sqliteFilename); // Load misc properties Dictionary <string, object> props = db.ExecuteQuery(new PropertiesQuery()) .ToDictionary(x => x.Key, x => (object)x.Value); // Amend root details if we're loading up a new clone if (cs != null) { Guid upstreamId = props.GetGuid(PropertyNaming.StoreId.ToString()); props[PropertyNaming.UpstreamId.ToString()] = upstreamId; props[PropertyNaming.UpstreamLocation.ToString()] = cs.Origin; props[PropertyNaming.StoreId.ToString()] = cs.StoreId; } var root = new StoreInfo( storeId: props.GetGuid(PropertyNaming.StoreId.ToString()), name: Path.GetFileNameWithoutExtension(sqliteFilename), upstreamId: props.GetGuid(PropertyNaming.UpstreamId.ToString()), upstreamLocation: props.GetValue <string>(PropertyNaming.UpstreamLocation.ToString()), pushTimes: null); // Fake a directory name that will provide a value for CmdStore.Name that // corresponds to the name of the database string rootDirectoryName = Path.ChangeExtension(sqliteFilename, null); // What was the last branch the user was working with? (it should be defined, // go with the master branch if not) var curId = props.GetGuid(PropertyNaming.LastBranch.ToString()); if (Guid.Empty.Equals(curId)) { curId = root.StoreId; } // Load metadata for all branches in the store BranchInfo[] acs = db.ExecuteQuery(new BranchesQuery()) .OrderBy(x => x.CreatedAt) .ToArray(); Debug.Assert(acs.Length > 0); Debug.Assert(acs.Any(x => x.BranchId.Equals(curId))); var result = new SQLiteStore(root, acs, curId, db); // If we amended the store properties for a new clone, save // them back to the database if (cs != null) { result.SaveStoreInfo(); } return(result); }
public static CmdStore CreateStore(CmdData args) { StoreType type = args.GetEnum <StoreType>(nameof(ICreateStore.Type)); if (type == StoreType.File) { return(FileStore.Create(args)); } if (type == StoreType.SQLite) { return(SQLiteStore.Create(args)); } if (type == StoreType.Memory) { return(MemoryStore.Create(args)); } throw new NotImplementedException(type.ToString()); }
internal static SQLiteStore Create(CmdData args) { // Disallow store names that correspond to tables in the database (bear // in mind that the entered name may or may not include a directory path) string enteredName = args.GetValue <string>(nameof(ICreateStore.Name)); string name = Path.GetFileNameWithoutExtension(enteredName); if (IsReservedName(name)) { throw new ApplicationException("Store name not allowed"); } // Expand the supplied name to include the current working directory (or // expand a relative path) string fullSpec = Path.GetFullPath(enteredName); string fileType = Path.GetExtension(fullSpec); if (String.IsNullOrEmpty(fileType)) { fullSpec += ".ac-sqlite"; } // Disallow if the database file already exists if (File.Exists(fullSpec)) { throw new ApplicationException($"{fullSpec} already exists"); } // Confirm the file is on a local drive if (!IsLocalDrive(fullSpec)) { throw new ApplicationException("Command stores can only be initialized on a local fixed drive"); } // Ensure the folder exists string folderName = Path.GetDirectoryName(fullSpec); if (!Directory.Exists(folderName)) { Log.Trace("Creating " + folderName); Directory.CreateDirectory(folderName); } Guid storeId = args.GetGuid(nameof(ICreateStore.StoreId)); SQLiteStore result = null; if (args.CmdName == nameof(ICloneStore)) { // Copy the SQLite database // TODO: To handle database files on remote machines ICloneStore cs = (args as ICloneStore); Log.Info($"Copying {cs.Origin} to {fullSpec}"); File.Copy(cs.Origin, fullSpec); // Load the copied store result = SQLiteStore.Load(fullSpec, cs); } else { Log.Info("Creating " + fullSpec); SQLiteDatabase db = CreateDatabase(fullSpec); // Create the AC file that represents the store root branch var ac = new BranchInfo(storeId: storeId, parentId: Guid.Empty, branchId: storeId, branchName: name, createdAt: args.CreatedAt); // Create the store metadata var storeInfo = new StoreInfo(storeId, name, Guid.Empty); // Create the store and save it result = new SQLiteStore(storeInfo, new BranchInfo[] { ac }, ac.BranchId, db); // Save the info for the master branch plus the store metadata result.SaveBranchInfo(ac); result.SaveStoreInfo(); // The last branch is the root of the new database result.SaveProperty(PropertyNaming.LastBranch, storeId.ToString()); } return(result); }