示例#1
0
        /// <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);
        }
示例#2
0
        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());
        }
示例#3
0
        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);
        }