Beispiel #1
0
        /// <summary>
        /// Creates manifest nodes for a set of file system elements.
        /// </summary>
        /// <param name="entries">The file system elements to create nodes for.</param>
        /// <returns>The nodes for the elements.</returns>
        private IEnumerable <ManifestNode> GetNodes(IEnumerable <FileSystemInfo> entries)
        {
            var externalXbits    = FlagUtils.GetFiles(FlagUtils.XbitFile, TargetDir);
            var externalSymlinks = FlagUtils.GetFiles(FlagUtils.SymlinkFile, TargetDir);

            // Iterate through the directory listing to build a list of manifets entries
            var nodes = new List <ManifestNode>();

            foreach (var entry in entries)
            {
                CancellationToken.ThrowIfCancellationRequested();

                var file = entry as FileInfo;
                if (file != null)
                {
                    // Don't include manifest management files in manifest
                    if (file.Name == Manifest.ManifestFile || file.Name == FlagUtils.XbitFile || file.Name == FlagUtils.SymlinkFile)
                    {
                        continue;
                    }

                    nodes.Add(GetFileNode(file, Format, externalXbits, externalSymlinks));
                    UnitsProcessed += file.Length;
                }
                else
                {
                    var directory = entry as DirectoryInfo;
                    if (directory != null)
                    {
                        nodes.Add(GetDirectoryNode(directory, Format, Path.GetFullPath(TargetDir)));
                    }
                }
            }
            return(nodes);
        }
Beispiel #2
0
        public void TestApplyRecipeSingleFile()
        {
            using (var singleFile = new TemporaryFile("0install-unit-tests"))
                using (var archiveFile = new TemporaryFile("0install-unit-tests"))
                {
                    File.WriteAllText(singleFile, "data");
                    typeof(ArchiveExtractorTest).CopyEmbeddedToFile("testArchive.zip", archiveFile);

                    var downloadedFiles = new[] { archiveFile, singleFile };
                    var recipe          = new Recipe {
                        Steps = { new Archive {
                                      MimeType = Archive.MimeTypeZip
                                  }, new SingleFile{
                                      Destination = "subdir2/executable"
                                  } }
                    };

                    using (TemporaryDirectory recipeDir = recipe.Apply(downloadedFiles, new SilentTaskHandler()))
                    {
                        // /subdir2/executable [!X]
                        string path = Path.Combine(recipeDir, "subdir2", "executable");
                        File.Exists(path).Should().BeTrue(because: "File should exist: " + path);
                        File.ReadAllText(path).Should().Be("data");
                        File.GetLastWriteTimeUtc(path).ToUnixTime()
                        .Should().Be(0, because: "Single files should be set to Unix epoch");
                        if (!UnixUtils.IsUnix)
                        {
                            FlagUtils.GetFiles(FlagUtils.XbitFile, recipeDir).Should().BeEmpty();
                        }
                    }
                }
        }
        public void TestApplyRecipeArchiv()
        {
            using (var archiveFile = new TemporaryFile("0install-unit-tests"))
            {
                typeof(ExtractorTest).WriteEmbeddedFile("testArchive.zip", archiveFile);

                var downloadedFiles = new[] { archiveFile };
                var recipe          = new Recipe {
                    Steps = { new Archive {
                                  MimeType = Archive.MimeTypeZip, Destination = "subDir"
                              } }
                };

                using (TemporaryDirectory recipeDir = recipe.Apply(downloadedFiles, new SilentTaskHandler()))
                {
                    // /dest/symlink [S]
                    string path = new[] { recipeDir, "subDir", "symlink" }.Aggregate(Path.Combine);
                    Assert.IsTrue(File.Exists(path), "File should exist: " + path);
                    if (!UnixUtils.IsUnix)
                    {
                        CollectionAssert.AreEquivalent(new[] { path }, FlagUtils.GetFiles(FlagUtils.SymlinkFile, recipeDir));
                    }

                    // /dest/subdir2/executable [deleted]
                    path = new[] { recipeDir, "subDir", "subdir2", "executable" }.Aggregate(Path.Combine);
                    Assert.IsTrue(File.Exists(path), "File should exist: " + path);
                    if (!UnixUtils.IsUnix)
                    {
                        CollectionAssert.AreEquivalent(new[] { path }, FlagUtils.GetFiles(FlagUtils.XbitFile, recipeDir));
                    }
                }
            }
        }
Beispiel #4
0
        protected virtual string VerifyAndAdd(string tempID, ManifestDigest expectedDigest, ITaskHandler handler)
        {
            #region Sanity checks
            if (string.IsNullOrEmpty(tempID))
            {
                throw new ArgumentNullException(nameof(tempID));
            }
            if (handler == null)
            {
                throw new ArgumentNullException(nameof(handler));
            }
            #endregion

            // Determine the digest method to use
            string?expectedDigestValue = expectedDigest.Best;
            if (string.IsNullOrEmpty(expectedDigestValue))
            {
                throw new NotSupportedException(Resources.NoKnownDigestMethod);
            }

            // Determine the source and target directories
            string source = Path.Combine(DirectoryPath, tempID);
            string target = Path.Combine(DirectoryPath, expectedDigestValue);

            if (_isUnixFS)
            {
                FlagUtils.ConvertToFS(source);
            }

            // Calculate the actual digest, compare it with the expected one and create a manifest file
            VerifyDirectory(source, expectedDigest, handler).Save(Path.Combine(source, Manifest.ManifestFile));

            lock (_renameLock) // Prevent race-conditions when adding the same digest twice
            {
                if (Directory.Exists(target))
                {
                    throw new ImplementationAlreadyInStoreException(expectedDigest);
                }

                // Move directory to final store destination
                try
                {
                    Directory.Move(source, target);
                }
                catch (IOException ex)
                    // TODO: Make language independent
                    when(ex.Message.Contains("already exists"))
                    {
                        throw new ImplementationAlreadyInStoreException(expectedDigest);
                    }
            }

            // Prevent any further changes to the directory
            if (_useWriteProtection)
            {
                EnableWriteProtection(target);
            }
            return(target);
        }
Beispiel #5
0
        public void TestRename()
        {
            using (var flagFile = new TemporaryFile("0install-unit-tests"))
            {
                File.WriteAllText(flagFile, "/dir/file1\n/dir/file2\n/dir2/file\n");

                FlagUtils.Rename(flagFile, "dir", "new_dir");
                File.ReadAllText(flagFile).Should().Be("/new_dir/file1\n/new_dir/file2\n/dir2/file\n");
            }
        }
Beispiel #6
0
        /// <summary>
        /// Applies a <see cref="RenameStep"/> to a <see cref="TemporaryDirectory"/>.
        /// </summary>
        /// <param name="step">The <see cref="Archive"/> to apply.</param>
        /// <param name="workingDir">The <see cref="TemporaryDirectory"/> to apply the changes to.</param>
        /// <exception cref="IOException">A path specified in <paramref name="step"/> is illegal.</exception>
        public static void Apply([NotNull] this RenameStep step, [NotNull] TemporaryDirectory workingDir)
        {
            #region Sanity checks
            if (step == null)
            {
                throw new ArgumentNullException(nameof(step));
            }
            if (workingDir == null)
            {
                throw new ArgumentNullException(nameof(workingDir));
            }
            #endregion

            #region Path validation
            if (string.IsNullOrEmpty(step.Source))
            {
                throw new IOException(string.Format(Resources.RecipeInvalidPath, "(empty)"));
            }
            if (string.IsNullOrEmpty(step.Destination))
            {
                throw new IOException(string.Format(Resources.RecipeInvalidPath, "(empty)"));
            }
            string source      = FileUtils.UnifySlashes(step.Source);
            string destination = FileUtils.UnifySlashes(step.Destination);
            if (FileUtils.IsBreakoutPath(source))
            {
                throw new IOException(string.Format(Resources.RecipeInvalidPath, source));
            }
            if (FileUtils.IsBreakoutPath(destination))
            {
                throw new IOException(string.Format(Resources.RecipeInvalidPath, destination));
            }
            #endregion

            string sourcePath      = Path.Combine(workingDir, source);
            string destinationPath = Path.Combine(workingDir, destination);
            string parentDir       = Path.GetDirectoryName(destinationPath);
            if (!string.IsNullOrEmpty(parentDir) && !Directory.Exists(parentDir))
            {
                Directory.CreateDirectory(parentDir);
            }

            if (Directory.Exists(sourcePath))
            {
                Directory.Move(sourcePath, destinationPath);
            }
            else
            {
                File.Move(sourcePath, destinationPath);
            }

            // Update in flag files as well
            FlagUtils.Rename(Path.Combine(workingDir, FlagUtils.XbitFile), source, destination);
            FlagUtils.Rename(Path.Combine(workingDir, FlagUtils.SymlinkFile), source, destination);
        }
Beispiel #7
0
        public void TestSet()
        {
            using (var flagFile = new TemporaryFile("0install-unit-tests"))
            {
                FlagUtils.Set(flagFile, Path.Combine("dir1", "file1"));
                File.ReadAllText(flagFile).Should().Be("/dir1/file1\n");

                FlagUtils.Set(flagFile, Path.Combine("dir2", "file2"));
                File.ReadAllText(flagFile).Should().Be("/dir1/file1\n/dir2/file2\n");
            }
        }
Beispiel #8
0
        /// <summary>
        /// Creates a new directory walking task.
        /// </summary>
        /// <param name="sourceDirectory">The path of the directory to walk.</param>
        protected DirectoryWalkTask([NotNull] string sourceDirectory)
        {
            #region Sanity checks
            if (string.IsNullOrEmpty(sourceDirectory))
            {
                throw new ArgumentNullException(nameof(sourceDirectory));
            }
            #endregion

            SourceDirectory = new DirectoryInfo(Path.GetFullPath(sourceDirectory));
            _isUnixFS       = FlagUtils.IsUnixFS(sourceDirectory);
        }
 protected override void CreateSymlink(string linkPath, string linkTarget)
 {
     if (_destinationIsUnixFS)
     {
         base.CreateSymlink(linkPath, linkTarget);
     }
     else
     {
         File.WriteAllText(linkPath, linkTarget, Encoding.UTF8);
         FlagUtils.Set(Path.Combine(DestinationPath, FlagUtils.SymlinkFile), new FileInfo(linkPath).RelativeTo(new DirectoryInfo(DestinationPath)));
     }
 }
Beispiel #10
0
        public void TestGetFiles()
        {
            using (var flagDir = new TemporaryDirectory("0install-unit-tests"))
            {
                File.WriteAllText(Path.Combine(flagDir, FlagUtils.XbitFile), "/dir1/file1\n/dir2/file2\n");

                var expectedResult = new[]
                {
                    new[] { flagDir, "dir1", "file1" }.Aggregate(Path.Combine),
                    new[] { flagDir, "dir2", "file2" }.Aggregate(Path.Combine)
                };

                CollectionAssert.AreEquivalent(expectedResult, FlagUtils.GetFiles(FlagUtils.XbitFile, flagDir), "Should find .xbit file in same directory");
                CollectionAssert.AreEquivalent(expectedResult, FlagUtils.GetFiles(FlagUtils.XbitFile, Path.Combine(flagDir, "subdir")), "Should find .xbit file in parent directory");
            }
        }
Beispiel #11
0
        public void TestRemove()
        {
            using (var flagFile = new TemporaryFile("0install-unit-tests"))
            {
                File.WriteAllText(flagFile, "/dir1/file1\n/dir2/file2\n");

                FlagUtils.Remove(flagFile, "dir");
                File.ReadAllText(flagFile).Should().Be("/dir1/file1\n/dir2/file2\n", because: "Partial match should not change anything");

                FlagUtils.Remove(flagFile, Path.Combine("dir1", "file1"));
                File.ReadAllText(flagFile).Should().Be("/dir2/file2\n");

                FlagUtils.Remove(flagFile, "dir2");
                File.ReadAllText(flagFile).Should().Be("");
            }
        }
Beispiel #12
0
        /// <summary>
        /// Creates a new store using a specific path to a cache directory.
        /// </summary>
        /// <param name="path">A fully qualified directory path. The directory will be created if it doesn't exist yet.</param>
        /// <param name="useWriteProtection">Controls whether implementation directories are made write-protected once added to the cache to prevent unintentional modification (which would invalidate the manifest digests).</param>
        /// <exception cref="IOException">The directory <paramref name="path"/> could not be created or if the underlying filesystem can not store file-changed times accurate to the second.</exception>
        /// <exception cref="UnauthorizedAccessException">Creating the directory <paramref name="path"/> is not permitted.</exception>
        public DirectoryStore([NotNull] string path, bool useWriteProtection = true)
        {
            #region Sanity checks
            if (string.IsNullOrEmpty(path))
            {
                throw new ArgumentNullException("path");
            }
            #endregion

            try
            {
                DirectoryPath = Path.GetFullPath(path);
                if (!Directory.Exists(DirectoryPath))
                {
                    Directory.CreateDirectory(DirectoryPath);
                }
            }
            #region Error handling
            catch (ArgumentException ex)
            {
                // Wrap exception since only certain exception types are allowed
                throw new IOException(ex.Message, ex);
            }
            catch (NotSupportedException ex)
            {
                // Wrap exception since only certain exception types are allowed
                throw new IOException(ex.Message, ex);
            }
            #endregion

            Kind = DetermineKind(DirectoryPath);
            _useWriteProtection = useWriteProtection;
            _isUnixFS           = FlagUtils.IsUnixFS(DirectoryPath);

            if (Kind == StoreKind.ReadWrite)
            {
                if (!_isUnixFS)
                {
                    FlagUtils.MarkAsNoUnixFS(DirectoryPath);
                }
                if (_useWriteProtection && WindowsUtils.IsWindowsNT)
                {
                    WriteDeleteInfoFile(DirectoryPath);
                }
            }
        }
Beispiel #13
0
        public void TestIsUnixFS()
        {
            using (var tempDir = new TemporaryDirectory("0install-unit-tests"))
            {
                if (UnixUtils.IsUnix)
                {
                    Assert.IsTrue(FlagUtils.IsUnixFS(tempDir));

                    FlagUtils.MarkAsNoUnixFS(tempDir);
                    Assert.IsFalse(FlagUtils.IsUnixFS(tempDir));
                }
                else
                {
                    Assert.IsFalse(FlagUtils.IsUnixFS(tempDir));
                }
            }
        }
Beispiel #14
0
        public static void Apply([NotNull] this SingleFile step, [NotNull] TemporaryFile downloadedFile, [NotNull] TemporaryDirectory workingDir, [NotNull] ITaskHandler handler, [CanBeNull] object tag = null)
        {
            #region Sanity checks
            if (step == null)
            {
                throw new ArgumentNullException("step");
            }
            if (downloadedFile == null)
            {
                throw new ArgumentNullException("downloadedFile");
            }
            if (workingDir == null)
            {
                throw new ArgumentNullException("workingDir");
            }
            if (handler == null)
            {
                throw new ArgumentNullException("handler");
            }
            #endregion

            #region Path validation
            if (string.IsNullOrEmpty(step.Destination))
            {
                throw new IOException(Resources.FileMissingDest);
            }
            string destination = FileUtils.UnifySlashes(step.Destination);
            if (FileUtils.IsBreakoutPath(destination))
            {
                throw new IOException(string.Format(Resources.RecipeInvalidPath, destination));
            }
            #endregion

            string destinationPath = Path.Combine(workingDir, destination);
            string parentDir       = Path.GetDirectoryName(destinationPath);
            if (!string.IsNullOrEmpty(parentDir) && !Directory.Exists(parentDir))
            {
                Directory.CreateDirectory(parentDir);
            }
            FileUtils.Replace(downloadedFile, destinationPath);
            File.SetLastWriteTimeUtc(destinationPath, FileUtils.FromUnixTime(0));

            // Update in flag files as well
            FlagUtils.Remove(Path.Combine(workingDir, FlagUtils.XbitFile), destination);
            FlagUtils.Remove(Path.Combine(workingDir, FlagUtils.SymlinkFile), destination);
        }
Beispiel #15
0
        public void TestIsUnixFS()
        {
            using (var tempDir = new TemporaryDirectory("0install-unit-tests"))
            {
                if (UnixUtils.IsUnix)
                {
                    FlagUtils.IsUnixFS(tempDir).Should().BeTrue();

                    FlagUtils.MarkAsNoUnixFS(tempDir);
                    FlagUtils.IsUnixFS(tempDir).Should().BeFalse();
                }
                else
                {
                    FlagUtils.IsUnixFS(tempDir).Should().BeFalse();
                }
            }
        }
Beispiel #16
0
        public void TestGetFiles()
        {
            using (var flagDir = new TemporaryDirectory("0install-unit-tests"))
            {
                File.WriteAllText(Path.Combine(flagDir, FlagUtils.XbitFile), "/dir1/file1\n/dir2/file2\n");

                var expectedResult = new[]
                {
                    Path.Combine(flagDir, "dir1", "file1"),
                    Path.Combine(flagDir, "dir2", "file2")
                };

                FlagUtils.GetFiles(FlagUtils.XbitFile, flagDir)
                .Should().BeEquivalentTo(expectedResult, because: "Should find .xbit file in same directory");
                FlagUtils.GetFiles(FlagUtils.XbitFile, Path.Combine(flagDir, "subdir"))
                .Should().BeEquivalentTo(expectedResult, because: "Should find .xbit file in parent directory");
            }
        }
Beispiel #17
0
        /// <summary>
        /// Prepares to generate a manifest for a directory in the filesystem.
        /// </summary>
        /// <param name="path">The path of the directory to analyze.</param>
        /// <param name="format">The format of the manifest to generate.</param>
        public ManifestGenerator([NotNull] string path, [NotNull] ManifestFormat format)
        {
            #region Sanity checks
            if (string.IsNullOrEmpty(path))
            {
                throw new ArgumentNullException("path");
            }
            if (format == null)
            {
                throw new ArgumentNullException("format");
            }
            #endregion

            TargetDir = path.TrimEnd(Path.DirectorySeparatorChar);
            Format    = format;

            _isUnixFS = FlagUtils.IsUnixFS(TargetDir);
        }
Beispiel #18
0
        protected void WriteFile(string name, bool executable = false)
        {
            string path = Path.Combine(_sourceDirectory, name);

            File.WriteAllText(path, Contents);
            File.SetLastWriteTimeUtc(path, Timestamp);

            if (executable)
            {
                if (UnixUtils.IsUnix)
                {
                    FileUtils.SetExecutable(path, true);
                }
                else
                {
                    FlagUtils.Set(Path.Combine(_sourceDirectory, FlagUtils.XbitFile), name);
                }
            }
        }
        protected override void CopyFile(FileInfo sourceFile, FileInfo destinationFile)
        {
            #region Sanity checks
            if (sourceFile == null)
            {
                throw new ArgumentNullException("sourceFile");
            }
            if (destinationFile == null)
            {
                throw new ArgumentNullException("destinationFile");
            }
            #endregion

            base.CopyFile(sourceFile, destinationFile);

            if (_sourceIsUnixFS && !_destinationIsUnixFS && FileUtils.IsExecutable(sourceFile.FullName))
            {
                FlagUtils.Set(Path.Combine(DestinationPath, FlagUtils.XbitFile), destinationFile.RelativeTo(new DirectoryInfo(DestinationPath)));
            }
        }
Beispiel #20
0
        public void TestApplyRecipeRemove()
        {
            using (var archiveFile = new TemporaryFile("0install-unit-tests"))
            {
                typeof(ArchiveExtractorTest).CopyEmbeddedToFile("testArchive.zip", archiveFile);

                var downloadedFiles = new[] { archiveFile };
                var recipe          = new Recipe
                {
                    Steps =
                    {
                        new Archive    {
                            MimeType = Archive.MimeTypeZip
                        },
                        new RemoveStep {
                            Path = "symlink"
                        },
                        new RemoveStep {
                            Path = "subdir2"
                        }
                    }
                };

                using (TemporaryDirectory recipeDir = recipe.Apply(downloadedFiles, new SilentTaskHandler()))
                {
                    if (!UnixUtils.IsUnix)
                    {
                        FlagUtils.GetFiles(FlagUtils.XbitFile, recipeDir).Should().BeEmpty();
                        FlagUtils.GetFiles(FlagUtils.SymlinkFile, recipeDir).Should().BeEmpty();
                    }

                    // /symlink [deleted]
                    string path = Path.Combine(recipeDir, "symlink");
                    File.Exists(path).Should().BeFalse(because: "File should not exist: " + path);

                    // /subdir2 [deleted]
                    path = Path.Combine(recipeDir, "subdir2");
                    Directory.Exists(path).Should().BeFalse(because: "Directory should not exist: " + path);
                }
            }
        }
Beispiel #21
0
        /// <summary>
        /// Applies a <see cref="RemoveStep"/> to a <see cref="TemporaryDirectory"/>.
        /// </summary>
        /// <param name="step">The <see cref="Archive"/> to apply.</param>
        /// <param name="workingDir">The <see cref="TemporaryDirectory"/> to apply the changes to.</param>
        /// <exception cref="IOException">A path specified in <paramref name="step"/> is illegal.</exception>
        public static void Apply([NotNull] this RemoveStep step, [NotNull] TemporaryDirectory workingDir)
        {
            #region Sanity checks
            if (step == null)
            {
                throw new ArgumentNullException(nameof(step));
            }
            if (workingDir == null)
            {
                throw new ArgumentNullException(nameof(workingDir));
            }
            #endregion

            #region Path validation
            if (string.IsNullOrEmpty(step.Path))
            {
                throw new IOException(string.Format(Resources.RecipeInvalidPath, "(empty)"));
            }
            string path = FileUtils.UnifySlashes(step.Path);
            if (FileUtils.IsBreakoutPath(path))
            {
                throw new IOException(string.Format(Resources.RecipeInvalidPath, path));
            }
            #endregion

            string absolutePath = Path.Combine(workingDir, path);
            if (Directory.Exists(absolutePath))
            {
                Directory.Delete(absolutePath, recursive: true);
            }
            else
            {
                File.Delete(absolutePath);
            }

            // Update in flag files as well
            FlagUtils.Remove(Path.Combine(workingDir, FlagUtils.XbitFile), path);
            FlagUtils.Remove(Path.Combine(workingDir, FlagUtils.SymlinkFile), path);
        }
Beispiel #22
0
        public void TestApplyRecipeArchiv()
        {
            using (var archiveFile = new TemporaryFile("0install-unit-tests"))
            {
                typeof(ArchiveExtractorTest).CopyEmbeddedToFile("testArchive.zip", archiveFile);

                var downloadedFiles = new[] { archiveFile };
                var recipe          = new Recipe {
                    Steps = { new Archive {
                                  MimeType = Archive.MimeTypeZip, Destination = "subDir"
                              } }
                };

                using (TemporaryDirectory recipeDir = recipe.Apply(downloadedFiles, new SilentTaskHandler()))
                {
                    // /dest/symlink [S]
                    string path = Path.Combine(recipeDir, "subDir", "symlink");
                    File.Exists(path).Should().BeTrue(because: "File should exist: " + path);
                    if (UnixUtils.IsUnix)
                    {
                        FileUtils.IsSymlink(path).Should().BeTrue();
                    }
                    else
                    {
                        CygwinUtils.IsSymlink(path).Should().BeTrue();
                    }

                    // /dest/subdir2/executable [deleted]
                    path = Path.Combine(recipeDir, "subDir", "subdir2", "executable");
                    File.Exists(path).Should().BeTrue(because: "File should exist: " + path);
                    if (!UnixUtils.IsUnix)
                    {
                        FlagUtils.GetFiles(FlagUtils.XbitFile, recipeDir).Should().BeEquivalentTo(path);
                    }
                }
            }
        }
Beispiel #23
0
        /// <summary>
        /// Iterates over all <paramref name="entries"/> and calls handler methods for them.
        /// </summary>
        /// <exception cref="NotSupportedException">A file has illegal properties (e.g. is a device file, has line breaks in the filename, etc.).</exception>
        /// <exception cref="IOException">There was an error reading a file.</exception>
        /// <exception cref="UnauthorizedAccessException">You have insufficient rights to read a file.</exception>
        protected virtual void HandleEntries([NotNull] IEnumerable <FileSystemInfo> entries)
        {
            #region Sanity checks
            if (entries == null)
            {
                throw new ArgumentNullException(nameof(entries));
            }
            #endregion

            var externalXbits    = FlagUtils.GetFiles(FlagUtils.XbitFile, SourceDirectory.FullName);
            var externalSymlinks = FlagUtils.GetFiles(FlagUtils.SymlinkFile, SourceDirectory.FullName);

            foreach (var entry in entries)
            {
                CancellationToken.ThrowIfCancellationRequested();

                var file = entry as FileInfo;
                if (file != null)
                {
                    if (file.Name == Manifest.ManifestFile || file.Name == FlagUtils.XbitFile || file.Name == FlagUtils.SymlinkFile)
                    {
                        continue;
                    }

                    HandleEntry(file, externalXbits, externalSymlinks);
                    UnitsProcessed += file.Length;
                }
                else
                {
                    var directory = entry as DirectoryInfo;
                    if (directory != null)
                    {
                        HandleEntry(directory);
                    }
                }
            }
        }
 public CopyDirectoryPosix(string sourcePath, string destinationPath, bool preserveDirectoryTimestamps = true, bool overwrite = false)
     : base(sourcePath, destinationPath, preserveDirectoryTimestamps, overwrite)
 {
     _sourceIsUnixFS      = FlagUtils.IsUnixFS(SourcePath);
     _destinationIsUnixFS = FlagUtils.IsUnixFS(DestinationPath);
 }
        public void TestApplyRecipeRename()
        {
            using (var archiveFile = new TemporaryFile("0install-unit-tests"))
            {
                typeof(ExtractorTest).WriteEmbeddedFile("testArchive.zip", archiveFile);

                var downloadedFiles = new[] { archiveFile };
                var recipe          = new Recipe
                {
                    Steps =
                    {
                        new Archive    {
                            MimeType = Archive.MimeTypeZip
                        },
                        new RenameStep {
                            Source = "symlink", Destination = "subdir3/symlink2"
                        },
                        new RenameStep {
                            Source = "subdir2/executable", Destination = "subdir2/executable2"
                        }
                    }
                };

                using (TemporaryDirectory recipeDir = recipe.Apply(downloadedFiles, new SilentTaskHandler()))
                {
                    if (!UnixUtils.IsUnix)
                    {
                        CollectionAssert.AreEquivalent(
                            new[] { new[] { recipeDir, "subdir2", "executable2" }.Aggregate(Path.Combine) },
                            FlagUtils.GetFiles(FlagUtils.XbitFile, recipeDir));
                        CollectionAssert.AreEquivalent(
                            new[] { new[] { recipeDir, "subdir3", "symlink2" }.Aggregate(Path.Combine) },
                            FlagUtils.GetFiles(FlagUtils.SymlinkFile, recipeDir));
                    }

                    // /symlink [deleted]
                    string path = Path.Combine(recipeDir, "symlink");
                    Assert.IsFalse(File.Exists(path), "File should not exist: " + path);

                    // /subdir3/symlink2 [S]
                    path = new[] { recipeDir, "subdir3", "symlink2" }.Aggregate(Path.Combine);
                    Assert.IsTrue(File.Exists(path), "Missing file: " + path);
                    if (UnixUtils.IsUnix)
                    {
                        Assert.IsTrue(FileUtils.IsSymlink(path), "Not symlink: " + path);
                    }

                    // /subdir2/executable [deleted]
                    path = new[] { recipeDir, "subdir2", "executable" }.Aggregate(Path.Combine);
                    Assert.IsFalse(File.Exists(path), "File should not exist: " + path);

                    // /subdir2/executable2 [X]
                    path = new[] { recipeDir, "subdir2", "executable2" }.Aggregate(Path.Combine);
                    Assert.IsTrue(File.Exists(path), "Missing file: " + path);
                    if (UnixUtils.IsUnix)
                    {
                        Assert.IsTrue(FileUtils.IsExecutable(path), "Not executable: " + path);
                    }
                }
            }
        }
Beispiel #26
0
        /// <summary>
        /// Creates a new store using a specific path to a cache directory.
        /// </summary>
        /// <param name="directoryPath">A fully qualified directory path. The directory will be created if it doesn't exist yet.</param>
        /// <param name="useWriteProtection">Controls whether implementation directories are made write-protected once added to the cache to prevent unintentional modification (which would invalidate the manifest digests).</param>
        /// <exception cref="IOException">The <paramref name="directoryPath"/> could not be created or the underlying filesystem can not store file-changed times accurate to the second.</exception>
        /// <exception cref="UnauthorizedAccessException">Creating the <paramref name="directoryPath"/> is not permitted.</exception>
        public DiskImplementationStore(string directoryPath, bool useWriteProtection = true)
        {
            #region Sanity checks
            if (string.IsNullOrEmpty(directoryPath))
            {
                throw new ArgumentNullException(nameof(directoryPath));
            }
            #endregion

            try
            {
                DirectoryPath = Path.GetFullPath(directoryPath);
                if (!Directory.Exists(DirectoryPath))
                {
                    Directory.CreateDirectory(DirectoryPath);
                }
            }
            #region Error handling
            catch (ArgumentException ex)
            {
                // Wrap exception since only certain exception types are allowed
                throw new IOException(ex.Message, ex);
            }
            catch (NotSupportedException ex)
            {
                // Wrap exception since only certain exception types are allowed
                throw new IOException(ex.Message, ex);
            }
            #endregion

            Kind = DetermineKind(DirectoryPath);
            _useWriteProtection = useWriteProtection;
            _isUnixFS           = FlagUtils.IsUnixFS(DirectoryPath);

            if (Kind == ImplementationStoreKind.ReadWrite)
            {
                try
                {
                    if (!_isUnixFS)
                    {
                        FlagUtils.MarkAsNoUnixFS(DirectoryPath);
                    }
                    if (_useWriteProtection && WindowsUtils.IsWindowsNT)
                    {
                        WriteDeleteInfoFile(DirectoryPath);
                    }
                }
                #region Error handling
                catch (IOException ex)
                {
                    // Writing these files is not critical
                    Log.Debug(ex);
                }
                catch (UnauthorizedAccessException ex)
                {
                    // Writing these files is not critical
                    Log.Debug(ex);
                }
                #endregion
            }
        }