private Manifest GenerateManifest(string path, string?subdir) { if (Directory.Exists(path)) { if (!string.IsNullOrEmpty(subdir)) { throw new OptionException(Resources.TooManyArguments + Environment.NewLine + subdir.EscapeArgument(), null); } var generator = new ManifestGenerator(path, _algorithm); Handler.RunTask(generator); return(generator.Manifest); } else if (File.Exists(path)) { using var tempDir = new TemporaryDirectory("0install"); using (var extractor = ArchiveExtractor.Create(path, tempDir, Archive.GuessMimeType(path))) { extractor.Extract = subdir; Handler.RunTask(extractor); } var generator = new ManifestGenerator(tempDir, _algorithm); Handler.RunTask(generator); return(generator.Manifest); } else { throw new FileNotFoundException(string.Format(Resources.FileOrDirNotFound, path)); } }
/// <inheritdoc/> public string AddArchives(IEnumerable <ArchiveFileInfo> archiveInfos, ManifestDigest manifestDigest, ITaskHandler handler) { #region Sanity checks if (archiveInfos == null) { throw new ArgumentNullException(nameof(archiveInfos)); } if (handler == null) { throw new ArgumentNullException(nameof(handler)); } if (manifestDigest.Best == null) { throw new ArgumentException("No known digest method", nameof(manifestDigest)); } #endregion if (Contains(manifestDigest)) { throw new ImplementationAlreadyInStoreException(manifestDigest); } Log.Info("Caching implementation: " + manifestDigest.Best); // Extract to temporary directory inside the cache so it can be validated safely (no manipulation of directory while validating) string tempDir = GetTempDir(); try { // Extract archives "over each other" in order foreach (var archiveInfo in archiveInfos) { try { using (var extractor = ArchiveExtractor.Create(archiveInfo.Path, tempDir, archiveInfo.MimeType, archiveInfo.StartOffset)) { extractor.SubDir = archiveInfo.SubDir; extractor.Destination = archiveInfo.Destination; extractor.Tag = manifestDigest; handler.RunTask(extractor); } } #region Error handling catch (IOException ex) { string source = archiveInfo.OriginalSource?.ToStringRfc() ?? archiveInfo.Path; throw new IOException(string.Format(Resources.FailedToExtractArchive, source), ex); } #endregion } return(VerifyAndAdd(Path.GetFileName(tempDir), manifestDigest, handler)); } finally { DeleteTempDir(tempDir); } }
/// <summary> /// Applies a <see cref="Archive"/> to a <see cref="TemporaryDirectory"/>. /// </summary> /// <param name="step">The <see cref="Archive"/> to apply.</param> /// <param name="localPath">The local path of the archive.</param> /// <param name="workingDir">The <see cref="TemporaryDirectory"/> to apply the changes to.</param> /// <param name="handler">A callback object used when the the user needs to be informed about progress.</param> /// <param name="tag">The <see cref="ITaskHandler"/> tag used by <paramref name="handler"/>; can be <c>null</c>.</param> /// <exception cref="IOException">A path specified in <paramref name="step"/> is illegal.</exception> public static void Apply([NotNull] this Archive step, [NotNull] string localPath, [NotNull] TemporaryDirectory workingDir, [NotNull] ITaskHandler handler, [CanBeNull] object tag = null) { #region Sanity checks if (step == null) { throw new ArgumentNullException(nameof(step)); } if (string.IsNullOrEmpty(localPath)) { throw new ArgumentNullException(nameof(localPath)); } if (workingDir == null) { throw new ArgumentNullException(nameof(workingDir)); } if (handler == null) { throw new ArgumentNullException(nameof(handler)); } #endregion #region Path validation if (!string.IsNullOrEmpty(step.Destination)) { string destination = FileUtils.UnifySlashes(step.Destination); if (FileUtils.IsBreakoutPath(destination)) { throw new IOException(string.Format(Resources.RecipeInvalidPath, destination)); } } #endregion if (string.IsNullOrEmpty(step.MimeType)) { throw new IOException(Resources.UnknownArchiveType); } using (var extractor = ArchiveExtractor.Create(localPath, workingDir, step.MimeType)) { extractor.SubDir = step.Extract; extractor.Destination = FileUtils.UnifySlashes(step.Destination); extractor.Tag = tag; handler.RunTask(extractor); } }
/// <summary> /// Applies a <see cref="Archive"/> to a <see cref="TemporaryDirectory"/>. /// </summary> /// <param name="step">The <see cref="Archive"/> to apply.</param> /// <param name="localPath">The local path of the archive.</param> /// <param name="workingDir">The <see cref="TemporaryDirectory"/> to apply the changes to.</param> /// <param name="handler">A callback object used when the the user needs to be informed about progress.</param> /// <param name="tag">A tag used to associate composite task with a specific operation; can be null.</param> /// <exception cref="IOException">A path specified in <paramref name="step"/> is illegal.</exception> /// <exception cref="ArgumentException"><see cref="Archive.Normalize"/> was not called for <paramref name="step"/>.</exception> public static void Apply(this Archive step, string localPath, TemporaryDirectory workingDir, ITaskHandler handler, object?tag = null) { #region Sanity checks if (step == null) { throw new ArgumentNullException(nameof(step)); } if (string.IsNullOrEmpty(localPath)) { throw new ArgumentNullException(nameof(localPath)); } if (workingDir == null) { throw new ArgumentNullException(nameof(workingDir)); } if (handler == null) { throw new ArgumentNullException(nameof(handler)); } #endregion if (!string.IsNullOrEmpty(step.Destination)) { string destination = FileUtils.UnifySlashes(step.Destination); if (FileUtils.IsBreakoutPath(destination)) { throw new IOException(string.Format(Resources.RecipeInvalidPath, destination)); } } using var extractor = ArchiveExtractor.Create( localPath, workingDir, step.MimeType ?? throw new ArgumentException($"{nameof(step.Normalize)} was not called.", nameof(step)), step.StartOffset); extractor.Extract = step.Extract; extractor.TargetSuffix = FileUtils.UnifySlashes(step.Destination); extractor.Tag = tag; handler.RunTask(extractor); }