Esempio n. 1
0
        /// <summary>
        /// Helper function to download package from given url, and place package (only 'content' folder from package) to given folder
        /// </summary>
        /// <param name="identity">Package identity</param>
        /// <param name="destinationFolder">Folder where we copy the package content (content folder only) to</param>
        /// <param name="pathToLocalCopyOfNupkg">File path where we copy the nudpk to</param>
        /// <returns></returns>
        public static async Task DownloadPackageToFolder(this SourceRepository srcRepo, PackageIdentity identity, string destinationFolder, string pathToLocalCopyOfNupkg)
        {
            var downloadResource = await srcRepo.GetResourceAndValidateAsync <DownloadResource>();

            using (Stream packageStream = await srcRepo.GetPackageStream(identity))
            {
                WriteStreamToFile(packageStream, pathToLocalCopyOfNupkg);
                // set position back to the head of stream
                packageStream.Position = 0;

                using (ZipFile zipFile = ZipFile.Read(packageStream))
                {
                    // we only care about stuff under "content" folder
                    int substringStartIndex = @"content/".Length;
                    IEnumerable <ZipEntry> contentEntries = zipFile.Entries.Where(e => e.FileName.StartsWith(@"content/", StringComparison.InvariantCultureIgnoreCase));
                    foreach (var entry in contentEntries)
                    {
                        string fullPath = Path.Combine(destinationFolder, entry.FileName.Substring(substringStartIndex));
                        FileSystemHelpers.EnsureDirectory(Path.GetDirectoryName(fullPath));
                        using (Stream writeStream = FileSystemHelpers.OpenWrite(fullPath))
                        {
                            // let the thread go with itself, so that once file finsihed writing, doesn`t need to request thread context from main thread
                            await entry.OpenReader().CopyToAsync(writeStream).ConfigureAwait(false);
                        }
                    }
                }
            }
        }
Esempio n. 2
0
        public static async Task UpdateLocalPackage(this SourceRepository srcRepo, SourceRepository localRepo, PackageIdentity identity, string destinationFolder, string pathToLocalCopyOfNupkg, ITracer tracer)
        {
            tracer.Trace("Performing incremental package update for {0}", identity.Id);
            using (Stream newPackageStream = await srcRepo.GetPackageStream(identity))
            {
                // update file
                var localPackage = await localRepo.GetLatestPackageByIdFromSrcRepo(identity.Id);

                if (localPackage == null)
                {
                    throw new FileNotFoundException(string.Format(CultureInfo.InvariantCulture, "Package {0} not found from local repo.", identity.Id));
                }
                using (Stream oldPackageStream = await localRepo.GetPackageStream(localPackage.Identity))
                    using (ZipFile oldPackageZip = ZipFile.Read(oldPackageStream))
                        using (ZipFile newPackageZip = ZipFile.Read(newPackageStream))
                        {
                            // we only care about stuff under "content" folder
                            IEnumerable <ZipEntry>        oldContentEntries = oldPackageZip.Entries.Where(e => e.FileName.StartsWith(@"content/", StringComparison.InvariantCultureIgnoreCase));
                            IEnumerable <ZipEntry>        newContentEntries = newPackageZip.Entries.Where(e => e.FileName.StartsWith(@"content/", StringComparison.InvariantCultureIgnoreCase));
                            List <ZipEntry>               filesNeedToUpdate = new List <ZipEntry>();
                            Dictionary <string, ZipEntry> indexedOldFiles   = new Dictionary <string, ZipEntry>();
                            foreach (var item in oldContentEntries)
                            {
                                indexedOldFiles.Add(item.FileName.ToLowerInvariant(), item);
                            }

                            foreach (var newEntry in newContentEntries)
                            {
                                var fileName = newEntry.FileName.ToLowerInvariant();
                                if (indexedOldFiles.ContainsKey(fileName))
                                {
                                    // file name existed, only update if file has been touched
                                    ZipEntry oldEntry = indexedOldFiles[fileName];
                                    if (oldEntry.LastModified != newEntry.LastModified)
                                    {
                                        filesNeedToUpdate.Add(newEntry);
                                    }

                                    // remove from old index files buffer, the rest will be files that need to be deleted
                                    indexedOldFiles.Remove(fileName);
                                }
                                else
                                {
                                    // new files
                                    filesNeedToUpdate.Add(newEntry);
                                }
                            }

                            int substringStartIndex = @"content/".Length;

                            foreach (var entry in filesNeedToUpdate)
                            {
                                string fullPath = Path.Combine(destinationFolder, entry.FileName.Substring(substringStartIndex));

                                if (entry.IsDirectory)
                                {
                                    using (tracer.Step("Ensure directory: {0}", fullPath))
                                    {
                                        FileSystemHelpers.EnsureDirectory(fullPath.Replace('/', '\\'));
                                    }

                                    continue;
                                }

                                using (tracer.Step("Adding/Updating file: {0}", fullPath))
                                {
                                    FileSystemHelpers.EnsureDirectory(Path.GetDirectoryName(fullPath));
                                    using (Stream writeStream = FileSystemHelpers.OpenWrite(fullPath))
                                    {
                                        // reset length of file stream
                                        writeStream.SetLength(0);

                                        // let the thread go with itself, so that once file finishes writing, doesn't need to request thread context from main thread
                                        await entry.OpenReader().CopyToAsync(writeStream).ConfigureAwait(false);
                                    }
                                }
                            }

                            foreach (var entry in indexedOldFiles.Values)
                            {
                                string fullPath = Path.Combine(destinationFolder, entry.FileName.Substring(substringStartIndex));

                                if (entry.IsDirectory)
                                {
                                    // in case the two zip file was created from different tool. some tool will include folder as seperate entry, some don`t.
                                    // to be sure that foder is meant to be deleted, double check there is no files under it
                                    var entryNameInLower = entry.FileName.ToLower();
                                    if (!string.Equals(destinationFolder, fullPath, StringComparison.OrdinalIgnoreCase) &&
                                        newContentEntries.FirstOrDefault(e => e.FileName.ToLowerInvariant().StartsWith(entryNameInLower)) == null)
                                    {
                                        using (tracer.Step("Deleting directory: {0}", fullPath))
                                        {
                                            FileSystemHelpers.DeleteDirectorySafe(fullPath);
                                        }
                                    }
                                    continue;
                                }

                                using (tracer.Step("Deleting file: {0}", fullPath))
                                {
                                    FileSystemHelpers.DeleteFileSafe(fullPath);
                                }
                            }
                        }

                // update nupkg
                newPackageStream.Position = 0;
                using (tracer.Step("Updating nupkg file."))
                {
                    WriteStreamToFile(newPackageStream, pathToLocalCopyOfNupkg);
                    if (!identity.Version.Equals(localPackage.Identity.Version))
                    {
                        using (tracer.Step("New package has difference version {0} from old package {1}. Remove old nupkg file.", identity.Version, localPackage.Identity.Version))
                        {
                            // if version is difference, nupkg file name will be difference. will need to clean up the old one.
                            var oldNupkg = pathToLocalCopyOfNupkg.Replace(
                                string.Format(CultureInfo.InvariantCulture, "{0}.{1}.nupkg", identity.Id, identity.Version.ToNormalizedString()),
                                string.Format(CultureInfo.InvariantCulture, "{0}.{1}.nupkg", localPackage.Identity.Id, localPackage.Identity.Version.ToNormalizedString()));

                            FileSystemHelpers.DeleteFileSafe(oldNupkg);
                        }
                    }
                }
            }
        }