Esempio n. 1
0
        static int BundleCommand(IEnumerable <string> args)
        {
            var help       = Ref.Create(false);
            var verbose    = Ref.Create(false);
            var force      = false;
            var bundlePath = (string)null;

            var options = new OptionSet(CreateStrictOptionSetArgumentParser())
            {
                Options.Help(help),
                Options.Verbose(verbose),
                Options.Debug,
                { "f|force", "overwrite bundle if exists", _ => force = true },
                { "o|out=", "write bundle at {PATH}", v => bundlePath = v },
            };

            var tail = options.Parse(args);

            var log = verbose ? Console.Error : null;

            if (log != null)
            {
                Trace.Listeners.Add(new TextWriterTraceListener(log));
            }

            if (help)
            {
                Help(options);
                return(0);
            }

            var queryPath = tail.FirstOrNone() switch
            {
                (SomeT, var arg) => arg,
                _ => throw new Exception("Missing LINQPad query path argument")
            };

            var query = LinqPadQuery.Load(Path.GetFullPath(queryPath));

            if (query.ValidateSupported() is Exception e)
            {
                throw e;
            }

            var logbundlePath = bundlePath == null;

            bundlePath ??= Path.ChangeExtension(query.FilePath, ".zip");

            if (!force && File.Exists(bundlePath))
            {
                throw new Exception("Target bundle file already exists: " + bundlePath);
            }

            File.Delete(bundlePath);

            var tempZipFilePath = Path.GetRandomFileName();

            using var _   = Defer(tempZipFilePath, File.Delete);
            using var zip = ZipFile.Open(tempZipFilePath, ZipArchiveMode.Create);

            var queryFileName = Path.GetFileName(query.FilePath);

            var epEntry = zip.CreateEntry(Path.GetFileName("lpless-bundle.ini"));

            epEntry.LastWriteTime = File.GetLastWriteTime(query.FilePath);
            using (var stream = epEntry.Open())
                using (var writer = new StreamWriter(stream, Utf8.BomlessEncoding))
                    writer.WriteLine("entrypoint=" + queryFileName);

            var loads = new List <(string Name, string SourceFilePath)>();

            var mainEntry = zip.CreateEntry(queryFileName);

            mainEntry.LastWriteTime = File.GetLastWriteTime(query.FilePath);
            using (var stream = mainEntry.Open())
                using (var writer = new StreamWriter(stream, Utf8.BomlessEncoding))
                {
                    var eomLineNumber = LinqPad.GetEndOfMetaLineNumber(new FileInfo(queryPath));
                    foreach (var line in File.ReadLines(queryPath).Take(eomLineNumber))
                    {
                        writer.WriteLine(line);
                    }

                    var loadNameSet = new HashSet <string>(StringComparer.OrdinalIgnoreCase)
                    {
                        mainEntry.Name
                    };

                    foreach (var(line, load) in
                             query.Code.Lines()
                             .Index(1)
                             .LeftJoin(query.Loads, e => e.Key, e => e.LineNumber,
                                       line => (line.Value, default),
                                       (line, load) => (line.Value, load)))
                    {
                        if (load != null)
                        {
                            var fileName     = Path.GetFileName(load.Path);
                            var originalName = Path.GetFileNameWithoutExtension(fileName);
                            var extension    = Path.GetExtension(fileName);

                            for (var counter = 1; !loadNameSet.Add(fileName); counter++)
                            {
                                fileName = originalName + counter.ToString(CultureInfo.InvariantCulture) + extension;
                            }

                            loads.Add((fileName, load.Path));

                            writer.WriteLine($@"#load "".\{fileName}"" // {line}");
                        }
                        else
                        {
                            writer.WriteLine(line);
                        }
                    }
                }

            if (loads.Count == 0)
            {
                Console.Error.WriteLine("Warning! No load directives found. Bundle is redundant.");
            }

            foreach (var(name, path) in loads)
            {
                log?.WriteLine("+ " + path);
                var entry = zip.CreateEntry(name);
                entry.LastWriteTime = File.GetLastWriteTime(path);
                using var output    = entry.Open();
                using var input     = File.OpenRead(path);
                input.CopyTo(output);
                output.Flush();
            }

            zip.Dispose();
            File.Move(tempZipFilePath, bundlePath);

            if (logbundlePath)
            {
                Console.Error.WriteLine(bundlePath);
            }

            return(0);
        }
Esempio n. 2
0
        static LinqPadQuery Parse(string source, string path, bool parseLoads, bool resolveLoads)
        {
            var eomLineNumber = LinqPad.GetEndOfMetaLineNumber(source);

            return(new LinqPadQuery(path, source, eomLineNumber, parseLoads, resolveLoads));
        }
Esempio n. 3
0
        static T Compile <T>(string queryFilePath, IPackageRepository repo, string packagesPath,
                             IEnumerable <PackageReference> extraPackageReferences,
                             IEnumerable <string> extraImports,
                             FrameworkName targetFramework,
                             bool verbose, IndentingLineWriter writer,
                             Func <QueryLanguage, string, IEnumerable <string>, IEnumerable <Reference>, T> selector)
        {
            var eomLineNumber = LinqPad.GetEndOfMetaLineNumber(queryFilePath);
            var lines         = File.ReadLines(queryFilePath);

            var xml = string.Join(Environment.NewLine,
                                  // ReSharper disable once PossibleMultipleEnumeration
                                  lines.Take(eomLineNumber));

            var query = XElement.Parse(xml);

            if (verbose)
            {
                writer.Write(query);
            }

            QueryLanguage queryKind;

            if (!Enum.TryParse((string)query.Attribute("Kind"), true, out queryKind) ||
                (queryKind != QueryLanguage.Statements &&
                 queryKind != QueryLanguage.Expression &&
                 queryKind != QueryLanguage.Program))
            {
                throw new NotSupportedException("Only LINQPad " +
                                                "C# Statements and Expression queries are fully supported " +
                                                "and C# Program queries partially in this version.");
            }

            var nrs =
                from nrsq in new[]
            {
                from nr in query.Elements("NuGetReference")
                select new PackageReference((string)nr,
                                            SemanticVersion.ParseOptionalVersion((string)nr.Attribute("Version")),
                                            (bool?)nr.Attribute("Prerelease") ?? false),
                extraPackageReferences,
            }
            from nr in nrsq
                select new
            {
                nr.Id,
                nr.Version,
                nr.IsPrereleaseAllowed,
                Title = string.Join(" ", Seq.Return(nr.Id,
                                                    nr.Version?.ToString(),
                                                    nr.IsPrereleaseAllowed ? "(pre-release)" : null)
                                    .Filter()),
            };

            nrs = nrs.ToArray();

            if (verbose && nrs.Any())
            {
                writer.WriteLine($"Packages referenced ({nrs.Count():N0}):");
                writer.Indent().WriteLines(from nr in nrs select nr.Title);
            }

            writer.WriteLine($"Packages directory: {packagesPath}");
            var pm = new PackageManager(repo, packagesPath);

            pm.PackageInstalling += (_, ea) =>
                                    writer.WriteLine($"Installing {ea.Package}...");
            pm.PackageInstalled += (_, ea) =>
                                   writer.Indent().WriteLine($"Installed at {ea.InstallPath}");

            writer.WriteLine($"Packages target: {targetFramework}");

            var resolutionList = Enumerable.Repeat(new { Package      = default(IPackage),
                                                         AssemblyPath = default(string) }, 0)
                                 .ToList();

            foreach (var nr in nrs)
            {
                var pkg = pm.LocalRepository.FindPackage(nr.Id, nr.Version,
                                                         allowPrereleaseVersions: nr.IsPrereleaseAllowed,
                                                         allowUnlisted: false);
                if (pkg == null)
                {
                    pkg = repo.FindPackage(nr.Id, nr.Version,
                                           allowPrereleaseVersions: nr.IsPrereleaseAllowed,
                                           allowUnlisted: false);

                    if (pkg == null)
                    {
                        throw new Exception("Package not found: " + nr.Title);
                    }

                    pm.InstallPackage(pkg.Id, pkg.Version);
                }

                writer.WriteLine("Resolving references...");
                resolutionList.AddRange(GetReferencesTree(pm.LocalRepository, pkg, targetFramework, writer.Indent(), (r, p) => new
                {
                    Package      = p,
                    AssemblyPath = r != null
                                 ? Path.Combine(pm.PathResolver.GetInstallPath(p), r.Path)
                                 : null
                }));
            }

            var packagesPathWithTrailer = packagesPath + Path.DirectorySeparatorChar;

            var resolution =
                resolutionList
                .GroupBy(r => r.Package)
                .Select(g => g.First())
                .Select(r => new
            {
                r.Package,
                AssemblyPath = r.AssemblyPath != null
                            ? MakeRelativePath(queryFilePath, packagesPathWithTrailer)
                               + MakeRelativePath(packagesPathWithTrailer, r.AssemblyPath)
                            : null,
            })
                .Partition(r => r.AssemblyPath == null, (ok, nok) => new
            {
                ResolvedReferences    = ok,
                ReferencelessPackages = from r in nok
                                        select r.Package.GetFullName(),
            });

            resolution.ReferencelessPackages.StartIter(e =>
            {
                writer.WriteLine($"Warning! Packages with no references for {targetFramework}:");
                writer.Indent().WriteLines(e.ResumeFromCurrent());
            });

            var references = resolution.ResolvedReferences.ToArray();

            references.Select(r => r.AssemblyPath).StartIter(e =>
            {
                writer.WriteLine($"Resolved references ({references.Length:N0}):");
                writer.Indent().WriteLines(e.ResumeFromCurrent());
            });

            return
                (selector(
                     queryKind,
                     // ReSharper disable once PossibleMultipleEnumeration
                     string.Join(Environment.NewLine, lines.Skip(eomLineNumber)),
                     LinqPad.DefaultNamespaces
                     .Concat(from ns in query.Elements("Namespace")
                             select(string) ns)
                     .Concat(extraImports),
                     LinqPad.DefaultReferences.Select(r => new Reference(r))
                     .Concat(from r in query.Elements("Reference")
                             select(string) r into r
                             select r.StartsWith(LinqPad.RuntimeDirToken, StringComparison.OrdinalIgnoreCase)
                                        ? r.Substring(LinqPad.RuntimeDirToken.Length)
                                        : r into r
                             select new Reference(r))
                     .Concat(from r in references
                             select new Reference(r.AssemblyPath, r.Package))));
        }