public int Execute(Execution execution) { var archiveType = this.DetectPackageType(execution.PackagePushFile); if (archiveType == PackageManager.ARCHIVE_FORMAT_NUGET_ZIP) { if (execution.PackagePushVersion != ArgumentOmitted || execution.PackagePushPlatform != ArgumentOmitted) { RedirectableConsole.ErrorWriteLine("You must omit the version and platform arguments when pushing packages in the NuGet format."); } } else { if (execution.PackagePushVersion == ArgumentOmitted || execution.PackagePushPlatform == ArgumentOmitted) { RedirectableConsole.ErrorWriteLine("You must provide the version and platform arguments."); } } RedirectableConsole.WriteLine("Detected package type as " + archiveType + "."); switch (archiveType) { case PackageManager.ARCHIVE_FORMAT_NUGET_ZIP: return(PushToNuGetRepository(execution)); case PackageManager.ARCHIVE_FORMAT_TAR_GZIP: case PackageManager.ARCHIVE_FORMAT_TAR_LZMA: default: return(PushToProtobuildRepository(execution, archiveType)); } }
private static string FindGitOnSystemPath() { if (Path.DirectorySeparatorChar != '/') { // We're on Windows. We split the environment PATH to see if we // can find Git, then we check standard directories (like // C:\Program Files (x86)\Git) etc. var pathEnv = Environment.GetEnvironmentVariable("PATH"); var paths = new string[0]; if (pathEnv != null) { paths = pathEnv.Split(';'); } var standardPaths = new List <string> { Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86), "Git", "cmd"), Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86), "Git", "bin"), Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), "Git", "cmd"), Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), "Git", "bin"), }; // Add standard paths that GitHub for Windows uses. Because the file // contains a hash, or some other mutable component, we need to search for // the PortableGit path. var github = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "GitHub"); if (Directory.Exists(github)) { foreach (var subfolder in new DirectoryInfo(github).GetDirectories()) { if (subfolder.Name.StartsWith("PortableGit_")) { standardPaths.Add(Path.Combine(subfolder.FullName, "cmd")); } } } var filenames = new[] { "git.exe", "git.bat", "git.cmd" }; foreach (var path in paths.Concat(standardPaths)) { foreach (var filename in filenames) { if (File.Exists(Path.Combine(path, filename))) { // We found Git. return(Path.Combine(path, filename)); } } } RedirectableConsole.ErrorWriteLine( "WARNING: Unable to find Git on your PATH, or any standard " + "locations. Have you installed Git on this system?"); return("git"); } // For UNIX systems, Git should always be on the PATH. return("git"); }
public int Execute(Execution execution) { var scriptPath = execution.AutomatedBuildScriptPath ?? "automated.build"; if (!File.Exists(scriptPath)) { RedirectableConsole.ErrorWriteLine("ERROR: Automated build script not found at " + scriptPath + "."); } return(_automatedBuildController.Execute(execution.WorkingDirectory, scriptPath)); }
private static bool SSLValidationForLinux(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslpolicyerrors) { // If the Mono root CA store is initialized properly, then use that. if (sslpolicyerrors == SslPolicyErrors.None) { // Good certificate. return(true); } // I'm not sure of the stability of the certificate thumbprint for protobuild.org // itself, so instead just verify that it is Let's Encrypt that's providing the // certificate. if (sender is HttpWebRequest && (sender as HttpWebRequest).Host == "protobuild.org") { if (chain.ChainElements.Count > 2 && chain.ChainElements[1].Certificate.Thumbprint == "3EAE91937EC85D74483FF4B77B07B43E2AF36BF4") { // This is the Let's Encrypt certificate authority. We can implicitly trust this without warning. return(true); } else { // The thumbprint differs! Show a danger message to the user, but continue anyway // because if the thumbprint does legitimately change, we have no way of backporting // a new certificate thumbprint without issuing a new version of Protobuild. var givenThumbprint = chain.ChainElements.Count >= 2 ? chain.ChainElements[1].Certificate.Thumbprint : "<no thumbprint available>"; RedirectableConsole.ErrorWriteLine( "DANGER: The thumbprint of the issuer's SSL certificate for protobuild.org \"" + givenThumbprint + "\" does not match the expected thumbprint value \"" + chain.ChainElements[1].Certificate.Thumbprint + "\". It's possible that Let's Encrypt " + "changed their certificate thumbprint, or someone is performing a MITM " + "attack on your connection. Unfortunately Mono does not ship out-of-the-box " + "with appropriate root CA certificates on Linux, so we have no method of verifying " + "that the proposed thumbprint is correct. You should verify that the given " + "thumbprint is correct either through your web browser (by visiting protobuild.org " + "and checking the certificate chain), or by performing the same operation on " + "Mac OS or Windows. If the operation succeeds, or the thumbprint matches, please " + "file an issue at https://github.com/hach-que/Protobuild/issues/new so we can " + "update the embedded thumbprint. We will now continue the operation regardless " + "as we can't update the thumbprint in previous versions if it has changed."); return(true); } } RedirectableConsole.WriteLine( "WARNING: Implicitly trusting SSL certificate " + certificate.GetCertHashString() + " " + "for " + certificate.Subject + " issued by " + certificate.Issuer + " on Linux, due " + "to inconsistent root CA store policies of Mono."); return(true); }
private void ShowSupportedPlatformsError(ModuleInfo module, string requestedPlatform) { RedirectableConsole.ErrorWriteLine("The platform '" + requestedPlatform + "' is not supported."); RedirectableConsole.ErrorWriteLine("The following platforms are supported by this module:"); foreach ( var supportedPlatform in module.SupportedPlatforms.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries) .Select(x => x.Trim()) .Where(x => !string.IsNullOrWhiteSpace(x))) { RedirectableConsole.ErrorWriteLine(" * " + supportedPlatform); } ExecEnvironment.Exit(1); }
private void InstallAssemblyIntoGAC(string gacPath) { try { var assembly = Assembly.Load("System.EnterpriseServices"); var type = assembly.GetType("System.EnterpriseServices.Internal.Publish"); var constructor = type.GetConstructor(Type.EmptyTypes); var publishObject = constructor.Invoke(null); var gacInstall = type.GetMethod("GacInstall"); gacInstall.Invoke(publishObject, new object[] { gacPath }); RedirectableConsole.WriteLine("GAC installation completed successfully for '" + gacPath + "'"); } catch (Exception ex) { RedirectableConsole.ErrorWriteLine("Got an exception while performing GAC install for '" + gacPath + "': " + ex.Message); } }
private Feature?LookupFeatureByID(string str) { foreach (var name in Enum.GetNames(typeof(Feature))) { var field = typeof(Feature).GetField(name); var internalAttribute = field.GetCustomAttributes(typeof(FeatureInternalAttribute), false).FirstOrDefault() as FeatureInternalAttribute; if (internalAttribute != null) { if (internalAttribute.InternalId == str) { return((Feature)field.GetValue(null)); } } } RedirectableConsole.ErrorWriteLine("WARNING: Unable to find feature based on ID '" + str + "'"); return(null); }
private void PerformRetryableRequest(string message, Uri baseUri, Action <Uri> func) { var exceptions = new List <Exception>(); var backoff = 100; for (var i = 0; i < MaxRequests; i++) { try { RedirectableConsole.WriteLine("(" + (i + 1) + "/" + MaxRequests + ") " + message); func(baseUri); return; } catch (Exception ex) { RedirectableConsole.ErrorWriteLine("Exception during web request: "); RedirectableConsole.ErrorWriteLine(ex); exceptions.Add(ex); var webException = ex as WebException; if (webException != null) { switch (webException.Status) { case WebExceptionStatus.NameResolutionFailure: // This is a permanent failure. i = MaxRequests; backoff = 0; break; } } RedirectableConsole.WriteLine("Backing off web requests for " + backoff + "ms..."); System.Threading.Thread.Sleep(backoff); backoff *= 2; if (backoff > 20000) { backoff = 20000; } } } throw new AggregateException(exceptions); }
public int Execute(string workingDirectory, string path) { IAutomatedBuildRuntime runtime = null; string script = null; using (var reader = new StreamReader(path)) { script = reader.ReadToEnd(); if (script.StartsWith("#version 1")) { script = script.Substring("#version 1".Length).TrimStart(); runtime = _automatedBuildRuntimeV1; } else { throw new InvalidOperationException( "Your automated build script must start with #version N, where " + "N is the number indicating the script runtime version for " + "automated builds."); } } object handle; try { handle = runtime.Parse(script); } catch (Exception ex) { RedirectableConsole.ErrorWriteLine("ERROR: " + ex.Message); return(1); } try { return(runtime.Execute(workingDirectory, handle)); } catch (Exception ex) { RedirectableConsole.ErrorWriteLine("ERROR: " + ex.Message + Environment.NewLine + ex.StackTrace); return(1); } }
private string GetSourcePackage(string workingDirectory, string url) { var sourcePath = Path.Combine( _packageCacheConfiguration.GetCacheDirectory(), this.GetPackageName(url)); if (this.HasSourcePackage(url)) { if (Directory.Exists(Path.Combine(sourcePath, "objects")) && File.Exists(Path.Combine(sourcePath, "config"))) { try { GitUtils.RunGitAbsolute(sourcePath, "fetch origin +refs/heads/*:refs/heads/*"); } catch (InvalidOperationException) { // Ignore exceptions here in case the user is offline. } return(sourcePath); } else { RedirectableConsole.ErrorWriteLine("WARNING: Source package cache is corrupt, removing and cloning again..."); try { PathUtils.AggressiveDirectoryDelete(sourcePath); } catch (Exception) { RedirectableConsole.ErrorWriteLine("WARNING: Unable to delete invalid source package from cache!"); } } } Directory.CreateDirectory(sourcePath); GitUtils.RunGit(workingDirectory, null, "clone --progress --bare " + url + " \"" + sourcePath + "\""); return(sourcePath); }
public void ValidateEnabledFeatures() { var features = GetAllEnabledFeatures().OrderByDescending(x => (int)x).ToArray(); var nonInternalFeatures = GetAllNonInternalFeatures().OrderByDescending(x => (int)x).ToList(); var missingFeatures = new List <Feature>(); foreach (var enabledFeature in features) { var idx = nonInternalFeatures.IndexOf(enabledFeature); if (idx == -1) { continue; } for (var i = idx; i < nonInternalFeatures.Count; i++) { if (!features.Contains(nonInternalFeatures[i])) { if (!missingFeatures.Contains(nonInternalFeatures[i])) { missingFeatures.Add(nonInternalFeatures[i]); } } } } if (missingFeatures.Count > 0) { var featureList = features.Length == 0 ? string.Empty : features.Select(x => x.ToString()).Aggregate((a, b) => a + "," + b); var missingFeatureList = missingFeatures.Count == 0 ? string.Empty : missingFeatures.Select(x => x.ToString()).Aggregate((a, b) => a + "," + b); RedirectableConsole.ErrorWriteLine( "WARNING: The active feature set is missing previous features! " + "You have the following features enabled: '" + featureList + "', but the following features should also be enabled for stability reasons: '" + missingFeatureList + "'"); } }
public int Execute(Execution execution) { var hostPlatform = _hostPlatformDetector.DetectPlatform(); string builderPathNativeArch = null; string builderPath64 = null; string builderPath32 = null; var extraArgsNativeArch = string.Empty; var extraArgs64 = string.Empty; var extraArgs32 = string.Empty; var extraArgsGeneral = string.Empty; if (hostPlatform == "Windows") { foreach (var arch in new[] { RegistryView.Default, RegistryView.Registry32, RegistryView.Registry64 }) { // Find latest version of MSBuild. var registryKey = RegistryKey.OpenBaseKey( RegistryHive.LocalMachine, arch) .OpenSubKey("SOFTWARE")? .OpenSubKey("Microsoft")? .OpenSubKey("MSBuild")? .OpenSubKey("ToolsVersions"); if (registryKey == null) { if (arch == RegistryView.Registry64) { continue; } RedirectableConsole.ErrorWriteLine( "ERROR: No versions of MSBuild were available " + "according to the registry (or they were not readable)."); return(1); } var subkeys = registryKey.GetSubKeyNames(); var orderedVersions = subkeys.OrderByDescending(x => int.Parse(x.Split('.').First(), CultureInfo.InvariantCulture)); var builderPath = (from version in orderedVersions let path = (string)registryKey.OpenSubKey(version)?.GetValue("MSBuildToolsPath") where path != null && Directory.Exists(path) let msbuild = Path.Combine(path, "MSBuild.exe") where File.Exists(msbuild) select msbuild).FirstOrDefault(); if (builderPath == null) { if (arch == RegistryView.Registry64) { continue; } RedirectableConsole.ErrorWriteLine( "ERROR: Unable to find installed MSBuild in any installed tools version."); return(1); } var extraArgs = string.Empty; if (!builderPath.Contains("v2.0.50727")) { extraArgs = "/m /nodeReuse:false "; } switch (arch) { case RegistryView.Default: builderPathNativeArch = builderPath; extraArgsNativeArch = extraArgs; break; case RegistryView.Registry32: builderPath32 = builderPath; extraArgs32 = extraArgs; break; case RegistryView.Registry64: builderPath64 = builderPath; extraArgs64 = extraArgs; break; } } } else { // Find path to xbuild. var whichPaths = new[] { "/bin/which", "/usr/bin/which" }; foreach (var w in whichPaths) { if (File.Exists(w)) { var whichProcess = Process.Start(new ProcessStartInfo(w, "xbuild") { RedirectStandardOutput = true, UseShellExecute = false }); if (whichProcess == null) { continue; } var result = whichProcess.StandardOutput.ReadToEnd().Trim(); if (!string.IsNullOrWhiteSpace(result) && File.Exists(result)) { builderPathNativeArch = result; break; } } } if (builderPathNativeArch == null && _hostPlatformDetector.DetectPlatform() == "MacOS" && File.Exists("/usr/local/bin/xbuild")) { // After upgrading to OSX El Capitan, the /usr/local/bin folder is no longer in // the system PATH. If we can't find xbuild with the which tool, manually set the // path here in an attempt to find it. builderPathNativeArch = "/usr/local/bin/xbuild"; } if (builderPathNativeArch == null) { RedirectableConsole.ErrorWriteLine("ERROR: Unable to find xbuild on the current PATH."); return(1); } builderPath32 = builderPathNativeArch; builderPath64 = builderPathNativeArch; } if (!string.IsNullOrWhiteSpace(execution.BuildTarget)) { extraArgsGeneral += "/t:\"" + execution.BuildTarget + "\" "; } foreach (var prop in execution.BuildProperties) { extraArgsGeneral += "/p:\"" + prop.Key.Replace("\"", "\\\"") + "\"=\"" + (prop.Value ?? string.Empty).Replace("\"", "\\\"") + "\" "; } switch (execution.BuildProcessArchitecture) { case "x86": RedirectableConsole.WriteLine("INFO: Using " + builderPath32 + " (forced 32-bit) to perform this build."); break; case "x64": RedirectableConsole.WriteLine("INFO: Using " + builderPath64 + " (forced 64-bit) to perform this build."); break; case "Default": default: RedirectableConsole.WriteLine("INFO: Using " + builderPathNativeArch + " (32-bit: " + builderPath32 + ") to perform this build."); break; } var targetPlatforms = (execution.Platform ?? hostPlatform).Split(','); var module = ModuleInfo.Load(Path.Combine(execution.WorkingDirectory, "Build", "Module.xml")); foreach (var platform in targetPlatforms) { string builderPath; string extraArgs; switch (execution.BuildProcessArchitecture) { case "x86": builderPath = builderPath32; extraArgs = extraArgs32 + extraArgsGeneral; break; case "x64": builderPath = builderPath64; extraArgs = extraArgs64 + extraArgsGeneral; break; case "Default": default: builderPath = platform == "WindowsPhone" ? builderPath32 : builderPathNativeArch; extraArgs = (platform == "WindowsPhone" ? extraArgs32 : extraArgsNativeArch) + extraArgsGeneral; break; } var fileToBuild = module.Name + "." + platform + ".sln"; RedirectableConsole.WriteLine("INFO: Executing " + builderPath + " with arguments: " + extraArgs + fileToBuild); var process = Process.Start(new ProcessStartInfo(builderPath, extraArgs + fileToBuild) { UseShellExecute = false }); if (process == null) { RedirectableConsole.ErrorWriteLine("ERROR: Build process did not start successfully."); return(1); } process.WaitForExit(); if (process.ExitCode != 0) { return(process.ExitCode); } } return(0); }
public byte[] Transform(string workingDirectory, string url, string gitReference, string platform, string format) { var urlAndPackageName = url.Split(new[] { '|' }, 2); if (urlAndPackageName.Length != 2) { RedirectableConsole.ErrorWriteLine( "ERROR: Malformed NuGet package reference '" + url + "'. Make sure you split the NuGet server URL and the package name with a pipe character (|)."); ExecEnvironment.Exit(1); } var repoUrl = urlAndPackageName[0]; var packageName = urlAndPackageName[1]; var originalFolder = DownloadOrUseExistingNuGetPackage(repoUrl.TrimEnd('/'), packageName, gitReference); if (Directory.Exists(Path.Combine(originalFolder, "protobuild"))) { // This is a Protobuild-aware NuGet package. In this case, we just use the contents of the // "protobuild" folder as the content of our package, and ignore everything else. RedirectableConsole.WriteLine("Detected Protobuild-aware package..."); RedirectableConsole.WriteLine("Converting to a Protobuild package..."); var target = new MemoryStream(); var filter = new FileFilter(_getRecursiveUtilitiesInPath.GetRecursiveFilesInPath(originalFolder)); filter.ApplyInclude("protobuild/(.*)"); filter.ApplyRewrite("protobuild/(.*)", "$1"); filter.ImplyDirectories(); _packageCreator.Create( target, filter, originalFolder, format, platform); RedirectableConsole.WriteLine("Package conversion complete."); var bytes2 = new byte[target.Position]; target.Seek(0, SeekOrigin.Begin); target.Read(bytes2, 0, bytes2.Length); return(bytes2); } var folder = Path.GetTempFileName(); File.Delete(folder); Directory.CreateDirectory(folder); byte[] bytes; try { RedirectableConsole.WriteLine("Copying directory for package transformation..."); CopyFolder(new DirectoryInfo(originalFolder), new DirectoryInfo(folder)); RedirectableConsole.WriteLine("Auto-detecting libraries to reference from NuGet package..."); var packagePath = new DirectoryInfo(folder).GetFiles("*.nuspec").First().FullName; var libraryReferences = new Dictionary <string, string>(); var packageDependencies = new Dictionary <string, string>(); // Use the nuspec file if it exists. List <string> references = new List <string>(); if (File.Exists(packagePath)) { var packageDoc = new XmlDocument(); packageDoc.Load(packagePath); // If the references are explicitly provided in the nuspec, use // those as to what files should be referenced by the projects. if ( packageDoc.DocumentElement.FirstChild.ChildNodes.OfType <XmlElement>() .Count(x => x.Name == "references") > 0) { references = packageDoc.DocumentElement.FirstChild.ChildNodes.OfType <XmlElement>() .First(x => x.Name == "references") .ChildNodes.OfType <XmlElement>() .Where(x => x.Name == "reference") .Select(x => x.Attributes["file"].Value) .ToList(); } // If there are dependencies specified, store them and convert them to // Protobuild references, and reference them in the Module.xml file. if ( packageDoc.DocumentElement.FirstChild.ChildNodes.OfType <XmlElement>() .Count(x => x.Name == "dependencies") > 0) { packageDependencies = packageDoc.DocumentElement.FirstChild.ChildNodes.OfType <XmlElement>() .First(x => x.Name == "dependencies") .ChildNodes.OfType <XmlElement>() .Where(x => x.Name == "dependency") .ToDictionarySafe( k => k.Attributes["id"].Value, v => v.Attributes["version"].Value, (dict, c) => RedirectableConsole.WriteLine("WARNING: More than one dependency on " + c + " in NuGet package.")); } } // Determine the priority of the frameworks that we want to target // out of the available versions. string[] clrNames = _nuGetPlatformMapping.GetFrameworkNamesForRead(workingDirectory, platform); var referenceDirectories = new string[] { "ref", "lib" }; foreach (var directory in referenceDirectories) { // Determine the base path for all references; that is, the lib/ folder. var referenceBasePath = Path.Combine( folder, directory); if (Directory.Exists(referenceBasePath)) { // If no references are in nuspec, reference all of the libraries that // are on disk. if (references.Count == 0) { // Search through all of the target frameworks until we find one that // has at least one file in it. foreach (var clrNameOriginal in clrNames) { var clrName = clrNameOriginal; var foundClr = false; if (clrName[0] == '=') { // Exact match (strip the equals). clrName = clrName.Substring(1); // If this target framework doesn't exist for this library, skip it. var dirPath = Path.Combine( referenceBasePath, clrName); if (!Directory.Exists(dirPath)) { continue; } } else if (clrName[0] == '?') { // Substring, search the reference base path for any folders // with a matching substring. clrName = clrName.Substring(1); var baseDirPath = referenceBasePath; var found = false; foreach (var subdir in new DirectoryInfo(baseDirPath).GetDirectories()) { if (subdir.Name.Contains(clrName)) { clrName = subdir.Name; found = true; break; } } if (!found) { continue; } } else { throw new InvalidOperationException("Unknown CLR name match type with '" + clrName + "'"); } // Otherwise enumerate through all of the libraries in this folder. foreach (var dll in Directory.EnumerateFiles( Path.Combine( referenceBasePath, clrName), "*.dll")) { // Determine the relative path to the library. var packageDll = Path.Combine( referenceBasePath, clrName, Path.GetFileName(dll)); // Confirm again that the file actually exists on disk when // combined with the root path. if (File.Exists( Path.Combine( packageDll))) { // Create the library reference. if (!libraryReferences.ContainsKey(Path.GetFileNameWithoutExtension(dll))) { libraryReferences.Add( Path.GetFileNameWithoutExtension(dll), packageDll); } // Mark this target framework as having provided at least // one reference. foundClr = true; } } // Break if we have found at least one reference. if (foundClr) { break; } } } // For all of the references that were found in the original nuspec file, // add those references. foreach (var reference in references) { // Search through all of the target frameworks until we find the one // that has the reference in it. foreach (var clrName in clrNames) { // If this target framework doesn't exist for this library, skip it. var packageDll = Path.Combine( referenceBasePath, clrName, reference); if (File.Exists( Path.Combine( packageDll))) { if (!libraryReferences.ContainsKey(Path.GetFileNameWithoutExtension(packageDll))) { libraryReferences.Add( Path.GetFileNameWithoutExtension(packageDll), packageDll); } break; } } } } } foreach (var kv in libraryReferences) { RedirectableConsole.WriteLine("Found library to reference: " + kv.Key + " (at " + kv.Value + ")"); } RedirectableConsole.WriteLine("Generating external project reference..."); var document = new XmlDocument(); var externalProject = document.CreateElement("ExternalProject"); externalProject.SetAttribute("Name", packageName); document.AppendChild(externalProject); foreach (var kv in libraryReferences) { var binaryReference = document.CreateElement("Binary"); binaryReference.SetAttribute("Name", kv.Key); binaryReference.SetAttribute("Path", kv.Value.Substring(folder.Length).TrimStart(new[] { '/', '\\' }).Replace("%2B", "-")); externalProject.AppendChild(binaryReference); } foreach (var package in packageDependencies) { var externalReference = document.CreateElement("Reference"); externalReference.SetAttribute("Include", package.Key); externalProject.AppendChild(externalReference); } document.Save(Path.Combine(folder, "_ProtobuildExternalProject.xml")); RedirectableConsole.WriteLine("Generating module..."); var generatedModule = new ModuleInfo(); generatedModule.Name = packageName; generatedModule.Packages = new List <PackageRef>(); foreach (var package in packageDependencies) { generatedModule.Packages.Add(new PackageRef { Uri = repoUrl.Replace("http://", "http-nuget://").Replace("https://", "https-nuget://") + "|" + package.Key, GitRef = package.Value.TrimStart('[').TrimEnd(']'), Folder = package.Key }); } generatedModule.Save(Path.Combine(folder, "_ProtobuildModule.xml")); RedirectableConsole.WriteLine("Converting to a Protobuild package..."); var target = new MemoryStream(); var filter = new FileFilter(_getRecursiveUtilitiesInPath.GetRecursiveFilesInPath(folder)); foreach (var kv in libraryReferences) { filter.ApplyInclude( Regex.Escape(kv.Value.Substring(folder.Length).Replace('\\', '/').TrimStart('/'))); filter.ApplyRewrite( Regex.Escape(kv.Value.Substring(folder.Length).Replace('\\', '/').TrimStart('/')), kv.Value.Substring(folder.Length).Replace('\\', '/').TrimStart('/').Replace("%2B", "-")); } filter.ApplyInclude("_ProtobuildExternalProject\\.xml"); filter.ApplyRewrite("_ProtobuildExternalProject\\.xml", "Build/Projects/" + packageName + ".definition"); filter.ApplyInclude("_ProtobuildModule\\.xml"); filter.ApplyRewrite("_ProtobuildModule\\.xml", "Build/Module.xml"); filter.ImplyDirectories(); _packageCreator.Create( target, filter, folder, format, platform); RedirectableConsole.WriteLine("Package conversion complete."); bytes = new byte[target.Position]; target.Seek(0, SeekOrigin.Begin); target.Read(bytes, 0, bytes.Length); } finally { RedirectableConsole.WriteLine("Cleaning up temporary data..."); PathUtils.AggressiveDirectoryDelete(folder); } return(bytes); }
private T PerformRetryableRequest <T>(string message, Uri baseUri, Func <Uri, T> func) { var exceptions = new List <Exception>(); var backoff = 100; for (var i = 0; i < MaxRequests; i++) { try { RedirectableConsole.WriteLine("(" + (i + 1) + "/" + MaxRequests + ") " + message); return(func(baseUri)); } catch (Exception ex) { exceptions.Add(ex); var webException = ex as WebException; if (webException != null) { switch (webException.Status) { case WebExceptionStatus.ProtocolError: var httpWebResponse = webException.Response as HttpWebResponse; if (httpWebResponse != null) { switch (httpWebResponse.StatusCode) { case HttpStatusCode.NotFound: case HttpStatusCode.Forbidden: // This is a permanent failure. i = MaxRequests; backoff = 0; break; } } break; case WebExceptionStatus.ServerProtocolViolation: case WebExceptionStatus.NameResolutionFailure: // This is a permanent failure. i = MaxRequests; backoff = 0; break; } } if (!SilentOnError || i != MaxRequests || backoff != 0) { RedirectableConsole.ErrorWriteLine("Exception during web request: "); RedirectableConsole.ErrorWriteLine(ex); RedirectableConsole.WriteLine("Backing off web requests for " + backoff + "ms..."); } System.Threading.Thread.Sleep(backoff); backoff *= 2; if (backoff > 20000) { backoff = 20000; } } } throw new AggregateException(exceptions); }
public int Execute(Execution execution) { var hostPlatform = _hostPlatformDetector.DetectPlatform(); string builderPathNativeArch = null; string builderPath64 = null; string builderPath32 = null; var extraArgsNativeArch = string.Empty; var extraArgs64 = string.Empty; var extraArgs32 = string.Empty; var extraArgsGeneral = string.Empty; var targetPlatforms = (execution.Platform ?? hostPlatform).Split(','); var module = ModuleInfo.Load(Path.Combine(execution.WorkingDirectory, "Build", "Module.xml")); if (hostPlatform == "Windows") { // Newer installs of Visual Studio (like 2017) don't create registry entries for MSBuild, so we have to // use a tool called vswhere in order to find MSBuild on these systems. This call will implicitly install // the vswhere package if it's not already installed. var vswhere = _knownToolProvider.GetToolExecutablePath("vswhere"); List <string> installations = null; if (vswhere != null && File.Exists(vswhere)) { try { var processStartInfo = new ProcessStartInfo(); processStartInfo.FileName = vswhere; processStartInfo.Arguments = "-products * -requires Microsoft.Component.MSBuild -property installationPath"; processStartInfo.UseShellExecute = false; processStartInfo.RedirectStandardOutput = true; var process = Process.Start(processStartInfo); var installationsString = process.StandardOutput.ReadToEnd(); installations = installationsString.Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries).Where(x => !string.IsNullOrWhiteSpace(x)).ToList(); process.WaitForExit(); if (process.ExitCode != 0) { RedirectableConsole.ErrorWriteLine("Unable to locate Visual Studio 2017 and later installations (non-zero exit code from vswhere)"); } } catch (Exception ex) { RedirectableConsole.ErrorWriteLine("Unable to locate Visual Studio 2017 and later installations: " + ex.Message); } } if (installations != null) { // Check if MSBuild is present in any of those installation paths. foreach (var basePath in installations) { var msbuildLocation = Path.Combine(basePath, "MSBuild\\15.0\\Bin\\MSBuild.exe"); if (File.Exists(msbuildLocation)) { builderPathNativeArch = msbuildLocation; extraArgsNativeArch = "/m /nodeReuse:false "; builderPath32 = msbuildLocation; extraArgs32 = "/m /nodeReuse:false "; var x64Location = Path.Combine(basePath, "MSBuild\\15.0\\Bin\\amd64\\MSBuild.exe"); if (File.Exists(x64Location)) { builderPath64 = x64Location; extraArgs64 = "/m /nodeReuse:false "; } break; } } } if (builderPathNativeArch == null) { // Try to find via the registry. foreach (var arch in new[] { RegistryView.Default, RegistryView.Registry32, RegistryView.Registry64 }) { // Find latest version of MSBuild. var registryKey = RegistryKey.OpenBaseKey( RegistryHive.LocalMachine, arch) .OpenSubKey("SOFTWARE")? .OpenSubKey("Microsoft")? .OpenSubKey("MSBuild")? .OpenSubKey("ToolsVersions"); if (registryKey == null) { if (arch == RegistryView.Registry64) { continue; } RedirectableConsole.ErrorWriteLine( "ERROR: No versions of MSBuild were available " + "according to the registry (or they were not readable)."); return(1); } var subkeys = registryKey.GetSubKeyNames(); var orderedVersions = subkeys.OrderByDescending(x => int.Parse(x.Split('.').First(), CultureInfo.InvariantCulture)); var builderPath = (from version in orderedVersions let path = (string)registryKey.OpenSubKey(version)?.GetValue("MSBuildToolsPath") where path != null && Directory.Exists(path) let msbuild = Path.Combine(path, "MSBuild.exe") where File.Exists(msbuild) select msbuild).FirstOrDefault(); if (builderPath == null) { if (arch == RegistryView.Registry64) { continue; } RedirectableConsole.ErrorWriteLine( "ERROR: Unable to find installed MSBuild in any installed tools version."); return(1); } var extraArgs = string.Empty; if (!builderPath.Contains("v2.0.50727")) { extraArgs = "/m /nodeReuse:false "; } switch (arch) { case RegistryView.Default: builderPathNativeArch = builderPath; extraArgsNativeArch = extraArgs; break; case RegistryView.Registry32: builderPath32 = builderPath; extraArgs32 = extraArgs; break; case RegistryView.Registry64: builderPath64 = builderPath; extraArgs64 = extraArgs; break; } } } } else { // Find path to xbuild. var whichPaths = new[] { "/bin/which", "/usr/bin/which" }; // We can only use the new MSBuild tool if no projects are C++ projects on Mac or Linux. var isAnyNativeProject = false; foreach (var def in module.GetDefinitionsRecursively()) { var document = XDocument.Load(def.DefinitionPath); var languageAttr = document?.Root?.Attributes()?.FirstOrDefault(x => x.Name.LocalName == "Language"); if (languageAttr != null && languageAttr.Value == "C++") { isAnyNativeProject = true; break; } } if (!isAnyNativeProject) { foreach (var w in whichPaths) { if (File.Exists(w)) { var whichProcess = Process.Start(new ProcessStartInfo(w, "msbuild") { RedirectStandardOutput = true, UseShellExecute = false }); if (whichProcess == null) { continue; } var result = whichProcess.StandardOutput.ReadToEnd().Trim(); if (!string.IsNullOrWhiteSpace(result) && File.Exists(result)) { builderPathNativeArch = result; break; } } } } if (builderPathNativeArch == null) { foreach (var w in whichPaths) { if (File.Exists(w)) { var whichProcess = Process.Start(new ProcessStartInfo(w, "xbuild") { RedirectStandardOutput = true, UseShellExecute = false }); if (whichProcess == null) { continue; } var result = whichProcess.StandardOutput.ReadToEnd().Trim(); if (!string.IsNullOrWhiteSpace(result) && File.Exists(result)) { builderPathNativeArch = result; break; } } } } if (builderPathNativeArch == null && _hostPlatformDetector.DetectPlatform() == "MacOS" && File.Exists("/usr/local/bin/xbuild")) { // After upgrading to OSX El Capitan, the /usr/local/bin folder is no longer in // the system PATH. If we can't find xbuild with the which tool, manually set the // path here in an attempt to find it. builderPathNativeArch = "/usr/local/bin/xbuild"; } if (builderPathNativeArch == null) { RedirectableConsole.ErrorWriteLine("ERROR: Unable to find msbuild or xbuild on the current PATH."); return(1); } builderPath32 = builderPathNativeArch; builderPath64 = builderPathNativeArch; } if (!string.IsNullOrWhiteSpace(execution.BuildTarget)) { extraArgsGeneral += "/t:\"" + execution.BuildTarget + "\" "; } foreach (var prop in execution.BuildProperties) { extraArgsGeneral += "/p:\"" + prop.Key.Replace("\"", "\\\"") + "\"=\"" + (prop.Value ?? string.Empty).Replace("\"", "\\\"") + "\" "; } switch (execution.BuildProcessArchitecture) { case "x86": RedirectableConsole.WriteLine("INFO: Using " + builderPath32 + " (forced 32-bit) to perform this build."); break; case "x64": RedirectableConsole.WriteLine("INFO: Using " + builderPath64 + " (forced 64-bit) to perform this build."); break; case "Default": default: RedirectableConsole.WriteLine("INFO: Using " + builderPathNativeArch + " (32-bit: " + builderPath32 + ") to perform this build."); break; } foreach (var platform in targetPlatforms) { string builderPath; string extraArgs; switch (execution.BuildProcessArchitecture) { case "x86": builderPath = builderPath32; extraArgs = extraArgs32 + extraArgsGeneral; break; case "x64": builderPath = builderPath64; extraArgs = extraArgs64 + extraArgsGeneral; break; case "Default": default: builderPath = platform == "WindowsPhone" ? builderPath32 : builderPathNativeArch; extraArgs = (platform == "WindowsPhone" ? extraArgs32 : extraArgsNativeArch) + extraArgsGeneral; break; } var fileToBuild = module.Name + "." + platform + ".sln"; RedirectableConsole.WriteLine("INFO: Executing " + builderPath + " with arguments: " + extraArgs + fileToBuild); var process = Process.Start(new ProcessStartInfo(builderPath, extraArgs + fileToBuild) { UseShellExecute = false }); if (process == null) { RedirectableConsole.ErrorWriteLine("ERROR: Build process did not start successfully."); return(1); } process.WaitForExit(); if (process.ExitCode != 0) { return(process.ExitCode); } } return(0); }
public void Resolve(string workingDirectory, IPackageMetadata metadata, PackageRef reference, string templateName, bool?source, bool forceUpgrade, bool?safeResolve) { if (reference.Folder == null) { if (metadata.PackageType == PACKAGE_TYPE_GLOBAL_TOOL) { } else { throw new InvalidOperationException( "No target folder was provided for package resolution, and the resulting package is not " + "a global tool."); } } else { if (metadata.PackageType == PackageManager.PACKAGE_TYPE_TEMPLATE && templateName == null) { throw new InvalidOperationException( "Template referenced as part of module packages. Templates can only be used " + "with the --start option."); } else if (metadata.PackageType == PackageManager.PACKAGE_TYPE_LIBRARY) { Directory.CreateDirectory(Path.Combine(workingDirectory, reference.Folder)); if (new DirectoryInfo(Path.Combine(workingDirectory, reference.Folder)).GetFiles().Length > 0 || new DirectoryInfo(Path.Combine(workingDirectory, reference.Folder)).GetDirectories().Length > 0) { if (!File.Exists(Path.Combine(workingDirectory, reference.Folder, ".git")) && !Directory.Exists(Path.Combine(workingDirectory, reference.Folder, ".git")) && !File.Exists(Path.Combine(workingDirectory, reference.Folder, ".pkg"))) { bool shouldSafeResolve; if (safeResolve.HasValue) { // If the user specifies it on the command line, use that setting. shouldSafeResolve = safeResolve.Value; } else { if (!_featureManager.IsFeatureEnabled(Feature.SafeResolutionDisabled)) { // If the module doesn't have this feature set enabled, we default // to using safe package resolution. shouldSafeResolve = true; } else { // If the module does have this feature set enabled, or is using the // full feature set, we default to turning safe resolution off. shouldSafeResolve = false; } } if (shouldSafeResolve) { RedirectableConsole.ErrorWriteLine( "WARNING: The package directory '" + reference.Folder + "' already exists and contains " + "files and/or subdirectories, but neither a .pkg file nor a .git file or subdirectory exists. " + "This indicates the package directory contains data that is not been instantiated or managed " + "by Protobuild. Since there is no safe way to initialize the package in this directory " + "without a potential loss of data, Protobuild will not modify the contents of this folder " + "during package resolution. If the folder does not contains the required package " + "dependencies, the project generation or build may unexpectedly fail."); return; } } } if (source == null) { if (File.Exists(Path.Combine(workingDirectory, reference.Folder, ".git")) || Directory.Exists(Path.Combine(workingDirectory, reference.Folder, ".git"))) { RedirectableConsole.WriteLine("Git repository present at " + Path.Combine(workingDirectory, reference.Folder, ".git") + "; leaving as source version."); source = true; } else { RedirectableConsole.WriteLine("Package type not specified (and no file at " + Path.Combine(workingDirectory, reference.Folder, ".git") + "), requesting binary version."); source = false; } } } } metadata.Resolve(workingDirectory, metadata, reference.Folder, templateName, forceUpgrade, source); }
/// <summary> /// Generates a project at the target path. /// </summary> /// <param name="current">The current project to generate.</param> /// <param name="definitions">A list of all loaded project definitions.</param> /// <param name="workingDirectory"></param> /// <param name="rootPath">The module root path, with directory seperator appended.</param> /// <param name="projectName">The project name.</param> /// <param name="platformName">The platform name.</param> /// <param name="services">A list of services.</param> /// <param name="packagesFilePath"> /// Either the full path to the packages.config for the /// generated project if it exists, or an empty string. /// </param> /// <param name="onActualGeneration"></param> /// <param name="debugProjectGeneration">Whether to emit a .input file for XSLT debugging.</param> public void Generate( DefinitionInfo current, List <LoadedDefinitionInfo> definitions, string workingDirectory, string rootPath, string projectName, string platformName, List <Service> services, out string packagesFilePath, Action onActualGeneration, bool debugProjectGeneration) { packagesFilePath = string.Empty; // Work out what document this is. var projectDoc = definitions.First( x => x.Project.DocumentElement.Attributes["Name"].Value == projectName)?.Project; // Check to see if we have a Project node; don't process it. if (projectDoc?.DocumentElement == null) { return; } // If this is a custom project, run any custom generation commands for // the current host and target platform. if (projectDoc.DocumentElement.Name == "CustomProject") { onActualGeneration(); var onGenerateElements = projectDoc.DocumentElement.SelectNodes("OnGenerate"); if (onGenerateElements != null) { foreach (var onGenerateElement in onGenerateElements.OfType <XmlElement>()) { var matches = true; var hostName = onGenerateElement.GetAttribute("HostName"); var targetName = onGenerateElement.GetAttribute("TargetName"); if (!string.IsNullOrWhiteSpace(hostName)) { if (hostName != _hostPlatformDetector.DetectPlatform()) { matches = false; } } if (!string.IsNullOrWhiteSpace(targetName)) { if (targetName != platformName) { matches = false; } } if (matches) { var command = onGenerateElement.SelectSingleNode("Command")?.InnerText.Trim(); var arguments = onGenerateElement.SelectSingleNode("Arguments")?.InnerText.Trim() ?? string.Empty; if (!string.IsNullOrWhiteSpace(command)) { var workingPath = Path.Combine( rootPath, projectDoc.DocumentElement.Attributes["Path"].Value); var resolvedCommandPath = Path.Combine( workingPath, command); if (File.Exists(resolvedCommandPath)) { var process = Process.Start(new ProcessStartInfo(resolvedCommandPath, arguments) { WorkingDirectory = workingPath, UseShellExecute = false }); if (process == null) { RedirectableConsole.ErrorWriteLine("ERROR: Process did not start when running " + resolvedCommandPath + " " + arguments); ExecEnvironment.Exit(1); return; } process.WaitForExit(); if (process.ExitCode != 0) { RedirectableConsole.ErrorWriteLine( "ERROR: Non-zero exit code " + process.ExitCode); ExecEnvironment.Exit(1); return; } } } } } } } // If this is not a normal project at this point, don't process it. if (projectDoc.DocumentElement.Name != "Project") { return; } // Load the appropriate project transformation XSLT. var languageAttribute = projectDoc.DocumentElement.Attributes["Language"]; var languageText = languageAttribute != null ? languageAttribute.Value : "C#"; var language = this.m_LanguageStringProvider.GetLanguageFromConfigurationName(languageText); var projectTransform = this.m_ResourceProvider.LoadXSLT(workingDirectory, ResourceType.GenerateProject, language, platformName); // Work out what platforms this project should be generated for. var platformAttribute = projectDoc.DocumentElement.Attributes["Platforms"]; string[] allowedPlatforms = null; if (platformAttribute != null) { allowedPlatforms = platformAttribute.Value .Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries) .Select(x => x.Trim()) .ToArray(); } // Filter on allowed platforms. if (allowedPlatforms != null) { var allowed = false; foreach (var platform in allowedPlatforms) { if (string.Compare(platformName, platform, StringComparison.InvariantCultureIgnoreCase) == 0) { allowed = true; break; } } if (!allowed) { return; } } // If the project has a <Services> node, but there are no entries in /Input/Services, // then nothing depends on this service (if there is a <Reference> to this project, it will // use the default service). So for service-aware projects without any services being // referenced, we exclude them from the generation. if (this.m_ExcludedServiceAwareProjectDetector.IsExcludedServiceAwareProject( projectDoc.DocumentElement.Attributes["Name"].Value, projectDoc, services)) { return; } // Inform the user we're generating this project. onActualGeneration(); // Add include projects if they have an AppliesTo tag that matches this project's name. this._includeProjectAppliesToUpdater.UpdateProjectReferences(definitions.Select(x => x.Project).ToList(), projectDoc); // Add references and properties from include projects. _includeProjectMerger.MergeInReferencesAndPropertiesForIncludeProjects(definitions, projectDoc, platformName); // Imply external project references from other external projects. We do // this so that external projects can reference other external projects (which // we can't reasonably handle at the XSLT level since it's recursive). this.m_ExternalProjectReferenceResolver.ResolveExternalProjectReferences(definitions, projectDoc, platformName); // Generate Info.plist files if necessary (for Mac / iOS). this._mPlatformResourcesGenerator.GenerateInfoPListIfNeeded(definitions, current, projectDoc, platformName); // Work out what path to save at. var path = Path.Combine( rootPath, projectDoc.DocumentElement.Attributes["Path"].Value .Replace('\\', Path.DirectorySeparatorChar) .Replace('/', Path.DirectorySeparatorChar), projectDoc.DocumentElement.Attributes["Name"].Value + "." + platformName + "." + this.m_LanguageStringProvider.GetProjectExtension(language)); // Make sure that the directory exists where the file will be stored. var targetFile = new FileInfo(path); if (!targetFile.Directory.Exists) { targetFile.Directory.Create(); } path = targetFile.FullName; // Handle NuGet packages.config early so that it'll be in place // when the generator automatically determined dependencies. this.m_NuGetConfigMover.Move(rootPath, platformName, projectDoc); // Work out what path the NuGet packages.config might be at. var packagesFile = new FileInfo( Path.Combine( rootPath, projectDoc.DocumentElement.Attributes["Path"].Value .Replace('\\', Path.DirectorySeparatorChar) .Replace('/', Path.DirectorySeparatorChar), "packages.config")); // Generate the input document. var input = this.m_ProjectInputGenerator.Generate( definitions.Select(x => x.Project).ToList(), workingDirectory, rootPath, projectName, platformName, packagesFile.FullName, projectDoc.DocumentElement.ChildNodes .OfType <XmlElement>() .Where(x => x.Name.ToLower() == "properties") .SelectMany(x => x.ChildNodes .OfType <XmlElement>()), services); var settings = new XmlWriterSettings(); settings.Indent = true; if (debugProjectGeneration) { using (var writer = XmlWriter.Create(path + ".input", settings)) { input.Save(writer); } } // Transform the input document using the XSLT transform. using (var writer = XmlWriter.Create(path, settings)) { projectTransform.Transform(input, writer); } // Also remove any left over .sln or .userprefs files. var slnPath = Path.Combine( rootPath, projectDoc.DocumentElement.Attributes["Path"].Value, projectDoc.DocumentElement.Attributes["Name"].Value + "." + platformName + ".sln"); var userprefsPath = Path.Combine( rootPath, projectDoc.DocumentElement.Attributes["Path"].Value, projectDoc.DocumentElement.Attributes["Name"].Value + "." + platformName + ".userprefs"); if (File.Exists(slnPath)) { File.Delete(slnPath); } if (File.Exists(userprefsPath)) { File.Delete(userprefsPath); } // Only return the package file path if it exists. if (packagesFile.Exists) { packagesFilePath = packagesFile.FullName; } }
public Tuple <int, string, string> RunProtobuild(ModuleInfo module, string args, bool capture = false) { var invokeInline = false; var myHash = ExecEnvironment.GetProgramHash(); var targetHash = ExecEnvironment.GetProgramHash(Path.Combine(module.Path, "Protobuild.exe")); if (myHash == targetHash) { invokeInline = true; } if (ExecEnvironment.RunProtobuildInProcess || invokeInline) { var oldBuffer = RedirectableConsole.TargetBuffer; var ourBuffer = new RedirectableBuffer(); RedirectableConsole.TargetBuffer = ourBuffer; var needsEndSelfInvoke = true; try { var exitCode = ExecEnvironment.InvokeSelf(module.Path, args.SplitCommandLine().ToArray()); RedirectableConsole.TargetBuffer = oldBuffer; needsEndSelfInvoke = false; if (capture) { return(new Tuple <int, string, string>( exitCode, ourBuffer.Stdout, ourBuffer.Stderr)); } else { return(new Tuple <int, string, string>( exitCode, string.Empty, string.Empty)); } } finally { if (needsEndSelfInvoke) { RedirectableConsole.TargetBuffer = oldBuffer; } } } var protobuildPath = Path.Combine(module.Path, "Protobuild.exe"); try { var chmodStartInfo = new ProcessStartInfo { FileName = "chmod", Arguments = "a+x Protobuild.exe", WorkingDirectory = module.Path, CreateNoWindow = capture, UseShellExecute = false }; Process.Start(chmodStartInfo); } catch (ExecEnvironment.SelfInvokeExitException) { throw; } catch { } var stdout = string.Empty; var stderr = string.Empty; for (var attempt = 0; attempt < 3; attempt++) { if (File.Exists(protobuildPath)) { var pi = new ProcessStartInfo { FileName = protobuildPath, Arguments = args, WorkingDirectory = module.Path, CreateNoWindow = capture, RedirectStandardError = capture, RedirectStandardInput = capture, RedirectStandardOutput = capture, UseShellExecute = false }; var p = new Process { StartInfo = pi }; if (capture) { p.OutputDataReceived += (sender, eventArgs) => { if (!string.IsNullOrEmpty(eventArgs.Data)) { if (capture) { stdout += eventArgs.Data + "\n"; } else { RedirectableConsole.WriteLine(eventArgs.Data); } } }; p.ErrorDataReceived += (sender, eventArgs) => { if (!string.IsNullOrEmpty(eventArgs.Data)) { if (capture) { stderr += eventArgs.Data + "\n"; } else { RedirectableConsole.ErrorWriteLine(eventArgs.Data); } } }; } try { p.Start(); } catch (System.ComponentModel.Win32Exception ex) { if (ex.Message.Contains("Cannot find the specified file")) { // Mono sometimes throws this error even though the // file does exist on disk. The best guess is there's // a race condition between performing chmod on the // file and Mono actually seeing it as an executable file. // Show a warning and sleep for a bit before retrying. if (attempt != 2) { RedirectableConsole.WriteLine("WARNING: Unable to execute Protobuild.exe, will retry again..."); System.Threading.Thread.Sleep(2000); continue; } else { RedirectableConsole.WriteLine("ERROR: Still unable to execute Protobuild.exe."); throw; } } } if (capture) { p.BeginOutputReadLine(); p.BeginErrorReadLine(); } p.WaitForExit(); return(new Tuple <int, string, string>(p.ExitCode, stdout, stderr)); } } return(new Tuple <int, string, string>(1, string.Empty, string.Empty)); }
public int Execute(string workingDirectory, object handle) { var instructions = (List <ParsedInstruction>)handle; var protobuild = Assembly.GetEntryAssembly().Location; var targets = string.Empty; var buildTarget = string.Empty; var buildProcessArch = string.Empty; var buildProperties = new Dictionary <string, string>(); string executeConfiguration = null; string packageFormat = null; var predicates = new Stack <ParsedInstruction>(); foreach (var inst in instructions) { if (inst.Predicate != null) { predicates.Push(inst); } else if (inst.EndPredicate) { predicates.Pop(); } else if (predicates.All(x => x.Predicate())) { if (inst.Command == "native-execute") { var components = inst.Arguments.Split(new[] { ' ' }, 2); string path; try { path = FindNativeProgram(components[0]); } catch (ApplicationException ex) { RedirectableConsole.ErrorWriteLine(ex); return(1); } var args = components.Length == 2 ? components[1] : string.Empty; RedirectableConsole.WriteLine("+ native-execute " + path + " " + args); var process = Process.Start(new ProcessStartInfo(path, args) { WorkingDirectory = workingDirectory, UseShellExecute = false }); if (process == null) { RedirectableConsole.ErrorWriteLine("ERROR: Process did not start when running " + path + " " + args); return(1); } process.WaitForExit(); if (process.ExitCode != 0) { RedirectableConsole.ErrorWriteLine( "ERROR: Non-zero exit code " + process.ExitCode); return(process.ExitCode); } } else if (inst.Command == "nuget") { // See if we have a copy of NuGet available for use. var cachedNuget = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "NuGet.exe"); if (!File.Exists(cachedNuget)) { var client = new RetryableWebClient(); client.DownloadFile("https://dist.nuget.org/win-x86-commandline/latest/nuget.exe", cachedNuget); } string runtime = null; var hostPlatform = _hostPlatformDetector.DetectPlatform(); if (hostPlatform != "Windows") { try { runtime = FindNativeProgram("mono"); } catch (ApplicationException ex) { RedirectableConsole.ErrorWriteLine(ex); return(1); } } Process process; if (hostPlatform != "Windows" && runtime != null) { RedirectableConsole.WriteLine("+ " + runtime + " \"" + cachedNuget + "\" " + inst.Arguments); process = Process.Start(new ProcessStartInfo(runtime, "\"" + cachedNuget + "\" " + inst.Arguments) { WorkingDirectory = workingDirectory, UseShellExecute = false }); } else { RedirectableConsole.WriteLine("+ " + cachedNuget + " " + inst.Arguments); process = Process.Start(new ProcessStartInfo(cachedNuget, inst.Arguments) { WorkingDirectory = workingDirectory, UseShellExecute = false }); } if (process == null) { RedirectableConsole.ErrorWriteLine( "ERROR: Process did not start when running NuGet with arguments " + inst.Arguments); return(1); } process.WaitForExit(); if (process.ExitCode != 0) { RedirectableConsole.ErrorWriteLine( "ERROR: Non-zero exit code " + process.ExitCode); return(process.ExitCode); } } else if (inst.Command != null) { var args = string.Empty; switch (inst.Command) { case "execute": if (executeConfiguration != null) { args = "--execute-configuration " + executeConfiguration + " --" + inst.Command + " " + inst.Arguments; } else { args = "--" + inst.Command + " " + inst.Arguments; } break; case "build": args = "--" + inst.Command + " " + targets + " "; if (buildTarget != string.Empty) { args += "--build-target " + buildTarget + " "; } if (buildProcessArch != string.Empty) { args += "--build-process-arch " + buildProcessArch + " "; } args = buildProperties.Aggregate(args, (current, prop) => current + ("--build-property " + prop.Key + " " + prop.Value + " ")); args += " " + inst.Arguments; break; case "pack": case "push": case "repush": args = string.Empty; if (!string.IsNullOrWhiteSpace(packageFormat)) { args = "--format " + packageFormat + " "; } args += "--" + inst.Command + " " + inst.Arguments; break; default: args = "--" + inst.Command + " " + targets + " " + inst.Arguments; break; } var runSets = new List <string>(); if (args.Contains("$TARGET_PLATFORM")) { var targetsSplit = targets.Split(','); if (targetsSplit.Length < 1 || string.IsNullOrWhiteSpace(targetsSplit[0])) { runSets.Add(_hostPlatformDetector.DetectPlatform()); } else { runSets.AddRange(targetsSplit); } } else { runSets.Add(_hostPlatformDetector.DetectPlatform()); } if (args.Contains("$GIT_BRANCH")) { RedirectableConsole.ErrorWriteLine( "ERROR: Support for $GIT_BRANCH has been dropped, because it almost never behaved as intended (due to no guarentees that the desired refs would exist in the repository being operated on)."); return(1); } if (args.Contains("$GIT_COMMIT") || inst.Command == "pack") { string commit; try { RedirectableConsole.WriteLine("+ git rev-parse HEAD"); commit = GitUtils.RunGitAndCapture(workingDirectory, null, "rev-parse HEAD").Trim(); } catch (InvalidOperationException) { commit = string.Empty; } if (inst.Command == "pack" && !string.IsNullOrWhiteSpace(commit)) { args = "--package-git-commit " + commit + " " + args; } args = args.Replace("$GIT_COMMIT", commit); } string runtime = null; var hostPlatform = _hostPlatformDetector.DetectPlatform(); if (hostPlatform != "Windows") { try { runtime = FindNativeProgram("mono"); } catch (ApplicationException ex) { RedirectableConsole.ErrorWriteLine(ex); return(1); } } foreach (var run in runSets) { var runArgs = args .Replace("$TARGET_PLATFORM", run); Process process; if (hostPlatform != "Windows" && runtime != null) { RedirectableConsole.WriteLine("+ " + runtime + " \"" + protobuild + "\" " + runArgs); process = Process.Start(new ProcessStartInfo(runtime, "\"" + protobuild + "\" " + runArgs) { WorkingDirectory = workingDirectory, UseShellExecute = false }); } else { RedirectableConsole.WriteLine("+ " + protobuild + " " + runArgs); process = Process.Start(new ProcessStartInfo(protobuild, runArgs) { WorkingDirectory = workingDirectory, UseShellExecute = false }); } if (process == null) { RedirectableConsole.ErrorWriteLine( "ERROR: Process did not start when running Protobuild with arguments " + args); return(1); } process.WaitForExit(); if (process.ExitCode != 0) { RedirectableConsole.ErrorWriteLine( "ERROR: Non-zero exit code " + process.ExitCode); return(process.ExitCode); } } } else if (inst.Key != null) { RedirectableConsole.WriteLine("+ set " + inst.Key + " -> " + inst.Values.Aggregate((a, b) => a + ", " + b)); switch (inst.Key) { case "target-platforms": targets = inst.Values.Aggregate((a, b) => a + "," + b); break; case "build-target": buildTarget = inst.Values.First(); break; case "build-process-arch": buildProcessArch = inst.Values.First(); break; case "build-property": buildProperties.Add(inst.Values[0], inst.Values.Length >= 2 ? inst.Values[1] : string.Empty); break; case "execute-configuration": executeConfiguration = inst.Values.First(); break; case "package-format": packageFormat = inst.Values.First(); break; } } else if (inst.Echo != null) { RedirectableConsole.WriteLine(inst.Echo); } } } RedirectableConsole.WriteLine("Automated build script completed successfully."); return(0); }
/// <summary> /// Performs a resynchronisation, synchronisation, generation or clean on the specified module. /// </summary> /// <returns><c>true</c>, if the action succeeded, <c>false</c> otherwise.</returns> /// <param name="module">The module to perform the action on.</param> /// <param name="action">The action to perform, either "resync", "sync", "generate" or "clean".</param> /// <param name="platform">The platform to perform the action for.</param> /// <param name="enabledServices">A list of enabled services.</param> /// <param name="disabledServices">A list of disabled services.</param> /// <param name="serviceSpecPath">The service specification path.</param> /// <param name="debugServiceResolution">Whether to enable debugging information during service resolution.</param> /// <param name="disablePackageResolution">Whether to disable package resolution.</param> /// <param name="disableHostPlatformGeneration">Whether to disable generation of the host platform projects.</param> /// <param name="taskParallelisation">Whether to enable or disable task generation, or null for the default behaviour.</param> public bool PerformAction( string workingDirectory, ModuleInfo module, string action, string platform, string[] enabledServices, string[] disabledServices, string serviceSpecPath, bool debugServiceResolution, bool disablePackageResolution, bool disableHostPlatformGeneration, bool?taskParallelisation, bool?safeResolve, bool debugProjectGeneration) { var platformSupplied = !string.IsNullOrWhiteSpace(platform); var hostPlatform = this.m_HostPlatformDetector.DetectPlatform(); if (string.IsNullOrWhiteSpace(platform)) { platform = hostPlatform; } var originalPlatform = platform; string primaryPlatform = null; string multiplePlatforms = null; if (platform.Contains(",")) { // The user requested multiple platforms; the first one // is the primary platform. var platforms = platform.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); if (platforms.Length == 0) { RedirectableConsole.ErrorWriteLine("You supplied only commas where a list of platforms was expected."); ExecEnvironment.Exit(1); return(false); } else { for (var i = 0; i < platforms.Length; i++) { var newPlatform = _moduleUtilities.NormalizePlatform(module, platforms[i]); if (newPlatform == null) { ShowSupportedPlatformsError(module, platforms[i]); return(false); } platforms[i] = newPlatform; } primaryPlatform = platforms[0]; multiplePlatforms = platforms.Aggregate((a, b) => a + "," + b); } } else { platform = _moduleUtilities.NormalizePlatform(module, platform); if (platform == null && !platformSupplied) { // The current host platform isn't supported, so we shouldn't try to // operate on it. string firstPlatform = null; switch (this.m_HostPlatformDetector.DetectPlatform()) { case "Windows": firstPlatform = module.DefaultWindowsPlatforms.Split(',').FirstOrDefault(); break; case "MacOS": firstPlatform = module.DefaultMacOSPlatforms.Split(',').FirstOrDefault(); break; case "Linux": firstPlatform = module.DefaultLinuxPlatforms.Split(',').FirstOrDefault(); break; } if (firstPlatform != null) { // This will end up null if the first platform isn't supported // either and hence throw the right message. platform = _moduleUtilities.NormalizePlatform(module, firstPlatform); } } if (platform == null) { ShowSupportedPlatformsError(module, originalPlatform); return(false); } primaryPlatform = platform; } // You can generate multiple targets by default by setting the <DefaultWindowsPlatforms> // <DefaultMacOSPlatforms> and <DefaultLinuxPlatforms> tags in Module.xml. Note that // synchronisation will only be done for the primary platform, as there is no correct // synchronisation behaviour when dealing with multiple C# projects. // // We only trigger this behaviour when the platform is omitted; if you explicitly // specify "Windows" on the command line, we'll only generate / resync / sync // the Windows platform. if (!platformSupplied) { switch (platform) { case "Windows": multiplePlatforms = module.DefaultWindowsPlatforms; break; case "MacOS": multiplePlatforms = module.DefaultMacOSPlatforms; break; case "Linux": multiplePlatforms = module.DefaultLinuxPlatforms; break; } } // If no overrides are set, just use the current platform. if (string.IsNullOrEmpty(multiplePlatforms)) { multiplePlatforms = platform; } // If running pure synchronisation or a project clean, we don't need to perform // package resolution. if (action.ToLower() == "sync" || action.ToLower() == "clean") { disablePackageResolution = true; } // Resolve submodules as needed. if (!disablePackageResolution) { this.m_PackageManager.ResolveAll(workingDirectory, module, primaryPlatform, taskParallelisation, false, safeResolve); } // Create the list of multiple platforms. var multiplePlatformsList = multiplePlatforms.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(x => x.Trim()).ToList(); // Remember whether or not we need to implicitly generate the host // platform. var implicitlyGenerateHostPlatform = false; Action requiresHostPlatform = () => implicitlyGenerateHostPlatform = true; // If we are already generating the host platform, then requiring the // host platform is already satisifed. if (platform == hostPlatform || multiplePlatformsList.Contains(hostPlatform)) { requiresHostPlatform = () => {}; } else if (!_featureManager.IsFeatureEnabled(Feature.HostPlatformGeneration)) { requiresHostPlatform = () => { RedirectableConsole.ErrorWriteLine( "WARNING: One or more projects requires host platforms to be generated, " + "but the HostPlatformGeneration feature is not enabled. Expect your " + "build to fail."); }; } // You can configure the default action for Protobuild in their project // with the <DefaultAction> tag in Module.xml. If omitted, default to a resync. // Valid options for this tag are either "Generate", "Resync" or "Sync". // If the actions are "Resync" or "Sync", then we need to perform an initial // step against the primary platform. switch (action.ToLower()) { case "generate": if (!this.GenerateProjectsForPlatform( workingDirectory, module, primaryPlatform, enabledServices, disabledServices, serviceSpecPath, debugServiceResolution, disablePackageResolution, disableHostPlatformGeneration, requiresHostPlatform, debugProjectGeneration)) { return(false); } break; case "resync": if (!this.ResyncProjectsForPlatform( workingDirectory, module, primaryPlatform, enabledServices, disabledServices, serviceSpecPath, debugServiceResolution, disablePackageResolution, disableHostPlatformGeneration, requiresHostPlatform, debugProjectGeneration)) { return(false); } break; case "sync": return(this.SyncProjectsForPlatform(module, primaryPlatform)); case "clean": if (!this.CleanProjectsForPlatform(module, primaryPlatform)) { return(false); } break; default: RedirectableConsole.ErrorWriteLine("Unknown option in <DefaultAction> tag of Module.xml. Defaulting to resync!"); return(this.ResyncProjectsForPlatform( workingDirectory, module, primaryPlatform, enabledServices, disabledServices, serviceSpecPath, debugServiceResolution, disablePackageResolution, disableHostPlatformGeneration, requiresHostPlatform, debugProjectGeneration)); } // Now iterate through the multiple platforms specified. foreach (var platformIter in multiplePlatformsList.Distinct()) { if (platformIter == primaryPlatform) { // Already handled above. continue; } // Resolve submodules as needed. if (!disablePackageResolution) { this.m_PackageManager.ResolveAll(workingDirectory, module, platformIter, taskParallelisation, false, safeResolve); } switch (action.ToLower()) { case "generate": case "resync": // We do a generate under resync mode since we only want the primary platform // to have synchronisation done (and it has had above). if (!this.GenerateProjectsForPlatform( workingDirectory, module, platformIter, enabledServices, disabledServices, serviceSpecPath, debugServiceResolution, disablePackageResolution, disableHostPlatformGeneration, requiresHostPlatform, debugProjectGeneration)) { return(false); } break; case "clean": if (!this.CleanProjectsForPlatform(module, platformIter)) { return(false); } break; default: throw new InvalidOperationException("Code should never reach this point"); } } // If we implicitly require the host platform, generate that now (this variable can // only ever be set to true if the host platform is not already in the list of // platforms generated previously). if (implicitlyGenerateHostPlatform) { // Check to see if the host platform is supported. var hostPlatformNormalized = _moduleUtilities.NormalizePlatform(module, hostPlatform); if (hostPlatformNormalized == null) { RedirectableConsole.WriteLine( "WARNING: The current host platform is not a supported platform for the solution. IDE editor " + "projects and post-build hooks will not be available, and this may cause the project to be " + "built incorrectly!"); return(true); } RedirectableConsole.WriteLine( "One or more projects required the presence of host platform " + "projects, implicitly starting generation for " + hostPlatform + "..."); // Resolve submodules as needed. if (!disablePackageResolution) { this.m_PackageManager.ResolveAll(workingDirectory, module, hostPlatform, taskParallelisation, false, safeResolve); } switch (action.ToLower()) { case "generate": case "resync": // We do a generate under resync mode since we only want the primary platform // to have synchronisation done (and it has had above). if (!this.GenerateProjectsForPlatform( workingDirectory, module, hostPlatform, enabledServices, disabledServices, serviceSpecPath, debugServiceResolution, disablePackageResolution, disableHostPlatformGeneration, requiresHostPlatform, debugProjectGeneration)) { return(false); } break; case "clean": if (!this.CleanProjectsForPlatform(module, hostPlatform)) { return(false); } break; default: throw new InvalidOperationException("Code should never reach this point"); } } // All the steps succeeded, so return true. return(true); }
private void InstallVSIXIntoVisualStudio(string vsixPath, IKnownToolProvider knownToolProvider) { // This installation technique is for pre-2017 editions of Visual Studio. // We don't list 10.0 and 11.0 because they don't support all editions (you should // use GAC based installation for these editions instead). var vsVersions = new[] { "12.0", "14.0" }; var editionRegistryKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32) ?.OpenSubKey("SOFTWARE") ?.OpenSubKey("Microsoft") ?.OpenSubKey("VisualStudio"); if (editionRegistryKey != null) { foreach (var version in vsVersions) { var installPath = (string)editionRegistryKey?.OpenSubKey(version)?.GetValue("InstallDir"); if (installPath != null) { var vsixInstallerPath = Path.Combine(installPath, "VSIXInstaller.exe"); if (Directory.Exists(installPath)) { if (File.Exists(vsixInstallerPath)) { try { RedirectableConsole.WriteLine("Installing VSIX into Visual Studio " + version + "..."); var processStartInfo = new ProcessStartInfo(); processStartInfo.FileName = vsixInstallerPath; processStartInfo.Arguments = "/q \"" + vsixPath + "\""; processStartInfo.UseShellExecute = false; var process = Process.Start(processStartInfo); process.WaitForExit(); if (process.ExitCode != 0) { RedirectableConsole.ErrorWriteLine("VSIX installation failed for Visual Studio " + version + " (non-zero exit code)"); } else { RedirectableConsole.WriteLine("VSIX installation completed successfully for Visual Studio " + version); } } catch (Exception ex) { RedirectableConsole.ErrorWriteLine("Failed to install VSIX for Visual Studio " + version + ": " + ex.Message); } } else { RedirectableConsole.WriteLine("Visual Studio " + version + " does not provide VSIXInstaller.exe (checked for existance of " + vsixInstallerPath + ")."); } } else { RedirectableConsole.WriteLine("Visual Studio " + version + " is not installed (checked for existance of " + installPath + ")."); } } } } // Now try and install in all editions of Visual Studio 2017 and later. This // may install the vswhere global tool. var vswhere = knownToolProvider.GetToolExecutablePath("vswhere"); List <string> installations = null; RedirectableConsole.WriteLine("Locating installations of Visual Studio 2017 and later..."); try { var processStartInfo = new ProcessStartInfo(); processStartInfo.FileName = vswhere; processStartInfo.Arguments = "-products * -property installationPath"; processStartInfo.UseShellExecute = false; processStartInfo.RedirectStandardOutput = true; var process = Process.Start(processStartInfo); var installationsString = process.StandardOutput.ReadToEnd(); installations = installationsString.Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries).Where(x => !string.IsNullOrWhiteSpace(x)).ToList(); process.WaitForExit(); if (process.ExitCode != 0) { RedirectableConsole.ErrorWriteLine("Unable to locate Visual Studio 2017 and later installations (non-zero exit code from vswhere)"); } } catch (Exception ex) { RedirectableConsole.ErrorWriteLine("Unable to locate Visual Studio 2017 and later installations: " + ex.Message); } if (installations != null) { foreach (var installPath in installations) { var vsixInstallerPath = Path.Combine(installPath, "Common7", "IDE", "VSIXInstaller.exe"); if (Directory.Exists(installPath)) { if (File.Exists(vsixInstallerPath)) { try { RedirectableConsole.WriteLine("Installing VSIX into " + installPath + "..."); var processStartInfo = new ProcessStartInfo(); processStartInfo.FileName = vsixInstallerPath; processStartInfo.Arguments = "/q \"" + vsixPath + "\""; processStartInfo.UseShellExecute = false; var process = Process.Start(processStartInfo); process.WaitForExit(); if (process.ExitCode != 0) { RedirectableConsole.ErrorWriteLine("VSIX installation failed for " + installPath + " (non-zero exit code)"); } else { RedirectableConsole.WriteLine("VSIX installation completed successfully for " + installPath); } } catch (Exception ex) { RedirectableConsole.ErrorWriteLine("Failed to install VSIX for " + installPath + ": " + ex.Message); } } else { RedirectableConsole.WriteLine("Visual Studio at " + installPath + " does not provide VSIXInstaller.exe (checked for existance of " + vsixInstallerPath + ")."); } } else { RedirectableConsole.WriteLine("Visual Studio at " + installPath + " is not installed (checked for existance of " + installPath + ")."); } } } }
private async Task <int> PushNuGetBinaryAsync(string targetUri, string apiKey, MemoryStream file, bool ignoreOnExisting) { byte[] fileBytes; fileBytes = new byte[(int)file.Length]; file.Read(fileBytes, 0, fileBytes.Length); const string ApiKeyHeader = "X-NuGet-ApiKey"; var boundary = Guid.NewGuid().ToString(); byte[] boundaryBytes = Encoding.UTF8.GetBytes("--" + boundary + "\r\n"); byte[] trailer = Encoding.UTF8.GetBytes("\r\n--" + boundary + "--\r\n"); byte[] header = Encoding.UTF8.GetBytes( string.Format( "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\";\r\nContent-Type: {2}\r\n\r\n", "package", "package.nupkg", "application/octet-stream")); var requestLength = boundaryBytes.Length + header.Length + trailer.Length + fileBytes.Length; var combinedContent = new byte[requestLength]; if (combinedContent == null) { throw new InvalidOperationException("Unable to create byte array " + requestLength + " bytes long for upload!"); } boundaryBytes.CopyTo(combinedContent, 0); header.CopyTo(combinedContent, boundaryBytes.Length); fileBytes.CopyTo(combinedContent, boundaryBytes.Length + header.Length); trailer.CopyTo(combinedContent, boundaryBytes.Length + header.Length + fileBytes.Length); using (var client = new RetryableWebClient()) { var done = false; byte[] result = null; Exception ex = null; var uploadProgressRenderer = new UploadProgressRenderer(); client.UploadDataCompleted += (sender, e) => { if (e.Error != null) { ex = e.Error; } try { result = e.Result; } catch { } done = true; }; client.UploadProgressChanged += (sender, e) => { if (!done) { uploadProgressRenderer.Update(e.ProgressPercentage, e.BytesSent / 1024); } }; client.SetHeader("Content-Type", "multipart/form-data; boundary=\"" + boundary + "\""); if (!string.IsNullOrWhiteSpace(apiKey)) { client.SetHeader(ApiKeyHeader, apiKey); } client.SetHeader("X-NuGet-Protocol-Version", "4.1.0"); client.SetHeader("User-Agent", "Protobuild"); client.UploadDataAsync(new Uri(targetUri), "PUT", combinedContent); while (!done) { System.Threading.Thread.Sleep(0); } uploadProgressRenderer.FinalizeRendering(); if (ex != null) { var webException = ex as WebException; if (webException != null) { var httpResponse = webException.Response as HttpWebResponse; if (httpResponse != null) { RedirectableConsole.ErrorWriteLine(httpResponse.StatusDescription); if (httpResponse.StatusCode == HttpStatusCode.Conflict) { if (ignoreOnExisting) { // This is okay - the user doesn't care if there's an existing package with the same version. return(0); } else { return(1); } } return(1); } } else { throw new InvalidOperationException("Upload error", ex); } } if (result != null) { var resultDecoded = Encoding.UTF8.GetString(result); if (!string.IsNullOrWhiteSpace(resultDecoded)) { RedirectableConsole.WriteLine(Encoding.UTF8.GetString(result)); } else { RedirectableConsole.WriteLine("Package uploaded successfully"); } } else { RedirectableConsole.WriteLine("Package uploaded successfully"); } return(0); } }
public int Execute(Execution execution) { using (var client = new RetryableWebClient()) { var sourcePackage = _packageUrlParser.Parse(execution.PackageUrl); RedirectableConsole.WriteLine("Retrieving source package..."); var metadata = _packageLookup.Lookup(execution.WorkingDirectory, new PackageRequestRef( sourcePackage.Uri, sourcePackage.GitRef, execution.PackagePushPlatform, true, sourcePackage.IsStaticReference)); if (metadata.GetProtobuildPackageBinary == null) { RedirectableConsole.ErrorWriteLine( "ERROR: URL resolved to a package metadata type '" + metadata.GetType().Name + "', " + "but this type doesn't provide a mechanism to convert to a Protobuild package."); } string archiveType; byte[] archiveData; metadata.GetProtobuildPackageBinary(metadata, out archiveType, out archiveData); var protobuildPackageMetadata = metadata as ProtobuildPackageMetadata; if (protobuildPackageMetadata == null) { RedirectableConsole.ErrorWriteLine("--repush requires that the source URL resolve to a Protobuild package"); return(1); } RedirectableConsole.WriteLine("Detected package type as " + archiveType + "."); if (execution.PackagePushVersion.StartsWith("hash:", StringComparison.InvariantCulture)) { var sha1 = new SHA1Managed(); var hashed = sha1.ComputeHash(Encoding.ASCII.GetBytes(execution.PackagePushVersion.Substring("hash:".Length))); execution.PackagePushVersion = BitConverter.ToString(hashed).ToLowerInvariant().Replace("-", ""); } RedirectableConsole.WriteLine("Creating new package version..."); var uploadParameters = new System.Collections.Specialized.NameValueCollection { { "__apikey__", execution.PackagePushApiKey }, { "version", execution.PackagePushVersion }, { "platform", execution.PackagePushPlatform }, }; var json = fastJSON.JSON.ToDynamic( System.Text.Encoding.ASCII.GetString( client.UploadValues(execution.PackagePushUrl + "/version/new/api", uploadParameters))); if (json.has_error) { RedirectableConsole.WriteLine(json.error); return(1); } var uploadTarget = (string)json.result.uploadUrl; var finalizeTarget = (string)json.result.finalizeUrl; RedirectableConsole.WriteLine("Uploading package..."); this.PushBinary(uploadTarget, archiveData); RedirectableConsole.WriteLine("Finalizing package version..."); var finalizeParameters = new System.Collections.Specialized.NameValueCollection { { "__apikey__", execution.PackagePushApiKey }, { "archiveType", archiveType }, }; json = fastJSON.JSON.ToDynamic( System.Text.Encoding.ASCII.GetString( client.UploadValues(finalizeTarget, finalizeParameters))); if (json.has_error) { RedirectableConsole.WriteLine(json.error); return(1); } if (execution.PackagePushBranchToUpdate != null) { RedirectableConsole.WriteLine("Updating branch " + execution.PackagePushBranchToUpdate + " to point at new version..."); var branchUpdateParameters = new System.Collections.Specialized.NameValueCollection { { "__apikey__", execution.PackagePushApiKey }, { "name", execution.PackagePushBranchToUpdate }, { "git", execution.PackagePushVersion }, }; json = fastJSON.JSON.ToDynamic( System.Text.Encoding.ASCII.GetString( client.UploadValues( execution.PackagePushUrl + "/branch/edit/" + execution.PackagePushBranchToUpdate + "/api", branchUpdateParameters))); if (json.has_error) { RedirectableConsole.WriteLine(json.error); return(1); } } RedirectableConsole.WriteLine("Package version repushed successfully."); } return(0); }
private static ModuleInfo LoadInternal(XDocument doc, string modulePath, Func <ModuleInfo> fallback) { var def = new ModuleInfo(); var xsi = doc.Root == null ? null : doc.Root.Attribute(XName.Get("xsi", "http://www.w3.org/2000/xmlns/")); if (xsi != null && xsi.Value == "http://www.w3.org/2001/XMLSchema-instance") { return(fallback()); } Func <string, string> getStringValue = name => { if (doc.Root == null) { return(null); } var elem = doc.Root.Element(XName.Get(name)); if (elem == null) { return(null); } return(elem.Value); }; def.Name = getStringValue("Name"); def.Authors = getStringValue("Authors"); def.Description = getStringValue("Description"); def.ProjectUrl = getStringValue("ProjectUrl"); def.LicenseUrl = getStringValue("LicenseUrl"); def.IconUrl = getStringValue("IconUrl"); def.GitRepositoryUrl = getStringValue("GitRepositoryUrl"); def.SemanticVersion = getStringValue("SemanticVersion"); def.Path = modulePath; def.DefaultAction = getStringValue("DefaultAction"); def.DefaultLinuxPlatforms = getStringValue("DefaultLinuxPlatforms"); def.DefaultMacOSPlatforms = getStringValue("DefaultMacOSPlatforms"); def.DefaultWindowsPlatforms = getStringValue("DefaultWindowsPlatforms"); def.DefaultStartupProject = getStringValue("DefaultStartupProject"); def.SupportedPlatforms = getStringValue("SupportedPlatforms"); def.DisableSynchronisation = getStringValue("DisableSynchronisation") == "true"; def.GenerateNuGetRepositories = getStringValue("GenerateNuGetRepositories") == "true"; def.Packages = new List <PackageRef>(); if (doc.Root != null) { var packagesElem = doc.Root.Element(XName.Get("Packages")); if (packagesElem != null) { var packages = packagesElem.Elements(); foreach (var package in packages) { var folder = package.Attribute(XName.Get("Folder"))?.Value; var gitRef = package.Attribute(XName.Get("GitRef"))?.Value; var uri = package.Attribute(XName.Get("Uri"))?.Value; var repository = package.Attribute(XName.Get("Repository"))?.Value; var packageName = package.Attribute(XName.Get("Package"))?.Value; var version = package.Attribute(XName.Get("Version"))?.Value; if (!string.IsNullOrWhiteSpace(repository) && !string.IsNullOrWhiteSpace(packageName) && !string.IsNullOrWhiteSpace(version)) { // This is NuGet v3 package. Rather than writing a different interface, // we just automatically form a URI that complies with the rest of the // package resolution system. uri = repository; if (!string.IsNullOrWhiteSpace(uri)) { uri = uri.Replace("https://", "https-nuget-v3://"); uri = uri.Replace("http://", "http-nuget-v3://"); uri += $"|{packageName}"; } gitRef = version; } if (string.IsNullOrWhiteSpace(folder) && !string.IsNullOrWhiteSpace(packageName)) { folder = packageName; } if (string.IsNullOrWhiteSpace(folder) || string.IsNullOrWhiteSpace(gitRef) || string.IsNullOrWhiteSpace(uri)) { RedirectableConsole.ErrorWriteLine("WARNING: Invalid package declaration in module; skipping package."); continue; } var packageRef = new PackageRef { Folder = folder, GitRef = gitRef, Uri = uri, Platforms = null, }; var platforms = package.Attribute(XName.Get("Platforms")); var platformsArray = platforms?.Value.Split(','); if (platformsArray?.Length > 0) { packageRef.Platforms = platformsArray; } def.Packages.Add(packageRef); } } var featureSetElem = doc.Root.Element(XName.Get("FeatureSet")); if (featureSetElem != null) { def.FeatureSet = new List <Feature>(); var features = featureSetElem.Elements(); foreach (var feature in features) { try { def.FeatureSet.Add((Feature)Enum.Parse(typeof(Feature), feature.Value)); } catch { RedirectableConsole.ErrorWriteLine("Unknown feature in Module.xml; ignoring: " + feature.Value); } } } else { def.FeatureSet = null; } // Check if the feature set is present and if it does not contain // the PackageManagement feature. If that feature isn't there, we // ignore any of the data in Packages and just set the value to // an empty list. if (def.FeatureSet != null && !def.FeatureSet.Contains(Feature.PackageManagement)) { def.Packages.Clear(); } } return(def); }