Пример #1
0
        public async Task<TempPackage> FetchAsync(Package pkg, Progress progress)
        {
            var user = pkg.Location.Host;
            var project = pkg.Location.Segments.Skip(1).SingleOrDefault()?.Trim('/');
            var props = pkg.Location.ParseQueryString();
            var url = $"https://api.github.com/repos/{user}/{project}/releases/latest";

            using (var httpClient = NetUtils.HttpClient())
            {
                var content = await httpClient.GetStringAsync(url);

                var json = fastJSON.JSON.Parse(content) as IDictionary<string, object>;
                var assets = json["assets"] as IList<object>;
                var asset = NarrowAssets(assets, props);
                var pkgUrlString = asset["browser_download_url"] as string;
                Uri pkgUri;
                if (!Uri.TryCreate(pkgUrlString, UriKind.Absolute, out pkgUri))
                {
                    throw new UriFormatException($"Could not parse output from Github API, failed to parse URI: '{pkgUrlString}'");
                }
                var result = new TempPackage
                {
                    Package = pkg,
                    WorkDirectory = new TempDirectory("winston"),
                    FileName = pkgUri.LastSegment()
                };

                using (var download = File.Open(result.FullPath, FileMode.Create, FileAccess.ReadWrite))
                {
                    await httpClient.DownloadFileAsync(pkgUri, download, progress);
                }
                progress?.CompletedDownload();
                return result;
            }
        }
Пример #2
0
        public async Task<TempPackage> FetchAsync(Package pkg, Progress progress)
        {
            var result = new TempPackage { WorkDirectory = new TempDirectory("winston") };
            using (var handler = new HttpClientHandler { AllowAutoRedirect = true })
            using (var client = NetUtils.HttpClient(handler))
            using (var response = await client.GetAsync(pkg.Location, HttpCompletionOption.ResponseHeadersRead))
            {
                result.MimeType = response.Content.Headers.ContentType?.MediaType;

                var uriFileName = pkg.Location.LastSegment();
                // Heuristic: assume the last path segment is a file name if it contains a dot for the file extension
                if (!uriFileName.Contains('.'))
                {
                    uriFileName = null;
                }
                // Try to get the right file name to give hints about the file type to the extractor
                result.FileName = response.Content.Headers.ContentDisposition?.FileName?.Trim('\"', '\\', '\'') ??
                                  uriFileName ??
                                  "package";

                var total = response.Content.Headers.ContentLength ?? -1L;

                using (var stream = await response.Content.ReadAsStreamAsync())
                using (var output = File.Open(result.FullPath, FileMode.Create, FileAccess.ReadWrite))
                {
                    var totalRead = 0L;
                    var buffer = new byte[81920]; // Default size from .NET docs on CopyTo
                    while (true)
                    {
                        var read = await stream.ReadAsync(buffer, 0, buffer.Length);
                        if (read == 0)
                        {
                            break;
                        }
                        await output.WriteAsync(buffer, 0, read);
                        totalRead += read;
                        // Can't report progress if there was no Content-Length
                        if (total > 0)
                        {
                            progress?.Report(totalRead * 1d / (total * 1d) * 100);
                        }
                    }
                    progress?.Report(100);
                    progress?.CompletedDownload();
                }
            }

            var hash = await FileSystem.GetSha1Async(result.FullPath);
            // Only check when Sha1 is specified in the package metadata
            if (!string.IsNullOrWhiteSpace(pkg.Sha1) &&
                !string.Equals(hash, pkg.Sha1, StringComparison.OrdinalIgnoreCase))
            {
                throw new InvalidDataException($"SHA1 hash of remote file {pkg.Location} did not match {pkg.Sha1}");
            }
            return result;
        }
Пример #3
0
 public async Task<TempPackage> FetchAsync(Package pkg, Progress progress)
 {
     var result = new TempPackage
     {
         FileName = Path.GetFileName(pkg.Location.LocalPath),
         Package = pkg,
         WorkDirectory = new NonTempItem(pkg.Location.LocalPath)
     };
     return await Task.FromResult(result);
 }
Пример #4
0
 public async Task<string> AddAsync(Package pkg, bool inject = true, bool writeRegistryPath = true)
 {
     var pkgDir = Path.Combine(RepoPath, pkg.Name);
     var client = new PackageClient(pkg, pkgDir);
     var progress = user.NewProgress(pkg.Name);
     var installDir = await client.InstallAsync(progress);
     var junctionPath = CreateCurrentJunction(pkgDir, installDir.FullName);
     var path = UpdatePaths(pkg, inject, writeRegistryPath, junctionPath);
     progress.CompletedInstall();
     return path;
 }
Пример #5
0
 public async Task CanFetchLatestVersion(string namePattern)
 {
     var fetcher = new GithubFetcher();
     var pkg = new Package
     {
         Name = "Test",
         Location = new Uri($"github://mattolenik/winston-test/?name={namePattern}")
     };
     var tmpPkg = await fetcher.FetchAsync(pkg, null);
     var ext = new ArchiveExtractor();
     using (var tmpDir = new TempDirectory("winston-test-"))
     {
         await ext.ExtractAsync(tmpPkg, tmpDir, null);
         Directory.GetFiles(tmpDir).Should().Contain(f => f.Contains("test.exe"));
     }
 }
Пример #6
0
 public Package Merge(Package other)
 {
     return new Package
     {
         Name = Name ?? other.Name,
         Description = Description ?? other.Description,
         Maintainer = Maintainer ?? other.Maintainer,
         Location = Location ?? other.Location,
         Path = Path ?? other.Path,
         Type = Type != PackageType.Unspecified ? Type : other.Type,
         Preserve = Preserve ?? other.Preserve,
         Ignore = Ignore ?? other.Ignore,
         Platform = Platform != Platform.Nil ? Platform : other.Platform,
         Variants = Variants ?? other.Variants,
         Version = Version ?? other.Version
     };
 }
Пример #7
0
 static string UpdatePaths(Package pkg, bool inject, bool writeRegistryPath, string junctionPath)
 {
     var matches = Paths.ResolveGlobPath(junctionPath, pkg.Path);
     if (matches.Count() > 1)
     {
         throw new NotSupportedException("Only globbing which results in a single path result is supported at this time");
     }
     var path = matches.SingleOrDefault();
     if (path == null)
     {
         throw new ArgumentException("Package path did not resolve to any path on disk");
     }
     // resolve wildcard here
     if (writeRegistryPath)
     {
         UpdateRegistryPath(path);
     }
     if (inject)
     {
         InjectPathIntoParent(path);
     }
     return path;
 }
Пример #8
0
 public bool IsMatch(Package pkg)
 {
     return pkg.Location.Scheme == "http" || pkg.Location.Scheme == "https";
 }
Пример #9
0
 public bool IsMatch(Package pkg)
 {
     // TODO: check for a pkg.json to verify this directory is really a package?
     return Directory.Exists(pkg?.Location?.LocalPath ?? ":");
 }
Пример #10
0
 public bool IsMatch(Package pkg)
 {
     return pkg.Location.Scheme == "github";
 }
Пример #11
0
 public PackageClient(Package pkg, string pkgDir)
 {
     this.pkg = pkg;
     this.pkgDir = pkgDir;
 }