Ejemplo n.º 1
0
        public void GetAllEntriesAndPrepToWriteAllEntriesSplitsFilesAndFoldersCorrectly()
        {
            ConfigurableFileSystem fs = new ConfigurableFileSystem();

            using (PlaceholderListDatabase dut1 = CreatePlaceholderListDatabase(fs, string.Empty))
            {
                dut1.AddAndFlushFile(InputGitIgnorePath, InputGitIgnoreSHA);
                dut1.AddAndFlushFolder("partialFolder", isExpanded: false);
                dut1.AddAndFlushFile(InputGitAttributesPath, InputGitAttributesSHA);
                dut1.AddAndFlushFolder("expandedFolder", isExpanded: true);
                dut1.AddAndFlushFile(InputThirdFilePath, InputThirdFileSHA);
                dut1.AddAndFlushPossibleTombstoneFolder("tombstone");
                dut1.RemoveAndFlush(InputThirdFilePath);
            }

            string error;
            PlaceholderListDatabase dut2;

            PlaceholderListDatabase.TryCreate(null, MockEntryFileName, fs, out dut2, out error).ShouldEqual(true, error);
            List <PlaceholderListDatabase.PlaceholderData> fileData;
            List <PlaceholderListDatabase.PlaceholderData> folderData;

            dut2.GetAllEntriesAndPrepToWriteAllEntries(out fileData, out folderData);
            fileData.Count.ShouldEqual(2);
            folderData.Count.ShouldEqual(3);
            folderData.ShouldContain(
                new[]
            {
                new PlaceholderListDatabase.PlaceholderData("partialFolder", PlaceholderListDatabase.PartialFolderValue),
                new PlaceholderListDatabase.PlaceholderData("expandedFolder", PlaceholderListDatabase.ExpandedFolderValue),
                new PlaceholderListDatabase.PlaceholderData("tombstone", PlaceholderListDatabase.PossibleTombstoneFolderValue),
            },
                (data1, data2) => data1.Path == data2.Path && data1.Sha == data2.Sha);
        }
Ejemplo n.º 2
0
        public override bool TryUpgrade(ITracer tracer, string enlistmentRoot)
        {
            string dotGVFSRoot = Path.Combine(enlistmentRoot, GVFSPlatform.Instance.Constants.DotGVFSRoot);

            try
            {
                string error;
                PlaceholderListDatabase placeholders;
                if (!PlaceholderListDatabase.TryCreate(
                        tracer,
                        Path.Combine(dotGVFSRoot, GVFSConstants.DotGVFS.Databases.PlaceholderList),
                        new PhysicalFileSystem(),
                        out placeholders,
                        out error))
                {
                    tracer.RelatedError("Failed to open placeholder database: " + error);
                    return(false);
                }

                using (placeholders)
                {
                    List <IPlaceholderData> oldPlaceholderEntries = placeholders.GetAllEntries();
                    List <IPlaceholderData> newPlaceholderEntries = new List <IPlaceholderData>();

                    foreach (IPlaceholderData entry in oldPlaceholderEntries)
                    {
                        if (entry.Sha == GVFSConstants.AllZeroSha)
                        {
                            newPlaceholderEntries.Add(new PlaceholderListDatabase.PlaceholderData(entry.Path, PlaceholderListDatabase.PartialFolderValue));
                        }
                        else
                        {
                            newPlaceholderEntries.Add(entry);
                        }
                    }

                    placeholders.WriteAllEntriesAndFlush(newPlaceholderEntries);
                }
            }
            catch (IOException ex)
            {
                tracer.RelatedError("Could not write to placeholder database: " + ex.ToString());
                return(false);
            }
            catch (Exception ex)
            {
                tracer.RelatedError("Error updating placeholder database folder entries: " + ex.ToString());
                return(false);
            }

            if (!this.TryIncrementMajorVersion(tracer, enlistmentRoot))
            {
                return(false);
            }

            return(true);
        }
Ejemplo n.º 3
0
        private static PlaceholderListDatabase CreatePlaceholderListDatabase(ConfigurableFileSystem fs, string initialContents)
        {
            fs.ExpectedFiles.Add(MockEntryFileName, new ReusableMemoryStream(initialContents));

            string error;
            PlaceholderListDatabase dut;

            PlaceholderListDatabase.TryCreate(null, MockEntryFileName, fs, out dut, out error).ShouldEqual(true, error);
            dut.ShouldNotBeNull();
            return(dut);
        }
        /// <summary>
        /// Adds the folder placeholders to the placeholders list
        /// </summary>
        public override bool TryUpgrade(ITracer tracer, string enlistmentRoot)
        {
            string dotGVFSRoot = Path.Combine(enlistmentRoot, GVFSConstants.DotGVFS.Root);

            try
            {
                string error;
                PlaceholderListDatabase placeholders;
                if (!PlaceholderListDatabase.TryCreate(
                        tracer,
                        Path.Combine(dotGVFSRoot, GVFSConstants.DotGVFS.Databases.PlaceholderList),
                        new PhysicalFileSystem(),
                        out placeholders,
                        out error))
                {
                    tracer.RelatedError("Failed to open placeholder database: " + error);
                    return(false);
                }

                using (placeholders)
                {
                    string workingDirectoryRoot = Path.Combine(enlistmentRoot, GVFSConstants.WorkingDirectoryRootName);

                    // Run through the folder placeholders adding to the placeholder list
                    IEnumerable <PlaceholderListDatabase.PlaceholderData> folderPlaceholderPaths =
                        GetFolderPlaceholdersFromDisk(tracer, new PhysicalFileSystem(), workingDirectoryRoot)
                        .Select(x => x.Substring(workingDirectoryRoot.Length + 1))
                        .Select(x => new PlaceholderListDatabase.PlaceholderData(x, GVFSConstants.AllZeroSha));

                    List <PlaceholderListDatabase.PlaceholderData> placeholderEntries = placeholders.GetAllEntriesAndPrepToWriteAllEntries();
                    placeholderEntries.AddRange(folderPlaceholderPaths);

                    placeholders.WriteAllEntriesAndFlush(placeholderEntries);
                }
            }
            catch (IOException ex)
            {
                tracer.RelatedError("Could not write to placeholder database: " + ex.ToString());
                return(false);
            }
            catch (Exception ex)
            {
                tracer.RelatedError("Error updating placeholder database with folders: " + ex.ToString());
                return(false);
            }

            if (!this.TryIncrementMajorVersion(tracer, enlistmentRoot))
            {
                return(false);
            }

            return(true);
        }
Ejemplo n.º 5
0
        public void WritesPlaceholderAddToFile()
        {
            ConfigurableFileSystem  fs  = new ConfigurableFileSystem();
            PlaceholderListDatabase dut = CreatePlaceholderListDatabase(fs, string.Empty);

            dut.AddAndFlushFile(InputGitIgnorePath, InputGitIgnoreSHA);

            fs.ExpectedFiles[MockEntryFileName].ReadAsString().ShouldEqual(ExpectedGitIgnoreEntry);

            dut.AddAndFlushFile(InputGitAttributesPath, InputGitAttributesSHA);

            fs.ExpectedFiles[MockEntryFileName].ReadAsString().ShouldEqual(ExpectedTwoEntries);
        }
Ejemplo n.º 6
0
        public void HandlesRaceBetweenAddAndWriteAllEntries()
        {
            ConfigurableFileSystem fs = new ConfigurableFileSystem();

            fs.ExpectedFiles.Add(MockEntryFileName + ".tmp", new ReusableMemoryStream(string.Empty));

            PlaceholderListDatabase dut = CreatePlaceholderListDatabase(fs, ExpectedGitIgnoreEntry);

            List <PlaceholderListDatabase.PlaceholderData> existingEntries = dut.GetAllEntriesAndPrepToWriteAllEntries();

            dut.AddAndFlushFile(InputGitAttributesPath, InputGitAttributesSHA);

            dut.WriteAllEntriesAndFlush(existingEntries);
            fs.ExpectedFiles[MockEntryFileName].ReadAsString().ShouldEqual(ExpectedTwoEntries);
        }
Ejemplo n.º 7
0
        public void HandlesRaceBetweenRemoveAndWriteAllEntries()
        {
            const string DeleteGitAttributesEntry = "D .gitattributes" + PlaceholderDatabaseNewLine;

            ConfigurableFileSystem fs = new ConfigurableFileSystem();

            fs.ExpectedFiles.Add(MockEntryFileName + ".tmp", new ReusableMemoryStream(string.Empty));

            PlaceholderListDatabase dut = CreatePlaceholderListDatabase(fs, ExpectedTwoEntries);

            List <PlaceholderListDatabase.PlaceholderData> existingEntries = dut.GetAllEntriesAndPrepToWriteAllEntries();

            dut.RemoveAndFlush(InputGitAttributesPath);

            dut.WriteAllEntriesAndFlush(existingEntries);
            fs.ExpectedFiles[MockEntryFileName].ReadAsString().ShouldEqual(ExpectedTwoEntries + DeleteGitAttributesEntry);
        }
Ejemplo n.º 8
0
        public void WriteAllEntriesCorrectlyWritesFile()
        {
            ConfigurableFileSystem fs = new ConfigurableFileSystem();

            fs.ExpectedFiles.Add(MockEntryFileName + ".tmp", new ReusableMemoryStream(string.Empty));

            PlaceholderListDatabase dut = CreatePlaceholderListDatabase(fs, string.Empty);

            List <PlaceholderListDatabase.PlaceholderData> allData = new List <PlaceholderListDatabase.PlaceholderData>()
            {
                new PlaceholderListDatabase.PlaceholderData(InputGitIgnorePath, InputGitIgnoreSHA),
                new PlaceholderListDatabase.PlaceholderData(InputGitAttributesPath, InputGitAttributesSHA)
            };

            dut.WriteAllEntriesAndFlush(allData);
            fs.ExpectedFiles[MockEntryFileName].ReadAsString().ShouldEqual(ExpectedTwoEntries);
        }
Ejemplo n.º 9
0
        public void ParsesExistingDataCorrectly()
        {
            ConfigurableFileSystem  fs  = new ConfigurableFileSystem();
            PlaceholderListDatabase dut = CreatePlaceholderListDatabase(
                fs,
                "A .gitignore\0AE930E4CF715315FC90D4AEC98E16A7398F8BF64\r\n" +
                "A Test_EPF_UpdatePlaceholderTests\\LockToPreventDelete\\test.txt\0B6948308A8633CC1ED94285A1F6BF33E35B7C321\r\n" +
                "A Test_EPF_UpdatePlaceholderTests\\LockToPreventDelete\\test.txt\0C7048308A8633CC1ED94285A1F6BF33E35B7C321\r\n" +
                "A Test_EPF_UpdatePlaceholderTests\\LockToPreventDelete\\test2.txt\0D19198D6EA60F0D66F0432FEC6638D0A73B16E81\r\n" +
                "A Test_EPF_UpdatePlaceholderTests\\LockToPreventDelete\\test3.txt\0E45EA0D328E581696CAF1F823686F3665A5F05C1\r\n" +
                "A Test_EPF_UpdatePlaceholderTests\\LockToPreventDelete\\test4.txt\0FCB3E2C561649F102DD8110A87DA82F27CC05833\r\n" +
                "A Test_EPF_UpdatePlaceholderTests\\LockToPreventUpdate\\test.txt\0E51B377C95076E4C6A9E22A658C5690F324FD0AD\r\n" +
                "D Test_EPF_UpdatePlaceholderTests\\LockToPreventUpdate\\test.txt\r\n" +
                "D Test_EPF_UpdatePlaceholderTests\\LockToPreventUpdate\\test.txt\r\n" +
                "D Test_EPF_UpdatePlaceholderTests\\LockToPreventUpdate\\test.txt\r\n");

            dut.EstimatedCount.ShouldEqual(5);
        }
Ejemplo n.º 10
0
        public override IssueType HasIssue(List <string> messages)
        {
            string error;
            PlaceholderListDatabase placeholders;

            if (!PlaceholderListDatabase.TryCreate(
                    this.Tracer,
                    this.databasePath,
                    new PhysicalFileSystem(),
                    out placeholders,
                    out error))
            {
                messages.Add(error);
                return(IssueType.CantFix);
            }

            return(IssueType.None);
        }
Ejemplo n.º 11
0
        public void GetAllEntriesAndPrepToWriteAllEntriesReturnsCorrectEntries()
        {
            ConfigurableFileSystem fs = new ConfigurableFileSystem();

            using (PlaceholderListDatabase dut1 = CreatePlaceholderListDatabase(fs, string.Empty))
            {
                dut1.AddAndFlushFile(InputGitIgnorePath, InputGitIgnoreSHA);
                dut1.AddAndFlushFile(InputGitAttributesPath, InputGitAttributesSHA);
                dut1.AddAndFlushFile(InputThirdFilePath, InputThirdFileSHA);
                dut1.RemoveAndFlush(InputThirdFilePath);
            }

            string error;
            PlaceholderListDatabase dut2;

            PlaceholderListDatabase.TryCreate(null, MockEntryFileName, fs, out dut2, out error).ShouldEqual(true, error);
            List <PlaceholderListDatabase.PlaceholderData> allData = dut2.GetAllEntriesAndPrepToWriteAllEntries();

            allData.Count.ShouldEqual(2);
        }
Ejemplo n.º 12
0
        public FileSystemCallbacks(
            GVFSContext context,
            GVFSGitObjects gitObjects,
            RepoMetadata repoMetadata,
            BlobSizes blobSizes,
            GitIndexProjection gitIndexProjection,
            BackgroundFileSystemTaskRunner backgroundFileSystemTaskRunner,
            FileSystemVirtualizer fileSystemVirtualizer,
            GitStatusCache gitStatusCache = null)
        {
            this.logsHeadFileProperties = null;
            this.postFetchJobLock       = new object();

            this.context               = context;
            this.gitObjects            = gitObjects;
            this.fileSystemVirtualizer = fileSystemVirtualizer;

            this.placeHolderCreationCount       = new ConcurrentDictionary <string, PlaceHolderCreateCounter>(StringComparer.OrdinalIgnoreCase);
            this.newlyCreatedFileAndFolderPaths = new ConcurrentHashSet <string>(StringComparer.OrdinalIgnoreCase);

            string error;

            if (!ModifiedPathsDatabase.TryLoadOrCreate(
                    this.context.Tracer,
                    Path.Combine(this.context.Enlistment.DotGVFSRoot, GVFSConstants.DotGVFS.Databases.ModifiedPaths),
                    this.context.FileSystem,
                    out this.modifiedPaths,
                    out error))
            {
                throw new InvalidRepoException(error);
            }

            this.BlobSizes = blobSizes;
            this.BlobSizes.Initialize();

            PlaceholderListDatabase placeholders;

            if (!PlaceholderListDatabase.TryCreate(
                    this.context.Tracer,
                    Path.Combine(this.context.Enlistment.DotGVFSRoot, GVFSConstants.DotGVFS.Databases.PlaceholderList),
                    this.context.FileSystem,
                    out placeholders,
                    out error))
            {
                throw new InvalidRepoException(error);
            }

            this.GitIndexProjection = gitIndexProjection ?? new GitIndexProjection(
                context,
                gitObjects,
                this.BlobSizes,
                repoMetadata,
                fileSystemVirtualizer,
                placeholders,
                this.modifiedPaths);

            if (backgroundFileSystemTaskRunner != null)
            {
                this.backgroundFileSystemTaskRunner = backgroundFileSystemTaskRunner;
                this.backgroundFileSystemTaskRunner.SetCallbacks(
                    this.PreBackgroundOperation,
                    this.ExecuteBackgroundOperation,
                    this.PostBackgroundOperation);
            }
            else
            {
                this.backgroundFileSystemTaskRunner = new BackgroundFileSystemTaskRunner(
                    this.context,
                    this.PreBackgroundOperation,
                    this.ExecuteBackgroundOperation,
                    this.PostBackgroundOperation,
                    Path.Combine(context.Enlistment.DotGVFSRoot, GVFSConstants.DotGVFS.Databases.BackgroundFileSystemTasks));
            }

            this.enableGitStatusCache = gitStatusCache != null;

            // If the status cache is not enabled, create a dummy GitStatusCache that will never be initialized
            // This lets us from having to add null checks to callsites into GitStatusCache.
            this.gitStatusCache = gitStatusCache ?? new GitStatusCache(context, TimeSpan.Zero);

            this.logsHeadPath = Path.Combine(this.context.Enlistment.WorkingDirectoryRoot, GVFSConstants.DotGit.Logs.Head);

            EventMetadata metadata = new EventMetadata();

            metadata.Add("placeholders.Count", placeholders.EstimatedCount);
            metadata.Add("background.Count", this.backgroundFileSystemTaskRunner.Count);
            metadata.Add(TracingConstants.MessageKey.InfoMessage, $"{nameof(FileSystemCallbacks)} created");
            this.context.Tracer.RelatedEvent(EventLevel.Informational, $"{nameof(FileSystemCallbacks)}_Constructor", metadata);
        }
Ejemplo n.º 13
0
        public FileSystemCallbacks(
            GVFSContext context,
            GVFSGitObjects gitObjects,
            RepoMetadata repoMetadata,
            BlobSizes blobSizes,
            GitIndexProjection gitIndexProjection,
            BackgroundFileSystemTaskRunner backgroundFileSystemTaskRunner,
            FileSystemVirtualizer fileSystemVirtualizer)
        {
            this.logsHeadFileProperties = null;
            this.postFetchJobLock       = new object();

            this.context               = context;
            this.gitObjects            = gitObjects;
            this.fileSystemVirtualizer = fileSystemVirtualizer;

            this.placeHolderCreationCount = new ConcurrentDictionary <string, PlaceHolderCreateCounter>(StringComparer.OrdinalIgnoreCase);

            string error;

            if (!ModifiedPathsDatabase.TryLoadOrCreate(
                    this.context.Tracer,
                    Path.Combine(this.context.Enlistment.DotGVFSRoot, GVFSConstants.DotGVFS.Databases.ModifiedPaths),
                    this.context.FileSystem,
                    out this.modifiedPaths,
                    out error))
            {
                throw new InvalidRepoException(error);
            }

            this.BlobSizes = blobSizes;
            this.BlobSizes.Initialize();

            PlaceholderListDatabase placeholders;

            if (!PlaceholderListDatabase.TryCreate(
                    this.context.Tracer,
                    Path.Combine(this.context.Enlistment.DotGVFSRoot, GVFSConstants.DotGVFS.Databases.PlaceholderList),
                    this.context.FileSystem,
                    out placeholders,
                    out error))
            {
                throw new InvalidRepoException(error);
            }

            this.GitIndexProjection = gitIndexProjection ?? new GitIndexProjection(
                context,
                gitObjects,
                this.BlobSizes,
                repoMetadata,
                fileSystemVirtualizer,
                placeholders,
                this.modifiedPaths);

            this.backgroundFileSystemTaskRunner = backgroundFileSystemTaskRunner ?? new BackgroundFileSystemTaskRunner(
                this.context,
                this.PreBackgroundOperation,
                this.ExecuteBackgroundOperation,
                this.PostBackgroundOperation,
                Path.Combine(context.Enlistment.DotGVFSRoot, GVFSConstants.DotGVFS.Databases.BackgroundFileSystemTasks));

            this.logsHeadPath = Path.Combine(this.context.Enlistment.WorkingDirectoryRoot, GVFSConstants.DotGit.Logs.Head);

            EventMetadata metadata = new EventMetadata();

            metadata.Add("placeholders.Count", placeholders.EstimatedCount);
            metadata.Add("background.Count", this.backgroundFileSystemTaskRunner.Count);
            metadata.Add(TracingConstants.MessageKey.InfoMessage, $"{nameof(FileSystemCallbacks)} created");
            this.context.Tracer.RelatedEvent(EventLevel.Informational, $"{nameof(FileSystemCallbacks)}_Constructor", metadata);
        }
        private bool UpdatePlaceholderList(ITracer tracer, string dotGVFSRoot)
        {
            string esentPlaceholderFolder = Path.Combine(dotGVFSRoot, EsentPlaceholderListFolder);

            if (Directory.Exists(esentPlaceholderFolder))
            {
                string newPlaceholderFolder = Path.Combine(dotGVFSRoot, GVFSConstants.DotGVFS.Databases.PlaceholderList);
                try
                {
                    using (PersistentDictionary <string, string> oldPlaceholders =
                               new PersistentDictionary <string, string>(esentPlaceholderFolder))
                    {
                        string error;
                        PlaceholderListDatabase newPlaceholders;
                        if (!PlaceholderListDatabase.TryCreate(
                                tracer,
                                newPlaceholderFolder,
                                new PhysicalFileSystem(),
                                out newPlaceholders,
                                out error))
                        {
                            tracer.RelatedError("Failed to create new placeholder database: " + error);
                            return(false);
                        }

                        using (newPlaceholders)
                        {
                            List <PlaceholderListDatabase.PlaceholderData> data = new List <PlaceholderListDatabase.PlaceholderData>();
                            foreach (KeyValuePair <string, string> kvp in oldPlaceholders)
                            {
                                tracer.RelatedInfo("Copying ESENT entry: {0} = {1}", kvp.Key, kvp.Value);
                                data.Add(new PlaceholderListDatabase.PlaceholderData(path: kvp.Key, fileShaOrFolderValue: kvp.Value));
                            }

                            newPlaceholders.WriteAllEntriesAndFlush(data);
                        }
                    }
                }
                catch (IOException ex)
                {
                    tracer.RelatedError("Could not write to new placeholder database: " + ex.Message);
                    return(false);
                }
                catch (EsentException ex)
                {
                    tracer.RelatedError("Placeholder database appears to be from an older version of GVFS and corrupted: " + ex.Message);
                    return(false);
                }

                string backupName;
                if (this.TryRenameFolderForDelete(tracer, esentPlaceholderFolder, out backupName))
                {
                    // If this fails, we leave behind cruft, but there's no harm because we renamed.
                    this.TryDeleteFolder(tracer, backupName);
                    return(true);
                }
                else
                {
                    // To avoid double upgrading, we should rollback if we can't rename the old data
                    this.TryDeleteFile(tracer, RepoMetadata.Instance.DataFilePath);
                    return(false);
                }
            }

            return(true);
        }