/// <inheritdoc />
                /// <remarks>This is the really tricky clever part. It's built around the assumption that we can, at this point of
                /// the disposal, still seek back to the beginning of the stream and commit the update that was started in the
                /// constructor. It also assumes that other updates are going to be OK with being committed (if there are any).</remarks>
                protected override void Dispose(bool disposing)
                {
                    if (Interlocked.Increment(ref _disposed) == 1)
                    {
                        var recurse             = false;
                        var copyToTemporaryFile = true;
                        var isRooted            = Path.IsPathRooted(_tarArchiveEntry.TarEntry.File);
                        if (isRooted)
                        {
                            recurse             = Directory.Exists(_tarArchiveEntry.TarEntry.File);
                            copyToTemporaryFile = !recurse && !File.Exists(_tarArchiveEntry.TarEntry.File);
                        }
                        if (copyToTemporaryFile)
                        {
                            // operating on something that thus far is in-memory only
                            using (var temporaryDirectory = new TemporaryDirectory())
                            {
                                var subdirectory = Path.GetDirectoryName(_tarArchiveEntry.Name);
                                if (!string.IsNullOrEmpty(subdirectory))
                                {
                                    Directory.CreateDirectory(Path.Combine(temporaryDirectory.Path, subdirectory));
                                }
                                var entryFilePath = Path.Combine(temporaryDirectory.Path, _tarArchiveEntry.Name);

                                Seek(0, SeekOrigin.Begin);
                                using (var fileStream = new FileStream(entryFilePath, FileMode.Create, FileAccess.Write))
                                {
                                    CopyTo(fileStream);
                                }
                                var tarEntry = TarEntry.CreateEntryFromFile(entryFilePath);
                                tarEntry.Name = _tarArchiveEntry.Name;
                                recurse       = IsDirectoryName(tarEntry.Name);
                                _tarAccess.TarArchive.WriteEntry(tarEntry, recurse);
                                _tarArchiveEntry.TarEntry = tarEntry;
                            }
                        }
                        else
                        {
                            // already operating on an existing on-disk entity
                            var tarEntry   = _tarArchiveEntry.TarEntry;
                            var tarArchive = _tarAccess.TarArchive;
                            var rootPath   = tarArchive.RootPath;
                            if (recurse)
                            {
                                if (!string.IsNullOrEmpty(_tarAccess.RootLocation))
                                {
                                    tarArchive.RootPath = Path.GetDirectoryName(_tarAccess.RootLocation);
                                }
                            }
                            try
                            {
                                tarArchive.WriteEntry(tarEntry, recurse);
                            }
                            finally
                            {
                                if (recurse)
                                {
                                    tarArchive.RootPath = rootPath;
                                }
                            }
                        }
                        base.Dispose(disposing);
                    }
                }
Beispiel #2
0
 private NestedCompressedArchiveAccess(ICompressedArchiveAccess parentArchiveAccess, ICompressedArchiveAccess nestedArchiveAccess, TemporaryDirectory temporaryLocation)
 {
     ParentArchiveAccess = parentArchiveAccess;
     NestedAchiveAccess  = nestedArchiveAccess;
     TemporaryLocation   = temporaryLocation;
 }