public void 修改檔案日期()
        {
            using var fileSystem = new PhysicalFileSystem();
            var executingAssembly = Assembly.GetExecutingAssembly();
            var rootPath          = Path.GetDirectoryName(executingAssembly.Location);
            var rootUPath         = fileSystem.ConvertPathFromInternal(rootPath);
            var subName           = "TestFolder";

            var subPath      = $"{rootUPath}/{subName}";
            var subPath1     = $"{subPath}/1";
            var subFile1     = $"{subPath}/1/1.txt";
            var subFile2     = $"{subPath}/1/2.txt";
            var subPath1_1   = $"{subPath}/1/1_1";
            var subFile1_1   = $"{subPath}/1/1_1/1_1.txt";
            var subPath1_1_1 = $"{subPath}/1/1_1/1_1_1";
            var subPath2     = $"{subPath}/2";
            var content      = "This is test string";
            var contentBytes = Encoding.UTF8.GetBytes(content);

            if (fileSystem.DirectoryExists(subPath1_1_1) == false)
            {
                fileSystem.CreateDirectory(subPath1_1_1);
            }

            if (fileSystem.DirectoryExists(subPath2) == false)
            {
                fileSystem.CreateDirectory(subPath2);
            }

            if (fileSystem.FileExists(subFile1) == false)
            {
                using var stream =
                          fileSystem.OpenFile(subFile1, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.Read);
                stream.Write(contentBytes, 0, contentBytes.Length);
            }

            if (fileSystem.FileExists(subFile1_1) == false)
            {
                using var stream =
                          fileSystem.OpenFile(subFile1_1, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.Read);
                stream.Write(contentBytes, 0, contentBytes.Length);
            }

            var fileEntry = fileSystem.GetFileEntry(subFile1);

            fileEntry.CreationTime   = new DateTime(1900, 1, 1);
            fileEntry.LastWriteTime  = new DateTime(1900, 1, 2);
            fileEntry.LastAccessTime = new DateTime(1900, 1, 3);

            Assert.AreEqual(true, fileSystem.DirectoryExists(subPath1));
            Assert.AreEqual(true, fileSystem.DirectoryExists(subPath1_1));
            Assert.AreEqual(true, fileSystem.DirectoryExists(subPath1_1_1));
            Assert.AreEqual(true, fileSystem.DirectoryExists(subPath2));

            fileSystem.DeleteDirectory(subPath, true);
        }
        public void ShadowScopeCompleteWithFileConflict()
        {
            var path     = HostingEnvironment.MapPathContentRoot("FileSysTests");
            var shadowfs = HostingEnvironment.MapPathContentRoot(Constants.SystemDirectories.TempData.EnsureEndsWith('/') + "ShadowFs");

            Directory.CreateDirectory(path);

            var scopedFileSystems = false;

            var phy = new PhysicalFileSystem(IOHelper, HostingEnvironment, Logger, path, "ignore");

            var globalSettings = Options.Create(new GlobalSettings());
            var fileSystems    = new FileSystems(NullLoggerFactory.Instance, IOHelper, globalSettings, HostingEnvironment)
            {
                IsScoped = () => scopedFileSystems
            };
            var shadowPath = $"x/{Guid.NewGuid().ToString("N").Substring(0, 6)}";
            var sw         = fileSystems.CreateShadowWrapper(phy, shadowPath);

            using (var ms = new MemoryStream(Encoding.UTF8.GetBytes("foo")))
                sw.AddFile("sub/f1.txt", ms);
            Assert.IsTrue(phy.FileExists("sub/f1.txt"));

            string id;

            scopedFileSystems = true; // pretend we have a scope
            var scope = new ShadowFileSystems(fileSystems, id = ShadowWrapper.CreateShadowId(HostingEnvironment));

            Assert.IsTrue(Directory.Exists(shadowfs + "/" + id));
            using (var ms = new MemoryStream(Encoding.UTF8.GetBytes("foo")))
                sw.AddFile("sub/f2.txt", ms);
            Assert.IsFalse(phy.FileExists("sub/f2.txt"));

            // pretend we're another thread w/out scope
            scopedFileSystems = false;
            using (var ms = new MemoryStream(Encoding.UTF8.GetBytes("bar")))
                sw.AddFile("sub/f2.txt", ms);
            scopedFileSystems = true;                    // pretend we have a scope

            Assert.IsTrue(phy.FileExists("sub/f2.txt")); // other thread has written out to fs
            scope.Complete();
            scope.Dispose();
            scopedFileSystems = false;
            Assert.IsTrue(phy.FileExists("sub/f2.txt"));
            TestHelper.TryAssert(() => Assert.IsFalse(Directory.Exists(shadowfs + "/" + id)));

            string text;

            using (var s = phy.OpenFile("sub/f2.txt"))
                using (var r = new StreamReader(s))
                    text = r.ReadToEnd();

            // the shadow filesystem will happily overwrite anything it can
            Assert.AreEqual("foo", text);
        }
        public void ShadowScopeCompleteWithFileConflict()
        {
            var path    = IOHelper.MapPath("FileSysTests");
            var appdata = IOHelper.MapPath("App_Data");

            Directory.CreateDirectory(path);

            var scopedFileSystems = false;
            var scopeProvider     = MockScopeProvider(() => scopedFileSystems);

            var fs  = new PhysicalFileSystem(path, "ignore");
            var sw  = new ShadowWrapper(fs, "shadow", scopeProvider);
            var swa = new[] { sw };

            using (var ms = new MemoryStream(Encoding.UTF8.GetBytes("foo")))
                sw.AddFile("sub/f1.txt", ms);
            Assert.IsTrue(fs.FileExists("sub/f1.txt"));

            Guid id;

            scopedFileSystems = true; // pretend we have a scope
            var scope = new ShadowFileSystems(id = Guid.NewGuid(), swa);

            Assert.IsTrue(Directory.Exists(appdata + "/TEMP/ShadowFs/" + id));
            using (var ms = new MemoryStream(Encoding.UTF8.GetBytes("foo")))
                sw.AddFile("sub/f2.txt", ms);
            Assert.IsFalse(fs.FileExists("sub/f2.txt"));

            // pretend we're another thread w/out scope
            scopedFileSystems = false;
            using (var ms = new MemoryStream(Encoding.UTF8.GetBytes("bar")))
                sw.AddFile("sub/f2.txt", ms);
            scopedFileSystems = true;                   // pretend we have a scope

            Assert.IsTrue(fs.FileExists("sub/f2.txt")); // other thread has written out to fs
            scope.Complete();
            scope.Dispose();
            scopedFileSystems = false;
            Assert.IsTrue(fs.FileExists("sub/f2.txt"));
            TestHelper.TryAssert(() => Assert.IsFalse(Directory.Exists(appdata + "/TEMP/ShadowFs/" + id)));

            string text;

            using (var s = fs.OpenFile("sub/f2.txt"))
                using (var r = new StreamReader(s))
                    text = r.ReadToEnd();

            // the shadow filesystem will happily overwrite anything it can
            Assert.AreEqual("foo", text);
        }
예제 #4
0
        public static bool IsServiceRunningAndInstalled(
            ITracer tracer,
            PhysicalFileSystem fileSystem,
            out bool isServiceInstalled,
            out bool isDriverFileInstalled,
            out bool isNativeLibInstalled)
        {
            bool isRunning = false;

            isServiceInstalled    = false;
            isDriverFileInstalled = fileSystem.FileExists(Path.Combine(Environment.SystemDirectory, "drivers", DriverFileName));
            isNativeLibInstalled  = IsNativeLibInstalled(tracer, fileSystem);

            try
            {
                ServiceController controller = new ServiceController(DriverName);
                isRunning          = controller.Status.Equals(ServiceControllerStatus.Running);
                isServiceInstalled = true;
            }
            catch (InvalidOperationException e)
            {
                if (tracer != null)
                {
                    EventMetadata metadata = CreateEventMetadata();
                    metadata.Add("Exception", e.Message);
                    metadata.Add(TracingConstants.MessageKey.InfoMessage, $"{nameof(IsServiceRunningAndInstalled)}: InvalidOperationException: {ServiceName} service was not found");
                    tracer.RelatedEvent(EventLevel.Informational, $"{nameof(IsServiceRunningAndInstalled)}_ServiceNotFound", metadata);
                }

                return(false);
            }

            return(isRunning);
        }
예제 #5
0
        public static string GetNewLogFileName(
            string logsRoot,
            string prefix,
            string logId = null,
            PhysicalFileSystem fileSystem = null)
        {
            fileSystem = fileSystem ?? new PhysicalFileSystem();

            // TODO: Remove Directory.CreateDirectory() code from here
            // Don't change the state from an accessor.
            if (!fileSystem.DirectoryExists(logsRoot))
            {
                fileSystem.CreateDirectory(logsRoot);
            }

            logId = logId ?? DateTime.Now.ToString("yyyyMMdd_HHmmss");

            string name     = prefix + "_" + logId;
            string fullPath = Path.Combine(
                logsRoot,
                name + ".log");

            if (fileSystem.FileExists(fullPath))
            {
                fullPath = Path.Combine(
                    logsRoot,
                    name + "_" + Guid.NewGuid().ToString("N") + ".log");
            }

            return(fullPath);
        }
예제 #6
0
    public void ShadowCreateFile()
    {
        var path = HostingEnvironment.MapPathContentRoot("FileSysTests");

        Directory.CreateDirectory(path);
        Directory.CreateDirectory(path + "/ShadowTests");
        Directory.CreateDirectory(path + "/ShadowSystem");

        var fs  = new PhysicalFileSystem(IOHelper, HostingEnvironment, Logger, path + "/ShadowTests/", "ignore");
        var sfs = new PhysicalFileSystem(IOHelper, HostingEnvironment, Logger, path + "/ShadowSystem/", "ignore");
        var ss  = new ShadowFileSystem(fs, sfs);

        File.WriteAllText(path + "/ShadowTests/f2.txt", "foo");

        using (var ms = new MemoryStream(Encoding.UTF8.GetBytes("foo")))
        {
            ss.AddFile("f1.txt", ms);
        }

        Assert.IsTrue(File.Exists(path + "/ShadowTests/f2.txt"));
        Assert.IsFalse(File.Exists(path + "/ShadowSystem/f2.txt"));
        Assert.IsTrue(fs.FileExists("f2.txt"));
        Assert.IsTrue(ss.FileExists("f2.txt"));

        Assert.IsFalse(File.Exists(path + "/ShadowTests/f1.txt"));
        Assert.IsTrue(File.Exists(path + "/ShadowSystem/f1.txt"));
        Assert.IsFalse(fs.FileExists("f1.txt"));
        Assert.IsTrue(ss.FileExists("f1.txt"));

        var files = ss.GetFiles(string.Empty);

        Assert.AreEqual(2, files.Count());
        Assert.IsTrue(files.Contains("f1.txt"));
        Assert.IsTrue(files.Contains("f2.txt"));

        string content;

        using (var stream = ss.OpenFile("f1.txt"))
        {
            content = new StreamReader(stream).ReadToEnd();
        }

        Assert.AreEqual("foo", content);
    }
예제 #7
0
        public void ShadowDeleteFileInDir()
        {
            var path = IOHelper.MapPath("FileSysTests");

            Directory.CreateDirectory(path);
            Directory.CreateDirectory(path + "/ShadowTests");
            Directory.CreateDirectory(path + "/ShadowSystem");

            var fs  = new PhysicalFileSystem(path + "/ShadowTests/", "ignore");
            var sfs = new PhysicalFileSystem(path + "/ShadowSystem/", "ignore");
            var ss  = new ShadowFileSystem(fs, sfs);

            Directory.CreateDirectory(path + "/ShadowTests/sub");
            File.WriteAllText(path + "/ShadowTests/sub/f1.txt", "foo");
            File.WriteAllText(path + "/ShadowTests/sub/f2.txt", "foo");

            var files = fs.GetFiles("");

            Assert.AreEqual(0, files.Count());

            files = fs.GetFiles("sub");
            Assert.AreEqual(2, files.Count());
            Assert.IsTrue(files.Contains("sub/f1.txt"));
            Assert.IsTrue(files.Contains("sub/f2.txt"));

            files = ss.GetFiles("");
            Assert.AreEqual(0, files.Count());

            var dirs = ss.GetDirectories("");

            Assert.AreEqual(1, dirs.Count());
            Assert.IsTrue(dirs.Contains("sub"));

            files = ss.GetFiles("sub");
            Assert.AreEqual(2, files.Count());
            Assert.IsTrue(files.Contains("sub/f1.txt"));
            Assert.IsTrue(files.Contains("sub/f2.txt"));

            dirs = ss.GetDirectories("sub");
            Assert.AreEqual(0, dirs.Count());

            ss.DeleteFile("sub/f1.txt");

            Assert.IsTrue(File.Exists(path + "/ShadowTests/sub/f1.txt"));
            Assert.IsTrue(fs.FileExists("sub/f1.txt"));
            Assert.IsFalse(ss.FileExists("sub/f1.txt"));

            files = fs.GetFiles("sub");
            Assert.AreEqual(2, files.Count());
            Assert.IsTrue(files.Contains("sub/f1.txt"));
            Assert.IsTrue(files.Contains("sub/f2.txt"));

            files = ss.GetFiles("sub");
            Assert.AreEqual(1, files.Count());
            Assert.IsTrue(files.Contains("sub/f2.txt"));
        }
예제 #8
0
        public void MultiThread()
        {
            string           rootPath            = HostingEnvironment.MapPathWebRoot(GlobalSettings.UmbracoMediaPhysicalRootPath);
            string           rootUrl             = HostingEnvironment.ToAbsolute(GlobalSettings.UmbracoMediaPath);
            var              physMediaFileSystem = new PhysicalFileSystem(IOHelper, HostingEnvironment, GetRequiredService <ILogger <PhysicalFileSystem> >(), rootPath, rootUrl);
            MediaFileManager mediaFileManager    = MediaFileManager;
            var              taskHelper          = new TaskHelper(Mock.Of <ILogger <TaskHelper> >());

            IScopeProvider scopeProvider = ScopeProvider;

            using (IScope scope = scopeProvider.CreateScope(scopeFileSystems: true))
            {
                using (var ms = new MemoryStream(Encoding.UTF8.GetBytes("foo")))
                {
                    mediaFileManager.FileSystem.AddFile("f1.txt", ms);
                }

                Assert.IsTrue(mediaFileManager.FileSystem.FileExists("f1.txt"));
                Assert.IsFalse(physMediaFileSystem.FileExists("f1.txt"));

                // execute on another disconnected thread (execution context will not flow)
                Task t = taskHelper.ExecuteBackgroundTask(() =>
                {
                    Assert.IsFalse(mediaFileManager.FileSystem.FileExists("f1.txt"));

                    using (var ms = new MemoryStream(Encoding.UTF8.GetBytes("foo")))
                    {
                        mediaFileManager.FileSystem.AddFile("f2.txt", ms);
                    }

                    Assert.IsTrue(mediaFileManager.FileSystem.FileExists("f2.txt"));
                    Assert.IsTrue(physMediaFileSystem.FileExists("f2.txt"));

                    return(Task.CompletedTask);
                });

                Task.WaitAll(t);

                Assert.IsTrue(mediaFileManager.FileSystem.FileExists("f2.txt"));
                Assert.IsTrue(physMediaFileSystem.FileExists("f2.txt"));
            }
        }
예제 #9
0
        public void Execute()
        {
            if (Help)
            {
                HelpCommand.ViewHelpForCommand(CommandAttribute.CommandName);
            }
            else
            {
                if (String.IsNullOrEmpty(ConfigFile))
                {
                    Settings = NuGet.Settings.LoadDefaultSettings(
                        FileSystem,
                        configFileName: null,
                        machineWideSettings: MachineWideSettings);
                }
                else
                {
                    var directory        = Path.GetDirectoryName(Path.GetFullPath(ConfigFile));
                    var configFileName   = Path.GetFileName(ConfigFile);
                    var configFileSystem = new PhysicalFileSystem(directory);

                    // Create the config file when neccessary
                    if (!configFileSystem.FileExists(configFileName) &&
                        ShouldCreateConfigFile)
                    {
                        XmlUtility.CreateDocument("configuration", configFileSystem, configFileName);
                    }

                    Settings = NuGet.Settings.LoadDefaultSettings(
                        configFileSystem,
                        configFileName,
                        MachineWideSettings);
                }

                SourceProvider = PackageSourceBuilder.CreateSourceProvider(Settings);

                // Register an additional provider for the console specific application so that the user
                // will be prompted if a proxy is set and credentials are required
                var credentialProvider = new SettingsCredentialProvider(
                    new ConsoleCredentialProvider(Console),
                    SourceProvider,
                    Console);
                HttpClient.DefaultCredentialProvider = credentialProvider;
                RepositoryFactory = new NuGet.Common.CommandLineRepositoryFactory(Console);

                // enable the V3 shim
                if (ShimControllerProvider != null)
                {
                    ShimControllerProvider.Controller.Enable(SourceProvider);
                }

                ExecuteCommand();
            }
        }
        public ActionResult <CodeFileDisplay> GetByPath(string virtualPath)
        {
            if (string.IsNullOrWhiteSpace(virtualPath))
            {
                throw new ArgumentException("Value cannot be null or whitespace.", "virtualPath");
            }

            virtualPath = System.Web.HttpUtility.UrlDecode(virtualPath);

            return(_fileSystem.FileExists(virtualPath) ? _fileSystem.PathToCodeFile(virtualPath) : NotFound());
        }
예제 #11
0
        public void Execute()
        {
            if (Help)
            {
                HelpCommand.ViewHelpForCommand(CommandAttribute.CommandName);
            }
            else
            {
                Stopwatch watch = new Stopwatch();
                watch.Start();
                if (String.IsNullOrEmpty(ConfigFile))
                {
                    Settings = NuGet.Settings.LoadDefaultSettings(
                        FileSystem,
                        configFileName: null,
                        machineWideSettings: MachineWideSettings);
                }
                else
                {
                    var directory        = Path.GetDirectoryName(Path.GetFullPath(ConfigFile));
                    var configFileName   = Path.GetFileName(ConfigFile);
                    var configFileSystem = new PhysicalFileSystem(directory);

                    // Create the config file when neccessary
                    if (!configFileSystem.FileExists(configFileName) &&
                        ShouldCreateConfigFile)
                    {
                        XmlUtility.CreateDocument("configuration", configFileSystem, configFileName);
                    }

                    Settings = NuGet.Settings.LoadDefaultSettings(
                        configFileSystem,
                        configFileName,
                        MachineWideSettings);
                }

                SourceProvider = PackageSourceBuilder.CreateSourceProvider(Settings);

                // Register an additional provider for the console specific application so that the user
                // will be prompted if a proxy is set and credentials are required
                var credentialProvider = new SettingsCredentialProvider(
                    new ConsoleCredentialProvider(Console),
                    SourceProvider,
                    Console);
                HttpClient.DefaultCredentialProvider = credentialProvider;

                ExecuteCommand();
                watch.Stop();
                DisplayExecutedTime(watch.Elapsed, CommandAttribute.CommandName);
            }
        }
예제 #12
0
        public static bool IsNativeLibInstalled(ITracer tracer, PhysicalFileSystem fileSystem)
        {
            string system32Path     = Path.Combine(Environment.SystemDirectory, ProjFSNativeLibFileName);
            bool   existsInSystem32 = fileSystem.FileExists(system32Path);

            string gvfsAppDirectory = ProcessHelper.GetCurrentProcessLocation();
            string appFilePath;
            string installFilePath;

            GetNativeLibPaths(gvfsAppDirectory, out installFilePath, out appFilePath);
            bool existsInAppDirectory = fileSystem.FileExists(appFilePath);

            EventMetadata metadata = CreateEventMetadata();

            metadata.Add(nameof(system32Path), system32Path);
            metadata.Add(nameof(existsInSystem32), existsInSystem32);
            metadata.Add(nameof(gvfsAppDirectory), gvfsAppDirectory);
            metadata.Add(nameof(appFilePath), appFilePath);
            metadata.Add(nameof(installFilePath), installFilePath);
            metadata.Add(nameof(existsInAppDirectory), existsInAppDirectory);
            tracer.RelatedEvent(EventLevel.Informational, nameof(IsNativeLibInstalled), metadata);
            return(existsInSystem32 || existsInAppDirectory);
        }
예제 #13
0
        public static bool HasIssue(string blobSizesRoot, PhysicalFileSystem filesystem, out string issue)
        {
            issue = null;
            string databasePath = Path.Combine(blobSizesRoot, DatabaseName);

            if (filesystem.FileExists(databasePath))
            {
                List <string> integrityCheckResults = new List <string>();

                try
                {
                    string sqliteConnectionString = CreateSQLiteConnectionString(databasePath);
                    using (SqliteConnection integrityConnection = new SqliteConnection(sqliteConnectionString))
                    {
                        integrityConnection.Open();

                        using (SqliteCommand pragmaCommand = integrityConnection.CreateCommand())
                        {
                            pragmaCommand.CommandText = $"PRAGMA integrity_check;";
                            using (SqliteDataReader reader = pragmaCommand.ExecuteReader())
                            {
                                while (reader.Read())
                                {
                                    integrityCheckResults.Add(reader.GetString(0));
                                }
                            }
                        }
                    }
                }
                catch (Exception e)
                {
                    issue = "Exception while trying to access database: " + e.Message;
                    return(true);
                }

                // If pragma integrity_check finds no errors, a single row with the value 'ok' is returned
                // http://www.sqlite.org/pragma.html#pragma_integrity_check
                if (integrityCheckResults.Count != 1 || integrityCheckResults[0] != "ok")
                {
                    issue = string.Join(",", integrityCheckResults);
                    return(true);
                }
            }

            return(false);
        }
예제 #14
0
        public void Can_Read_And_Deserialize_Macro_From_Disc()
        {
            // Arrange
            var serviceStackSerializer = new ServiceStackJsonSerializer();
            var serializationService   = new SerializationService(serviceStackSerializer);
            var fileSystem             = new PhysicalFileSystem("~/App_Data/Macros");

            var macro = new Macro
            {
                Alias         = "test",
                CacheByPage   = false,
                CacheByMember = false,
                DontRender    = true,
                Name          = "Test",
                Xslt          = "/xslt/testMacro.xslt",
                UseInEditor   = false
            };

            macro.Properties = new List <IMacroProperty>();
            macro.Properties.Add(new MacroProperty {
                Alias = "level", Name = "Level", SortOrder = 0, PropertyType = new Umbraco.Core.Macros.PropertyTypes.Number()
            });
            macro.Properties.Add(new MacroProperty {
                Alias = "fixedTitle", Name = "Fixed Title", SortOrder = 1, PropertyType = new Umbraco.Core.Macros.PropertyTypes.Text()
            });

            // Act
            var    json       = serializationService.ToStream(macro);
            string jsonString = json.ResultStream.ToJsonString();

            fileSystem.AddFile("test-serialized-Macro.macro", json.ResultStream, true);

            Stream stream       = fileSystem.OpenFile("test-serialized-Macro.macro");
            object o            = serializationService.FromStream(stream, typeof(Macro));
            var    deserialized = o as IMacro;

            // Assert
            Assert.That(json.Success, Is.True);
            Assert.That(jsonString, Is.Not.Empty);
            Assert.That(fileSystem.FileExists("test-serialized-Macro.macro"), Is.True);
            Assert.That(deserialized, Is.Not.Null);
            Assert.That(deserialized.Name, Is.EqualTo(macro.Name));
            Assert.That(deserialized.Alias, Is.EqualTo(macro.Alias));
        }
예제 #15
0
        public void ShadowCreateFileInDir()
        {
            var path = IOHelper.MapPath("FileSysTests");

            Directory.CreateDirectory(path);
            Directory.CreateDirectory(path + "/ShadowTests");
            Directory.CreateDirectory(path + "/ShadowSystem");

            var fs  = new PhysicalFileSystem(path + "/ShadowTests/", "ignore");
            var sfs = new PhysicalFileSystem(path + "/ShadowSystem/", "ignore");
            var ss  = new ShadowFileSystem(fs, sfs);

            using (var ms = new MemoryStream(Encoding.UTF8.GetBytes("foo")))
                ss.AddFile("sub/f1.txt", ms);

            Assert.IsFalse(File.Exists(path + "/ShadowTests/sub/f1.txt"));
            Assert.IsTrue(File.Exists(path + "/ShadowSystem/sub/f1.txt"));
            Assert.IsFalse(fs.FileExists("sub/f1.txt"));
            Assert.IsTrue(ss.FileExists("sub/f1.txt"));

            Assert.IsFalse(fs.DirectoryExists("sub"));
            Assert.IsTrue(ss.DirectoryExists("sub"));

            var dirs = fs.GetDirectories("");

            Assert.AreEqual(0, dirs.Count());

            dirs = ss.GetDirectories("");
            Assert.AreEqual(1, dirs.Count());
            Assert.IsTrue(dirs.Contains("sub"));

            var files = ss.GetFiles("sub");

            Assert.AreEqual(1, files.Count());

            string content;

            using (var stream = ss.OpenFile("sub/f1.txt"))
                content = new StreamReader(stream).ReadToEnd();

            Assert.AreEqual("foo", content);
        }
예제 #16
0
    public void ShadowDeleteFile()
    {
        var path = HostingEnvironment.MapPathContentRoot("FileSysTests");

        Directory.CreateDirectory(path);
        Directory.CreateDirectory(path + "/ShadowTests");
        Directory.CreateDirectory(path + "/ShadowSystem");

        var fs  = new PhysicalFileSystem(IOHelper, HostingEnvironment, Logger, path + "/ShadowTests/", "ignore");
        var sfs = new PhysicalFileSystem(IOHelper, HostingEnvironment, Logger, path + "/ShadowSystem/", "ignore");
        var ss  = new ShadowFileSystem(fs, sfs);

        File.WriteAllText(path + "/ShadowTests/f1.txt", "foo");
        File.WriteAllText(path + "/ShadowTests/f2.txt", "foo");

        var files = fs.GetFiles(string.Empty);

        Assert.AreEqual(2, files.Count());
        Assert.IsTrue(files.Contains("f1.txt"));
        Assert.IsTrue(files.Contains("f2.txt"));

        files = ss.GetFiles(string.Empty);
        Assert.AreEqual(2, files.Count());
        Assert.IsTrue(files.Contains("f1.txt"));
        Assert.IsTrue(files.Contains("f2.txt"));

        var dirs = ss.GetDirectories(string.Empty);

        Assert.AreEqual(0, dirs.Count());

        ss.DeleteFile("f1.txt");

        Assert.IsTrue(File.Exists(path + "/ShadowTests/f1.txt"));
        Assert.IsTrue(fs.FileExists("f1.txt"));
        Assert.IsFalse(ss.FileExists("f1.txt"));

        files = ss.GetFiles(string.Empty);
        Assert.AreEqual(1, files.Count());
        Assert.IsTrue(files.Contains("f2.txt"));
    }
예제 #17
0
    public void ShadowScopeComplete()
    {
        var loggerFactory = NullLoggerFactory.Instance;
        var path          = HostingEnvironment.MapPathContentRoot("FileSysTests");
        var shadowfs      =
            HostingEnvironment.MapPathContentRoot(Constants.SystemDirectories.TempData.EnsureEndsWith('/') +
                                                  "ShadowFs");

        Directory.CreateDirectory(path);
        Directory.CreateDirectory(shadowfs);

        var scopedFileSystems = false;

        var phy = new PhysicalFileSystem(IOHelper, HostingEnvironment, Logger, path, "ignore");

        var globalSettings = Options.Create(new GlobalSettings());
        var fileSystems    =
            new FileSystems(loggerFactory, IOHelper, globalSettings, HostingEnvironment)
        {
            IsScoped = () => scopedFileSystems
        };
        var shadowPath = $"x/{Guid.NewGuid().ToString("N").Substring(0, 6)}";
        var sw         = (ShadowWrapper)fileSystems.CreateShadowWrapper(phy, shadowPath);

        using (var ms = new MemoryStream(Encoding.UTF8.GetBytes("foo")))
        {
            sw.AddFile("sub/f1.txt", ms);
        }

        Assert.IsTrue(phy.FileExists("sub/f1.txt"));

        string id;

        // explicit shadow without scope does not work
        sw.Shadow(id = ShadowWrapper.CreateShadowId(HostingEnvironment));
        Assert.IsTrue(Directory.Exists(shadowfs + "/" + id));
        using (var ms = new MemoryStream(Encoding.UTF8.GetBytes("foo")))
        {
            sw.AddFile("sub/f2.txt", ms);
        }

        Assert.IsTrue(phy.FileExists("sub/f2.txt"));
        sw.UnShadow(true);
        Assert.IsTrue(phy.FileExists("sub/f2.txt"));
        Assert.IsFalse(Directory.Exists(shadowfs + "/" + id));

        // shadow with scope but no complete does not complete
        scopedFileSystems = true; // pretend we have a scope
        var scope = new ShadowFileSystems(fileSystems, id = ShadowWrapper.CreateShadowId(HostingEnvironment));

        Assert.IsTrue(Directory.Exists(shadowfs + "/" + id));
        using (var ms = new MemoryStream(Encoding.UTF8.GetBytes("foo")))
        {
            sw.AddFile("sub/f3.txt", ms);
        }

        Assert.IsFalse(phy.FileExists("sub/f3.txt"));
        var dirs = Directory.GetDirectories(shadowfs);

        Assert.AreEqual(1, dirs.Length);
        Assert.AreEqual((shadowfs + "/" + id).Replace('\\', '/'), dirs[0].Replace('\\', '/'));
        dirs = Directory.GetDirectories(dirs[0]);
        var typedDir = dirs.FirstOrDefault(x => x.Replace('\\', '/').EndsWith("/x"));

        Assert.IsNotNull(typedDir);
        dirs = Directory.GetDirectories(typedDir);
        var scopedDir =
            dirs.FirstOrDefault(x => x.Replace('\\', '/').EndsWith("/" + shadowPath)); // this is where files go

        Assert.IsNotNull(scopedDir);
        scope.Dispose();
        scopedFileSystems = false;
        Assert.IsFalse(phy.FileExists("sub/f3.txt"));
        TestHelper.TryAssert(() => Assert.IsFalse(Directory.Exists(shadowfs + "/" + id)));

        // shadow with scope and complete does complete
        scopedFileSystems = true; // pretend we have a scope
        scope             = new ShadowFileSystems(fileSystems, id = ShadowWrapper.CreateShadowId(HostingEnvironment));
        Assert.IsTrue(Directory.Exists(shadowfs + "/" + id));
        using (var ms = new MemoryStream(Encoding.UTF8.GetBytes("foo")))
        {
            sw.AddFile("sub/f4.txt", ms);
        }

        Assert.IsFalse(phy.FileExists("sub/f4.txt"));
        Assert.AreEqual(1, Directory.GetDirectories(shadowfs).Length);
        scope.Complete();
        scope.Dispose();
        scopedFileSystems = false;
        TestHelper.TryAssert(() => Assert.AreEqual(0, Directory.GetDirectories(shadowfs).Length));
        Assert.IsTrue(phy.FileExists("sub/f4.txt"));
        Assert.IsFalse(Directory.Exists(shadowfs + "/" + id));

        // test scope for "another thread"

        scopedFileSystems = true; // pretend we have a scope
        scope             = new ShadowFileSystems(fileSystems, id = ShadowWrapper.CreateShadowId(HostingEnvironment));
        Assert.IsTrue(Directory.Exists(shadowfs + "/" + id));
        using (var ms = new MemoryStream(Encoding.UTF8.GetBytes("foo")))
        {
            sw.AddFile("sub/f5.txt", ms);
        }

        Assert.IsFalse(phy.FileExists("sub/f5.txt"));

        // pretend we're another thread w/out scope
        scopedFileSystems = false;
        using (var ms = new MemoryStream(Encoding.UTF8.GetBytes("foo")))
        {
            sw.AddFile("sub/f6.txt", ms);
        }

        scopedFileSystems = true;                    // pretend we have a scope

        Assert.IsTrue(phy.FileExists("sub/f6.txt")); // other thread has written out to fs
        scope.Complete();
        scope.Dispose();
        scopedFileSystems = false;
        Assert.IsTrue(phy.FileExists("sub/f5.txt"));
        TestHelper.TryAssert(() => Assert.IsFalse(Directory.Exists(shadowfs + "/" + id)));
    }
예제 #18
0
        public override bool TryUpgrade(ITracer tracer, string enlistmentRoot)
        {
            ModifiedPathsDatabase modifiedPaths = null;

            try
            {
                PhysicalFileSystem fileSystem = new PhysicalFileSystem();

                string modifiedPathsDatabasePath = Path.Combine(enlistmentRoot, GVFSConstants.DotGVFS.Root, GVFSConstants.DotGVFS.Databases.ModifiedPaths);
                string error;
                if (!ModifiedPathsDatabase.TryLoadOrCreate(tracer, modifiedPathsDatabasePath, fileSystem, out modifiedPaths, out error))
                {
                    tracer.RelatedError($"Unable to create the modified paths database. {error}");
                    return(false);
                }

                string sparseCheckoutPath = Path.Combine(enlistmentRoot, GVFSConstants.WorkingDirectoryRootName, GVFSConstants.DotGit.Info.SparseCheckoutPath);
                IEnumerable <string> sparseCheckoutLines = fileSystem.ReadAllText(sparseCheckoutPath).Split(new string[] { "\r", "\n" }, StringSplitOptions.RemoveEmptyEntries);
                bool isRetryable;
                foreach (string entry in sparseCheckoutLines)
                {
                    bool isFolder = entry.EndsWith(GVFSConstants.GitPathSeparatorString);
                    if (!modifiedPaths.TryAdd(entry.Trim(GVFSConstants.GitPathSeparator), isFolder, out isRetryable))
                    {
                        tracer.RelatedError("Unable to add to the modified paths database.");
                        return(false);
                    }
                }

                string alwaysExcludePath = Path.Combine(enlistmentRoot, GVFSConstants.WorkingDirectoryRootName, GVFSConstants.DotGit.Info.AlwaysExcludePath);
                if (fileSystem.FileExists(alwaysExcludePath))
                {
                    string[] alwaysExcludeLines = fileSystem.ReadAllText(alwaysExcludePath).Split(new string[] { "\r", "\n" }, StringSplitOptions.RemoveEmptyEntries);
                    for (int i = alwaysExcludeLines.Length - 1; i >= 0; i--)
                    {
                        string entry = alwaysExcludeLines[i];
                        if (entry.EndsWith("*"))
                        {
                            // This is the first entry using the old format and we don't want to process old entries
                            // because we would need folder entries since there isn't a file and that would cause sparse-checkout to
                            // recursively clear skip-worktree bits for everything under that folder
                            break;
                        }

                        entry = entry.TrimStart('!');
                        bool isFolder = entry.EndsWith(GVFSConstants.GitPathSeparatorString);
                        if (!isFolder)
                        {
                            if (!modifiedPaths.TryAdd(entry.Trim(GVFSConstants.GitPathSeparator), isFolder, out isRetryable))
                            {
                                tracer.RelatedError("Unable to add to the modified paths database.");
                                return(false);
                            }
                        }
                    }
                }

                modifiedPaths.ForceFlush();
                fileSystem.WriteAllText(sparseCheckoutPath, "/.gitattributes" + Environment.NewLine);
                fileSystem.DeleteFile(alwaysExcludePath);
            }
            catch (IOException ex)
            {
                tracer.RelatedError($"IOException: {ex.ToString()}");
                return(false);
            }
            finally
            {
                if (modifiedPaths != null)
                {
                    modifiedPaths.Dispose();
                    modifiedPaths = null;
                }
            }

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

            return(true);
        }
        public override bool TryUpgrade(ITracer tracer, string enlistmentRoot)
        {
            ModifiedPathsDatabase modifiedPaths = null;

            try
            {
                PhysicalFileSystem fileSystem = new PhysicalFileSystem();

                string modifiedPathsDatabasePath = Path.Combine(enlistmentRoot, GVFSConstants.DotGVFS.Root, GVFSConstants.DotGVFS.Databases.ModifiedPaths);
                string error;
                if (!ModifiedPathsDatabase.TryLoadOrCreate(tracer, modifiedPathsDatabasePath, fileSystem, out modifiedPaths, out error))
                {
                    tracer.RelatedError($"Unable to create the modified paths database. {error}");
                    return(false);
                }

                string sparseCheckoutPath = Path.Combine(enlistmentRoot, GVFSConstants.WorkingDirectoryRootName, GVFSConstants.DotGit.Info.SparseCheckoutPath);
                bool   isRetryable;
                using (FileStream fs = File.OpenRead(sparseCheckoutPath))
                    using (StreamReader reader = new StreamReader(fs))
                    {
                        string entry = reader.ReadLine();
                        while (entry != null)
                        {
                            entry = entry.Trim();
                            if (!string.IsNullOrWhiteSpace(entry))
                            {
                                bool isFolder = entry.EndsWith(GVFSConstants.GitPathSeparatorString);
                                if (!modifiedPaths.TryAdd(entry.Trim(GVFSConstants.GitPathSeparator), isFolder, out isRetryable))
                                {
                                    tracer.RelatedError("Unable to add to the modified paths database.");
                                    return(false);
                                }
                            }

                            entry = reader.ReadLine();
                        }
                    }

                string alwaysExcludePath = Path.Combine(enlistmentRoot, GVFSConstants.WorkingDirectoryRootName, GVFSConstants.DotGit.Info.AlwaysExcludePath);
                if (fileSystem.FileExists(alwaysExcludePath))
                {
                    string alwaysExcludeData = fileSystem.ReadAllText(alwaysExcludePath);

                    char[] carriageReturnOrLineFeed = new[] { '\r', '\n' };
                    int    endPosition = alwaysExcludeData.Length;
                    while (endPosition > 0)
                    {
                        int startPosition = alwaysExcludeData.LastIndexOfAny(carriageReturnOrLineFeed, endPosition - 1);
                        if (startPosition < 0)
                        {
                            startPosition = 0;
                        }

                        string entry = alwaysExcludeData.Substring(startPosition, endPosition - startPosition).Trim();

                        if (entry.EndsWith("*"))
                        {
                            // This is the first entry using the old format and we don't want to process old entries
                            // because we would need folder entries since there isn't a file and that would cause sparse-checkout to
                            // recursively clear skip-worktree bits for everything under that folder
                            break;
                        }

                        // Substring will not return a null and the Trim will get rid of all the whitespace
                        // if there is a length it will be a valid path that we need to process
                        if (entry.Length > 0)
                        {
                            entry = entry.TrimStart('!');
                            bool isFolder = entry.EndsWith(GVFSConstants.GitPathSeparatorString);
                            if (!isFolder)
                            {
                                if (!modifiedPaths.TryAdd(entry.Trim(GVFSConstants.GitPathSeparator), isFolder, out isRetryable))
                                {
                                    tracer.RelatedError("Unable to add to the modified paths database.");
                                    return(false);
                                }
                            }
                        }

                        endPosition = startPosition;
                    }
                }

                modifiedPaths.ForceFlush();
                fileSystem.WriteAllText(sparseCheckoutPath, "/.gitattributes" + Environment.NewLine);
                fileSystem.DeleteFile(alwaysExcludePath);
            }
            catch (IOException ex)
            {
                tracer.RelatedError($"IOException: {ex.ToString()}");
                return(false);
            }
            finally
            {
                if (modifiedPaths != null)
                {
                    modifiedPaths.Dispose();
                    modifiedPaths = null;
                }
            }

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

            return(true);
        }
예제 #20
0
        public void TestFile()
        {
            var fs                 = new PhysicalFileSystem();
            var path               = fs.ConvertPathFromInternal(SystemPath);
            var fileName           = $"toto-{Guid.NewGuid()}.txt";
            var filePath           = path / fileName;
            var filePathDest       = path / Path.ChangeExtension(fileName, "dest");
            var filePathBack       = path / Path.ChangeExtension(fileName, "bak");
            var systemFilePath     = Path.Combine(SystemPath, fileName);
            var systemFilePathDest = fs.ConvertPathToInternal(filePathDest);
            var systemFilePathBack = fs.ConvertPathToInternal(filePathBack);

            try
            {
                // CreateFile / OpenFile
                var fileStream = fs.CreateFile(filePath);
                var buffer     = Encoding.UTF8.GetBytes("This is a test");
                fileStream.Write(buffer, 0, buffer.Length);
                fileStream.Dispose();

                // FileLength
                Assert.Equal(buffer.Length, fs.GetFileLength(filePath));

                // LastAccessTime
                // LastWriteTime
                // CreationTime
                Assert.Equal(File.GetLastWriteTime(systemFilePath), fs.GetLastWriteTime(filePath));
                Assert.Equal(File.GetLastAccessTime(systemFilePath), fs.GetLastAccessTime(filePath));
                Assert.Equal(File.GetCreationTime(systemFilePath), fs.GetCreationTime(filePath));

                var lastWriteTime  = DateTime.Now + TimeSpan.FromSeconds(10);
                var lastAccessTime = DateTime.Now + TimeSpan.FromSeconds(11);
                var creationTime   = DateTime.Now + TimeSpan.FromSeconds(12);
                fs.SetLastWriteTime(filePath, lastWriteTime);
                fs.SetLastAccessTime(filePath, lastAccessTime);
                fs.SetCreationTime(filePath, creationTime);
                Assert.Equal(lastWriteTime, fs.GetLastWriteTime(filePath));
                Assert.Equal(lastAccessTime, fs.GetLastAccessTime(filePath));
                Assert.Equal(creationTime, fs.GetCreationTime(filePath));

                // FileAttributes
                Assert.Equal(File.GetAttributes(systemFilePath), fs.GetAttributes(filePath));

                var attributes = fs.GetAttributes(filePath);
                attributes |= FileAttributes.ReadOnly;
                fs.SetAttributes(filePath, attributes);

                Assert.Equal(File.GetAttributes(systemFilePath), fs.GetAttributes(filePath));

                attributes &= ~FileAttributes.ReadOnly;
                fs.SetAttributes(filePath, attributes);
                Assert.Equal(File.GetAttributes(systemFilePath), fs.GetAttributes(filePath));

                // FileExists
                Assert.True(File.Exists(systemFilePath));
                Assert.True(fs.FileExists(filePath));

                // CopyFile
                fs.CopyFile(filePath, filePathDest, true);
                Assert.True(File.Exists(systemFilePathDest));
                Assert.True(fs.FileExists(filePathDest));

                // DeleteFile
                fs.DeleteFile(filePath);
                Assert.False(File.Exists(systemFilePath));
                Assert.False(fs.FileExists(filePath));

                // MoveFile
                fs.MoveFile(filePathDest, filePath);
                Assert.False(File.Exists(systemFilePathDest));
                Assert.False(fs.FileExists(filePathDest));
                Assert.True(File.Exists(systemFilePath));
                Assert.True(fs.FileExists(filePath));

                // ReplaceFile

                // copy file to filePathDest
                fs.CopyFile(filePath, filePathDest, true);

                // Change src file
                var filestream2 = fs.OpenFile(filePath, FileMode.Open, FileAccess.ReadWrite);
                var buffer2     = Encoding.UTF8.GetBytes("This is a test 123");
                filestream2.Write(buffer2, 0, buffer2.Length);
                filestream2.Dispose();
                Assert.Equal(buffer2.Length, fs.GetFileLength(filePath));

                // Perform ReplaceFile
                fs.ReplaceFile(filePath, filePathDest, filePathBack, true);
                Assert.False(fs.FileExists(filePath));
                Assert.True(fs.FileExists(filePathDest));
                Assert.True(fs.FileExists(filePathBack));

                Assert.Equal(buffer2.Length, fs.GetFileLength(filePathDest));
                Assert.Equal(buffer.Length, fs.GetFileLength(filePathBack));

                // RootFileSystem
                fs.GetLastWriteTime("/");
                fs.GetLastAccessTime("/");
                fs.GetCreationTime("/");

                fs.GetLastWriteTime("/mnt");
                fs.GetLastAccessTime("/mnt");
                fs.GetCreationTime("/mnt");

                fs.GetLastWriteTime("/mnt/c");
                fs.GetLastAccessTime("/mnt/c");
                fs.GetCreationTime("/mnt/c");
                fs.GetAttributes("/mnt/c");

                var sysAttr = FileAttributes.Directory | FileAttributes.System | FileAttributes.ReadOnly;
                Assert.True((fs.GetAttributes("/") & (sysAttr)) == sysAttr);
                Assert.True((fs.GetAttributes("/mnt") & (sysAttr)) == sysAttr);
            }
            finally
            {
                SafeDeleteFile(systemFilePath);
                SafeDeleteFile(systemFilePathDest);
                SafeDeleteFile(systemFilePathBack);
            }
        }
예제 #21
0
        public void ShadowScopeCompleteWithDirectoryConflict()
        {
            var logger = Mock.Of <ILogger>();

            var path     = IOHelper.MapPath("FileSysTests");
            var shadowfs = IOHelper.MapPath("App_Data/TEMP/ShadowFs");

            Directory.CreateDirectory(path);

            var scopedFileSystems = false;

            var phy = new PhysicalFileSystem(path, "ignore");

            var container   = Mock.Of <IFactory>();
            var fileSystems = new FileSystems(container, logger)
            {
                IsScoped = () => scopedFileSystems
            };
            var fs = fileSystems.GetFileSystem <FS>(phy);
            var sw = (ShadowWrapper)fs.InnerFileSystem;

            using (var ms = new MemoryStream(Encoding.UTF8.GetBytes("foo")))
                sw.AddFile("sub/f1.txt", ms);
            Assert.IsTrue(phy.FileExists("sub/f1.txt"));

            Guid id;

            scopedFileSystems = true; // pretend we have a scope
            var scope = new ShadowFileSystems(fileSystems, id = Guid.NewGuid());

            Assert.IsTrue(Directory.Exists(shadowfs + "/" + id));
            using (var ms = new MemoryStream(Encoding.UTF8.GetBytes("foo")))
                sw.AddFile("sub/f2.txt", ms);
            Assert.IsFalse(phy.FileExists("sub/f2.txt"));

            // pretend we're another thread w/out scope
            scopedFileSystems = false;
            using (var ms = new MemoryStream(Encoding.UTF8.GetBytes("bar")))
                sw.AddFile("sub/f2.txt/f2.txt", ms);
            scopedFileSystems = true;                           // pretend we have a scope

            Assert.IsTrue(phy.FileExists("sub/f2.txt/f2.txt")); // other thread has written out to fs

            using (var ms = new MemoryStream(Encoding.UTF8.GetBytes("foo")))
                sw.AddFile("sub/f3.txt", ms);
            Assert.IsFalse(phy.FileExists("sub/f3.txt"));

            scope.Complete();

            try
            {
                // no way this can work since we're trying to write a file
                // but there's now a directory with the same name on the real fs
                scope.Dispose();
                Assert.Fail("Expected AggregateException.");
            }
            catch (AggregateException ae)
            {
                Assert.AreEqual(1, ae.InnerExceptions.Count);
                var e = ae.InnerExceptions[0];
                Assert.IsNotNull(e.InnerException);
                Assert.IsInstanceOf <AggregateException>(e);
                ae = (AggregateException)e;

                Assert.AreEqual(1, ae.InnerExceptions.Count);
                e = ae.InnerExceptions[0];
                Assert.IsNotNull(e.InnerException);
                Assert.IsInstanceOf <Exception>(e.InnerException);
            }

            // still, the rest of the changes has been applied ok
            Assert.IsTrue(phy.FileExists("sub/f3.txt"));
        }
예제 #22
0
        public void ShadowScopeComplete()
        {
            var logger = Mock.Of <ILogger>();

            var path     = IOHelper.MapPath("FileSysTests");
            var shadowfs = IOHelper.MapPath("App_Data/TEMP/ShadowFs");

            Directory.CreateDirectory(path);
            Directory.CreateDirectory(shadowfs);

            var scopedFileSystems = false;

            var phy = new PhysicalFileSystem(path, "ignore");

            var container   = Mock.Of <IFactory>();
            var fileSystems = new FileSystems(container, logger)
            {
                IsScoped = () => scopedFileSystems
            };
            var fs = fileSystems.GetFileSystem <FS>(phy);
            var sw = (ShadowWrapper)fs.InnerFileSystem;

            using (var ms = new MemoryStream(Encoding.UTF8.GetBytes("foo")))
                sw.AddFile("sub/f1.txt", ms);
            Assert.IsTrue(phy.FileExists("sub/f1.txt"));

            Guid id;

            // explicit shadow without scope does not work
            sw.Shadow(id = Guid.NewGuid());
            Assert.IsTrue(Directory.Exists(shadowfs + "/" + id));
            using (var ms = new MemoryStream(Encoding.UTF8.GetBytes("foo")))
                sw.AddFile("sub/f2.txt", ms);
            Assert.IsTrue(phy.FileExists("sub/f2.txt"));
            sw.UnShadow(true);
            Assert.IsTrue(phy.FileExists("sub/f2.txt"));
            Assert.IsFalse(Directory.Exists(shadowfs + "/" + id));

            // shadow with scope but no complete does not complete
            scopedFileSystems = true; // pretend we have a scope
            var scope = new ShadowFileSystems(fileSystems, id = Guid.NewGuid());

            Assert.IsTrue(Directory.Exists(shadowfs + "/" + id));
            using (var ms = new MemoryStream(Encoding.UTF8.GetBytes("foo")))
                sw.AddFile("sub/f3.txt", ms);
            Assert.IsFalse(phy.FileExists("sub/f3.txt"));
            var dirs = Directory.GetDirectories(shadowfs);

            Assert.AreEqual(1, dirs.Length);
            Assert.AreEqual((shadowfs + "/" + id).Replace('\\', '/'), dirs[0].Replace('\\', '/'));
            dirs = Directory.GetDirectories(dirs[0]);
            var typedDir = dirs.FirstOrDefault(x => x.Replace('\\', '/').EndsWith("/typed"));

            Assert.IsNotNull(typedDir);
            dirs = Directory.GetDirectories(typedDir);
            var scopedDir = dirs.FirstOrDefault(x => x.Replace('\\', '/').EndsWith("/Umbraco.Tests.IO.ShadowFileSystemTests+FS")); // this is where files go

            Assert.IsNotNull(scopedDir);
            scope.Dispose();
            scopedFileSystems = false;
            Assert.IsFalse(phy.FileExists("sub/f3.txt"));
            TestHelper.TryAssert(() => Assert.IsFalse(Directory.Exists(shadowfs + "/" + id)));

            // shadow with scope and complete does complete
            scopedFileSystems = true; // pretend we have a scope
            scope             = new ShadowFileSystems(fileSystems, id = Guid.NewGuid());
            Assert.IsTrue(Directory.Exists(shadowfs + "/" + id));
            using (var ms = new MemoryStream(Encoding.UTF8.GetBytes("foo")))
                sw.AddFile("sub/f4.txt", ms);
            Assert.IsFalse(phy.FileExists("sub/f4.txt"));
            Assert.AreEqual(1, Directory.GetDirectories(shadowfs).Length);
            scope.Complete();
            scope.Dispose();
            scopedFileSystems = false;
            TestHelper.TryAssert(() => Assert.AreEqual(0, Directory.GetDirectories(shadowfs).Length));
            Assert.IsTrue(phy.FileExists("sub/f4.txt"));
            Assert.IsFalse(Directory.Exists(shadowfs + "/" + id));

            // test scope for "another thread"

            scopedFileSystems = true; // pretend we have a scope
            scope             = new ShadowFileSystems(fileSystems, id = Guid.NewGuid());
            Assert.IsTrue(Directory.Exists(shadowfs + "/" + id));
            using (var ms = new MemoryStream(Encoding.UTF8.GetBytes("foo")))
                sw.AddFile("sub/f5.txt", ms);
            Assert.IsFalse(phy.FileExists("sub/f5.txt"));

            // pretend we're another thread w/out scope
            scopedFileSystems = false;
            using (var ms = new MemoryStream(Encoding.UTF8.GetBytes("foo")))
                sw.AddFile("sub/f6.txt", ms);
            scopedFileSystems = true;                    // pretend we have a scope

            Assert.IsTrue(phy.FileExists("sub/f6.txt")); // other thread has written out to fs
            scope.Complete();
            scope.Dispose();
            scopedFileSystems = false;
            Assert.IsTrue(phy.FileExists("sub/f5.txt"));
            Assert.IsFalse(Directory.Exists(shadowfs + "/" + id));
        }
예제 #23
0
 public static void ShouldBeAPhysicalFile(this string physicalPath, PhysicalFileSystem fileSystem)
 {
     fileSystem.FileExists(physicalPath).ShouldEqual(true);
 }
        public void ShadowScopeComplete()
        {
            var path    = IOHelper.MapPath("FileSysTests");
            var appdata = IOHelper.MapPath("App_Data");

            Directory.CreateDirectory(path);
            Directory.CreateDirectory(appdata);

            var scopedFileSystems = false;
            var scopeProvider     = MockScopeProvider(() => scopedFileSystems);

            var fs  = new PhysicalFileSystem(path, "ignore");
            var sw  = new ShadowWrapper(fs, "shadow", scopeProvider);
            var swa = new[] { sw };

            using (var ms = new MemoryStream(Encoding.UTF8.GetBytes("foo")))
                sw.AddFile("sub/f1.txt", ms);
            Assert.IsTrue(fs.FileExists("sub/f1.txt"));

            Guid id;

            // explicit shadow without scope does not work
            sw.Shadow(id = Guid.NewGuid());
            Assert.IsTrue(Directory.Exists(appdata + "/TEMP/ShadowFs/" + id));
            using (var ms = new MemoryStream(Encoding.UTF8.GetBytes("foo")))
                sw.AddFile("sub/f2.txt", ms);
            Assert.IsTrue(fs.FileExists("sub/f2.txt"));
            sw.UnShadow(true);
            Assert.IsTrue(fs.FileExists("sub/f2.txt"));
            Assert.IsFalse(Directory.Exists(appdata + "/TEMP/ShadowFs/" + id));

            // shadow with scope but no complete does not complete
            scopedFileSystems = true; // pretend we have a scope
            var scope = new ShadowFileSystems(id = Guid.NewGuid(), swa);

            Assert.IsTrue(Directory.Exists(appdata + "/TEMP/ShadowFs/" + id));
            using (var ms = new MemoryStream(Encoding.UTF8.GetBytes("foo")))
                sw.AddFile("sub/f3.txt", ms);
            Assert.IsFalse(fs.FileExists("sub/f3.txt"));
            Assert.AreEqual(1, Directory.GetDirectories(appdata + "/TEMP/ShadowFs").Length);
            scope.Dispose();
            scopedFileSystems = false;
            Assert.IsFalse(fs.FileExists("sub/f3.txt"));
            Assert.IsFalse(Directory.Exists(appdata + "/TEMP/ShadowFs/" + id));

            // shadow with scope and complete does complete
            scopedFileSystems = true; // pretend we have a scope
            scope             = new ShadowFileSystems(id = Guid.NewGuid(), swa);
            Assert.IsTrue(Directory.Exists(appdata + "/TEMP/ShadowFs/" + id));
            using (var ms = new MemoryStream(Encoding.UTF8.GetBytes("foo")))
                sw.AddFile("sub/f4.txt", ms);
            Assert.IsFalse(fs.FileExists("sub/f4.txt"));
            Assert.AreEqual(1, Directory.GetDirectories(appdata + "/TEMP/ShadowFs").Length);
            scope.Complete();
            scope.Dispose();
            scopedFileSystems = false;
            TestHelper.TryAssert(() => Assert.AreEqual(0, Directory.GetDirectories(appdata + "/TEMP/ShadowFs").Length));
            Assert.IsTrue(fs.FileExists("sub/f4.txt"));
            Assert.IsFalse(Directory.Exists(appdata + "/TEMP/ShadowFs/" + id));

            // test scope for "another thread"

            scopedFileSystems = true; // pretend we have a scope
            scope             = new ShadowFileSystems(id = Guid.NewGuid(), swa);
            Assert.IsTrue(Directory.Exists(appdata + "/TEMP/ShadowFs/" + id));
            using (var ms = new MemoryStream(Encoding.UTF8.GetBytes("foo")))
                sw.AddFile("sub/f5.txt", ms);
            Assert.IsFalse(fs.FileExists("sub/f5.txt"));

            // pretend we're another thread w/out scope
            scopedFileSystems = false;
            using (var ms = new MemoryStream(Encoding.UTF8.GetBytes("foo")))
                sw.AddFile("sub/f6.txt", ms);
            scopedFileSystems = true;                   // pretend we have a scope

            Assert.IsTrue(fs.FileExists("sub/f6.txt")); // other thread has written out to fs
            scope.Complete();
            scope.Dispose();
            scopedFileSystems = false;
            Assert.IsTrue(fs.FileExists("sub/f5.txt"));
            Assert.IsFalse(Directory.Exists(appdata + "/TEMP/ShadowFs/" + id));
        }
예제 #25
0
    public void ShadowScopeCompleteWithDirectoryConflict()
    {
        var path     = HostingEnvironment.MapPathContentRoot("FileSysTests");
        var shadowfs =
            HostingEnvironment.MapPathContentRoot(Constants.SystemDirectories.TempData.EnsureEndsWith('/') +
                                                  "ShadowFs");

        Directory.CreateDirectory(path);

        var scopedFileSystems = false;

        var phy = new PhysicalFileSystem(IOHelper, HostingEnvironment, Logger, path, "ignore");

        var globalSettings = Options.Create(new GlobalSettings());
        var fileSystems    =
            new FileSystems(NullLoggerFactory.Instance, IOHelper, globalSettings, HostingEnvironment)
        {
            IsScoped = () => scopedFileSystems
        };
        var shadowPath = $"x/{Guid.NewGuid().ToString("N").Substring(0, 6)}";
        var sw         = fileSystems.CreateShadowWrapper(phy, shadowPath);

        using (var ms = new MemoryStream(Encoding.UTF8.GetBytes("foo")))
        {
            sw.AddFile("sub/f1.txt", ms);
        }

        Assert.IsTrue(phy.FileExists("sub/f1.txt"));

        string id;

        scopedFileSystems = true; // pretend we have a scope
        var scope = new ShadowFileSystems(fileSystems, id = ShadowWrapper.CreateShadowId(HostingEnvironment));

        Assert.IsTrue(Directory.Exists(shadowfs + "/" + id));
        using (var ms = new MemoryStream(Encoding.UTF8.GetBytes("foo")))
        {
            sw.AddFile("sub/f2.txt", ms);
        }

        Assert.IsFalse(phy.FileExists("sub/f2.txt"));

        // pretend we're another thread w/out scope
        scopedFileSystems = false;
        using (var ms = new MemoryStream(Encoding.UTF8.GetBytes("bar")))
        {
            sw.AddFile("sub/f2.txt/f2.txt", ms);
        }

        scopedFileSystems = true;                           // pretend we have a scope

        Assert.IsTrue(phy.FileExists("sub/f2.txt/f2.txt")); // other thread has written out to fs

        using (var ms = new MemoryStream(Encoding.UTF8.GetBytes("foo")))
        {
            sw.AddFile("sub/f3.txt", ms);
        }

        Assert.IsFalse(phy.FileExists("sub/f3.txt"));

        scope.Complete();

        try
        {
            // no way this can work since we're trying to write a file
            // but there's now a directory with the same name on the real fs
            scope.Dispose();
            Assert.Fail("Expected AggregateException.");
        }
        catch (AggregateException ae)
        {
            Assert.AreEqual(1, ae.InnerExceptions.Count);
            var e = ae.InnerExceptions[0];
            Assert.IsNotNull(e.InnerException);
            Assert.IsInstanceOf <AggregateException>(e);
            ae = (AggregateException)e;

            Assert.AreEqual(1, ae.InnerExceptions.Count);
            e = ae.InnerExceptions[0];
            Assert.IsNotNull(e.InnerException);
            Assert.IsInstanceOf <Exception>(e.InnerException);
        }

        // still, the rest of the changes has been applied ok
        Assert.IsTrue(phy.FileExists("sub/f3.txt"));
    }
예제 #26
0
        public void Execute()
        {
            if (Help)
            {
                HelpCommand.ViewHelpForCommand(CommandAttribute.CommandName);
            }
            else
            {
                Stopwatch watch = new Stopwatch();
                watch.Start();
                if (String.IsNullOrEmpty(ConfigFile))
                {
                    Settings = NuGet.Settings.LoadDefaultSettings(
                        FileSystem, 
                        configFileName: null, 
                        machineWideSettings: MachineWideSettings);
                }
                else
                {                    
                    var directory = Path.GetDirectoryName(Path.GetFullPath(ConfigFile));
                    var configFileName = Path.GetFileName(ConfigFile);
                    var configFileSystem = new PhysicalFileSystem(directory);

                    // Create the config file when neccessary
                    if (!configFileSystem.FileExists(configFileName) &&
                        ShouldCreateConfigFile)
                    {
                        XmlUtility.CreateDocument("configuration", configFileSystem, configFileName);
                    }

                    Settings = NuGet.Settings.LoadDefaultSettings(
                        configFileSystem,
                        configFileName,
                        MachineWideSettings);
                }

                SourceProvider = PackageSourceBuilder.CreateSourceProvider(Settings);

                // Register an additional provider for the console specific application so that the user
                // will be prompted if a proxy is set and credentials are required
                var credentialProvider = new SettingsCredentialProvider(
                    new ConsoleCredentialProvider(Console),
                    SourceProvider, 
                    Console);
                HttpClient.DefaultCredentialProvider = credentialProvider;

                ExecuteCommand();
                watch.Stop();
                DisplayExecutedTime(watch.Elapsed, CommandAttribute.CommandName);
            }
        }
예제 #27
0
        private static bool TryCopyNativeLibToAppDirectory(ITracer tracer, PhysicalFileSystem fileSystem, string gvfsAppDirectory)
        {
            string installFilePath;
            string appFilePath;

            GetNativeLibPaths(gvfsAppDirectory, out installFilePath, out appFilePath);

            EventMetadata pathMetadata = CreateEventMetadata();

            pathMetadata.Add(nameof(gvfsAppDirectory), gvfsAppDirectory);
            pathMetadata.Add(nameof(installFilePath), installFilePath);
            pathMetadata.Add(nameof(appFilePath), appFilePath);

            if (fileSystem.FileExists(installFilePath))
            {
                tracer.RelatedEvent(EventLevel.Informational, $"{nameof(TryCopyNativeLibToAppDirectory)}_CopyingNativeLib", pathMetadata);

                try
                {
                    fileSystem.CopyFile(installFilePath, appFilePath, overwrite: true);

                    try
                    {
                        Common.NativeMethods.FlushFileBuffers(appFilePath);
                    }
                    catch (Win32Exception e)
                    {
                        EventMetadata metadata = CreateEventMetadata(e);
                        metadata.Add(nameof(appFilePath), appFilePath);
                        metadata.Add(nameof(installFilePath), installFilePath);
                        tracer.RelatedWarning(metadata, $"{nameof(TryCopyNativeLibToAppDirectory)}: Win32Exception while trying to flush file buffers", Keywords.Telemetry);
                    }
                }
                catch (UnauthorizedAccessException e)
                {
                    EventMetadata metadata = CreateEventMetadata(e);
                    tracer.RelatedError(metadata, $"{nameof(TryCopyNativeLibToAppDirectory)}: UnauthorizedAccessException caught while trying to copy native lib");
                    return(false);
                }
                catch (DirectoryNotFoundException e)
                {
                    EventMetadata metadata = CreateEventMetadata(e);
                    tracer.RelatedError(metadata, $"{nameof(TryCopyNativeLibToAppDirectory)}: DirectoryNotFoundException caught while trying to copy native lib");
                    return(false);
                }
                catch (FileNotFoundException e)
                {
                    EventMetadata metadata = CreateEventMetadata(e);
                    tracer.RelatedError(metadata, $"{nameof(TryCopyNativeLibToAppDirectory)}: FileNotFoundException caught while trying to copy native lib");
                    return(false);
                }
                catch (IOException e)
                {
                    EventMetadata metadata = CreateEventMetadata(e);
                    tracer.RelatedWarning(metadata, $"{nameof(TryCopyNativeLibToAppDirectory)}: IOException caught while trying to copy native lib");

                    if (fileSystem.FileExists(appFilePath))
                    {
                        tracer.RelatedWarning(
                            CreateEventMetadata(),
                            "Could not copy native lib to app directory, but file already exists, continuing with install",
                            Keywords.Telemetry);
                    }
                    else
                    {
                        tracer.RelatedError($"{nameof(TryCopyNativeLibToAppDirectory)}: Failed to copy native lib to app directory");
                        return(false);
                    }
                }
            }
            else
            {
                tracer.RelatedError(pathMetadata, $"{nameof(TryCopyNativeLibToAppDirectory)}: Native lib does not exist in install directory");
                return(false);
            }

            return(true);
        }
예제 #28
0
파일: Command.cs 프로젝트: rikoe/nuget
        public void Execute()
        {
            if (Help)
            {
                HelpCommand.ViewHelpForCommand(CommandAttribute.CommandName);
            }
            else
            {
                if (String.IsNullOrEmpty(ConfigFile))
                {
                    Settings = NuGet.Settings.LoadDefaultSettings(
                        FileSystem, 
                        configFileName: null, 
                        machineWideSettings: MachineWideSettings);
                }
                else
                {                    
                    var directory = Path.GetDirectoryName(Path.GetFullPath(ConfigFile));
                    var configFileName = Path.GetFileName(ConfigFile);
                    var configFileSystem = new PhysicalFileSystem(directory);

                    // Create the config file when neccessary
                    if (!configFileSystem.FileExists(configFileName) &&
                        ShouldCreateConfigFile)
                    {
                        XmlUtility.CreateDocument("configuration", configFileSystem, configFileName);
                    }

                    Settings = NuGet.Settings.LoadDefaultSettings(
                        configFileSystem,
                        configFileName,
                        MachineWideSettings);
                }

                SourceProvider = PackageSourceBuilder.CreateSourceProvider(Settings);

                // Register an additional provider for the console specific application so that the user
                // will be prompted if a proxy is set and credentials are required
                var credentialProvider = new SettingsCredentialProvider(
                    new ConsoleCredentialProvider(Console),
                    SourceProvider, 
                    Console);
                HttpClient.DefaultCredentialProvider = credentialProvider;
                RepositoryFactory = new NuGet.Common.CommandLineRepositoryFactory(Console);

                // enable the V3 shim
                if (ShimControllerProvider != null)
                {
                    ShimControllerProvider.Controller.Enable(SourceProvider);
                }

                ExecuteCommand();
            }
        }
예제 #29
0
        private bool TryGetMaxGoodPrefetchTimestamp(
            ITracer tracer,
            GVFSEnlistment enlistment,
            PhysicalFileSystem fileSystem,
            GitObjects gitObjects,
            out long maxGoodTimestamp,
            out string error)
        {
            gitObjects.DeleteStaleTempPrefetchPackAndIdxs();

            string[] packs = gitObjects.ReadPackFileNames(enlistment.GitPackRoot, GVFSConstants.PrefetchPackPrefix);
            List <PrefetchPackInfo> orderedPacks = packs
                                                   .Where(pack => this.GetTimestamp(pack).HasValue)
                                                   .Select(pack => new PrefetchPackInfo(this.GetTimestamp(pack).Value, pack))
                                                   .OrderBy(packInfo => packInfo.Timestamp)
                                                   .ToList();

            maxGoodTimestamp = -1;

            int firstBadPack = -1;

            for (int i = 0; i < orderedPacks.Count; ++i)
            {
                long   timestamp = orderedPacks[i].Timestamp;
                string packPath  = orderedPacks[i].Path;
                string idxPath   = Path.ChangeExtension(packPath, ".idx");
                if (!fileSystem.FileExists(idxPath))
                {
                    EventMetadata metadata = new EventMetadata();
                    metadata.Add("pack", packPath);
                    metadata.Add("idxPath", idxPath);
                    metadata.Add("timestamp", timestamp);
                    GitProcess.Result indexResult = gitObjects.IndexPackFile(packPath);
                    if (indexResult.HasErrors)
                    {
                        firstBadPack = i;

                        metadata.Add("Errors", indexResult.Errors);
                        tracer.RelatedWarning(metadata, $"{nameof(this.TryPrefetchCommitsAndTrees)}: Found pack file that's missing idx file, and failed to regenerate idx");
                        break;
                    }
                    else
                    {
                        maxGoodTimestamp = timestamp;

                        metadata.Add(TracingConstants.MessageKey.InfoMessage, $"{nameof(this.TryPrefetchCommitsAndTrees)}: Found pack file that's missing idx file, and regenerated idx");
                        tracer.RelatedEvent(EventLevel.Informational, $"{nameof(this.TryPrefetchCommitsAndTrees)}_RebuildIdx", metadata);
                    }
                }
                else
                {
                    maxGoodTimestamp = timestamp;
                }
            }

            if (firstBadPack != -1)
            {
                const int MaxDeleteRetries      = 200; // 200 * IoFailureRetryDelayMS (50ms) = 10 seconds
                const int RetryLoggingThreshold = 40;  // 40 * IoFailureRetryDelayMS (50ms) = 2 seconds

                // Delete packs and indexes in reverse order so that if prefetch is killed, subseqeuent prefetch commands will
                // find the right starting spot.
                for (int i = orderedPacks.Count - 1; i >= firstBadPack; --i)
                {
                    string packPath = orderedPacks[i].Path;
                    string idxPath  = Path.ChangeExtension(packPath, ".idx");

                    EventMetadata metadata = new EventMetadata();
                    metadata.Add("path", idxPath);
                    metadata.Add(TracingConstants.MessageKey.InfoMessage, $"{nameof(this.TryPrefetchCommitsAndTrees)} deleting bad idx file");
                    tracer.RelatedEvent(EventLevel.Informational, $"{nameof(this.TryPrefetchCommitsAndTrees)}_DeleteBadIdx", metadata);
                    if (!fileSystem.TryWaitForDelete(tracer, idxPath, IoFailureRetryDelayMS, MaxDeleteRetries, RetryLoggingThreshold))
                    {
                        error = $"Unable to delete {idxPath}";
                        return(false);
                    }

                    metadata = new EventMetadata();
                    metadata.Add("path", packPath);
                    metadata.Add(TracingConstants.MessageKey.InfoMessage, $"{nameof(this.TryPrefetchCommitsAndTrees)} deleting bad pack file");
                    tracer.RelatedEvent(EventLevel.Informational, $"{nameof(this.TryPrefetchCommitsAndTrees)}_DeleteBadPack", metadata);
                    if (!fileSystem.TryWaitForDelete(tracer, packPath, IoFailureRetryDelayMS, MaxDeleteRetries, RetryLoggingThreshold))
                    {
                        error = $"Unable to delete {packPath}";
                        return(false);
                    }
                }
            }

            error = null;
            return(true);
        }
예제 #30
0
        public static bool TryCopyNativeLibIfDriverVersionsMatch(ITracer tracer, PhysicalFileSystem fileSystem, out string copyNativeDllError)
        {
            string system32NativeLibraryPath = Path.Combine(Environment.SystemDirectory, ProjFSNativeLibFileName);

            if (fileSystem.FileExists(system32NativeLibraryPath))
            {
                copyNativeDllError = $"{ProjFSNativeLibFileName} already exists at {system32NativeLibraryPath}";
                return(false);
            }

            string gvfsProcessLocation = ProcessHelper.GetCurrentProcessLocation();
            string nonInboxNativeLibInstallPath;
            string packagedNativeLibPath;

            GetNativeLibPaths(gvfsProcessLocation, out packagedNativeLibPath, out nonInboxNativeLibInstallPath);
            if (fileSystem.FileExists(nonInboxNativeLibInstallPath))
            {
                copyNativeDllError = $"{ProjFSNativeLibFileName} already exists at {nonInboxNativeLibInstallPath}";
                return(false);
            }

            if (!fileSystem.FileExists(packagedNativeLibPath))
            {
                copyNativeDllError = $"{packagedNativeLibPath} not found, no {ProjFSNativeLibFileName} available to copy";
                return(false);
            }

            string packagedPrjfltDriverPath = Path.Combine(gvfsProcessLocation, "Filter", DriverFileName);

            if (!fileSystem.FileExists(packagedPrjfltDriverPath))
            {
                copyNativeDllError = $"{packagedPrjfltDriverPath} not found, unable to validate that packaged driver matches installed driver";
                return(false);
            }

            string system32PrjfltDriverPath = Path.Combine(Environment.ExpandEnvironmentVariables(System32DriversRoot), DriverFileName);

            if (!fileSystem.FileExists(system32PrjfltDriverPath))
            {
                copyNativeDllError = $"{system32PrjfltDriverPath} not found, unable to validate that packaged driver matches installed driver";
                return(false);
            }

            FileVersionInfo packagedDriverVersion;
            FileVersionInfo system32DriverVersion;

            try
            {
                packagedDriverVersion = fileSystem.GetVersionInfo(packagedPrjfltDriverPath);
                system32DriverVersion = fileSystem.GetVersionInfo(system32PrjfltDriverPath);
                if (!fileSystem.FileVersionsMatch(packagedDriverVersion, system32DriverVersion))
                {
                    copyNativeDllError = $"Packaged sys FileVersion '{packagedDriverVersion.FileVersion}' does not match System32 sys FileVersion '{system32DriverVersion.FileVersion}'";
                    return(false);
                }

                if (!fileSystem.ProductVersionsMatch(packagedDriverVersion, system32DriverVersion))
                {
                    copyNativeDllError = $"Packaged sys ProductVersion '{packagedDriverVersion.ProductVersion}' does not match System32 sys ProductVersion '{system32DriverVersion.ProductVersion}'";
                    return(false);
                }
            }
            catch (FileNotFoundException e)
            {
                EventMetadata metadata = CreateEventMetadata(e);
                tracer.RelatedWarning(
                    metadata,
                    $"{nameof(TryCopyNativeLibIfDriverVersionsMatch)}: Exception caught while comparing sys versions");
                copyNativeDllError = $"Exception caught while comparing sys versions: {e.Message}";
                return(false);
            }

            EventMetadata driverVersionMetadata = CreateEventMetadata();

            driverVersionMetadata.Add($"{nameof(packagedDriverVersion)}.FileVersion", packagedDriverVersion.FileVersion.ToString());
            driverVersionMetadata.Add($"{nameof(system32DriverVersion)}.FileVersion", system32DriverVersion.FileVersion.ToString());
            driverVersionMetadata.Add($"{nameof(packagedDriverVersion)}.ProductVersion", packagedDriverVersion.ProductVersion.ToString());
            driverVersionMetadata.Add($"{nameof(system32DriverVersion)}.ProductVersion", system32DriverVersion.ProductVersion.ToString());
            tracer.RelatedInfo(driverVersionMetadata, $"{nameof(TryCopyNativeLibIfDriverVersionsMatch)}: Copying native library");

            if (!TryCopyNativeLibToNonInboxInstallLocation(tracer, fileSystem, gvfsProcessLocation))
            {
                copyNativeDllError = "Failed to copy native library";
                return(false);
            }

            copyNativeDllError = null;
            return(true);
        }