Example #1
0
        /// <summary>
        /// Add a project to to the cache.
        /// </summary>
        /// <param name="project">project to add to the cache.</param>
        /// <returns>The project name of the added project.</returns>
        public ProjectName AddProject(Project project)
        {
            // First create a project name from the project
            var projectName = new ProjectName(project);

            // Do nothing if we already have an entry
            if (_projectCache.ContainsKey(projectName)) {
                return projectName;
            }

            AddShortName(projectName);

            _projectNamesCache[projectName.CustomUniqueName] = projectName;
            _projectNamesCache[projectName.UniqueName] = projectName;
            _projectNamesCache[projectName.FullName] = projectName;

            // Add the entry mapping project name to the actual project
            _projectCache[projectName] = project;

            return projectName;
        }
        protected override void ProcessRecord()
        {
            var baseResourceList = new List <VariableSetResource>();
            var variableSetIDs   = new List <string>();

            var projectList            = new List <ProjectResource>();
            var libraryVariableSetList = new List <LibraryVariableSetResource>();

            var librarySetNameList = LibrarySetName?.ToList().ConvertAll(s => s.ToLower());

            var projectNameList = ProjectName?.ToList().ConvertAll(s => s.ToLower());

            //If no Project and Library set is declared, return all the things.
            if (projectNameList == null && librarySetNameList == null)
            {
                projectList.AddRange(_connection.Repository.Projects.FindAll());
                libraryVariableSetList.AddRange(_connection.Repository.LibraryVariableSets.FindAll());
            }

            //If at least 1 project or Library variable set is defined, then just return that list instead of everything.
            else
            {
                #region Getting projects
                //Getting variable set ids from projects

                if (projectNameList != null)
                {
                    //Multiple values but one of them is wildcarded, which is not an accepted scenario (I.e -MachineName WebServer*, Database1)
                    if (projectNameList.Any(item => WildcardPattern.ContainsWildcardCharacters(item) && projectNameList.Count > 1))
                    {
                        throw OctoposhExceptions.ParameterCollectionHasRegularAndWildcardItem("ProjectName");
                    }
                    //Only 1 wildcarded value (ie -MachineName WebServer*)
                    else if (projectNameList.Any(item => WildcardPattern.ContainsWildcardCharacters(item) && projectNameList.Count == 1))
                    {
                        var pattern = new WildcardPattern(projectNameList.First());
                        projectList.AddRange(_connection.Repository.Projects.FindMany(t => pattern.IsMatch(t.Name.ToLower())));
                    }
                    //multiple non-wildcared values (i.e. -MachineName WebServer1,Database1)
                    else if (!projectNameList.Any(WildcardPattern.ContainsWildcardCharacters))
                    {
                        projectList.AddRange(_connection.Repository.Projects.FindMany(t => projectNameList.Contains(t.Name.ToLower())));
                    }
                }
                #endregion

                #region Getting Library variable sets
                if (librarySetNameList != null)
                {
                    //Getting variable set ids from LibraryVariableSets

                    //Multiple values but one of them is wildcarded, which is not an accepted scenario (I.e -MachineName WebServer*, Database1)
                    if (librarySetNameList.Any(item => WildcardPattern.ContainsWildcardCharacters(item) && librarySetNameList.Count > 1))
                    {
                        throw OctoposhExceptions.ParameterCollectionHasRegularAndWildcardItem("LibrarySetName");
                    }
                    //Only 1 wildcarded value (ie -MachineName WebServer*)
                    else if (librarySetNameList.Any(item => WildcardPattern.ContainsWildcardCharacters(item) && librarySetNameList.Count == 1))
                    {
                        var pattern = new WildcardPattern(librarySetNameList.First());
                        libraryVariableSetList.AddRange(_connection.Repository.LibraryVariableSets.FindMany(t => pattern.IsMatch(t.Name.ToLower())));
                    }
                    //multiple non-wildcared values (i.e. -MachineName WebServer1,Database1)
                    else if (!librarySetNameList.Any(WildcardPattern.ContainsWildcardCharacters))
                    {
                        libraryVariableSetList.AddRange(_connection.Repository.LibraryVariableSets.FindMany(t => librarySetNameList.Contains(t.Name.ToLower())));
                    }
                }
                #endregion
            }

            variableSetIDs.AddRange(libraryVariableSetList.Select(v => v.VariableSetId));
            variableSetIDs.AddRange(projectList.Select(p => p.VariableSetId));

            //This works
            foreach (var id in variableSetIDs)
            {
                baseResourceList.Add(_connection.Repository.VariableSets.Get(id));
            }

            //This doesn't work and throws: [Exception thrown: 'Octopus.Client.Exceptions.OctopusResourceNotFoundException' in Octopus.Client.dll]
            //Github issue for this https://github.com/OctopusDeploy/Issues/issues/3307
            //baseResourceList.AddRange(_connection.Repository.VariableSets.Get(variableSetIDs.ToArray()));

            if (ResourceOnly)
            {
                if (baseResourceList.Count == 1)
                {
                    WriteObject(baseResourceList.FirstOrDefault(), true);
                }
                else
                {
                    WriteObject(baseResourceList, true);
                }
            }

            else
            {
                var converter  = new OutputConverter();
                var outputList = converter.GetOctopusVariableSet(baseResourceList, projectList, libraryVariableSetList, IncludeUsage);

                if (outputList.Count == 1)
                {
                    WriteObject(outputList.FirstOrDefault(), true);
                }
                else
                {
                    WriteObject(outputList, true);
                }
            }
        }
Example #3
0
        public SolutionProject(object solutionProject, string rootPath)
        {
            ProjectName  = Info["ProjectName"].GetValue(solutionProject, null) as string;
            RelativePath = Info["RelativePath"].GetValue(solutionProject, null) as string;
            ProjectGuid  = Info["ProjectGuid"].GetValue(solutionProject, null) as string;

            var projectFile = Path.Combine(rootPath, RelativePath);

            //if (!projectFile.ToLower().EndsWith(".csproj") && Directory.Exists(projectFile))
            //projectFile = Directory.GetFiles(projectFile, "*.csproj", SearchOption.TopDirectoryOnly).FirstOrDefault();
            if (/*projectFile != null &&*/ File.Exists(projectFile) &&
                !Path.GetExtension(projectFile).StartsWith(".wix", StringComparison.InvariantCultureIgnoreCase) &&
                Path.GetExtension(projectFile).EndsWith("proj", StringComparison.InvariantCultureIgnoreCase))
            {
                var        xml = XDocument.Load(projectFile);
                XNamespace ns  = xml.Root.Attribute("xmlns").Value;
                OutputType = xml
                             .Element(ns + "Project")
                             .Element(ns + "PropertyGroup")
                             .Element(ns + "OutputType").Value;
                OutputPath = xml.Descendants(ns + "OutputPath").First(x => x.Parent.Attribute("Condition").Value.Contains("'$(Configuration)|$(Platform)' == 'Release|AnyCPU'")).Value.TrimEnd('\\');
                var projectFolder = Path.GetDirectoryName(projectFile);

                // web app?
                if (File.Exists(Path.Combine(projectFolder, "web.config")))
                {
                    OutputClass = OutputClass.WebDeploy;
                }

                // nsb?
                else if (File.Exists(Path.Combine(projectFolder, "app.config")) &&
                         ProjectName != null && OutputType == "Library" &&
                         (!ProjectName.ToLower().Contains(".test")) &&
                         (ProjectName.ToLower().Contains(".nsb") || ProjectName.ToLower().Contains(".endpoint")))
                {
                    OutputClass = OutputClass.NServiceBus;
                }

                // win svc?
                else if (File.Exists(Path.Combine(projectFolder, "app.config")) &&
                         File.Exists(Path.Combine(projectFolder, "program.cs")) &&
                         File.ReadAllText(Path.Combine(projectFolder, "program.cs")).Contains("ServiceBase.Run"))
                {
                    OutputClass = OutputClass.WindowsService;
                }
            }
            if (ProjectName != null)
            {
                switch (OutputClass)
                {
                case OutputClass.NServiceBus:
                case OutputClass.WindowsService:
                    Artifact = new Artifact(ProjectName, Path.Combine("Source", Path.GetDirectoryName(RelativePath), OutputPath), OutputClass);
                    break;

                case OutputClass.WebDeploy:
                    Artifact = new Artifact(ProjectName, Path.Combine("WebDeploy", ProjectName), OutputClass);
                    break;

                default:
                    Artifact = null;
                    break;
                }
            }
            else
            {
                Artifact = null;
            }
        }
    public override void ExecuteBuild()
    {
        var UEProjectRoot = ParseParamValue("UEProjectRoot");

        if (UEProjectRoot == null)
        {
            UEProjectRoot = CmdEnv.LocalRoot;
        }

        var UEProjectDirectory = ParseParamValue("UEProjectDirectory");

        if (UEProjectDirectory == null)
        {
            throw new AutomationException("Missing required command line argument: 'UEProjectDirectory'");
        }

        var UEProjectName = ParseParamValue("UEProjectName");

        if (UEProjectName == null)
        {
            UEProjectName = "";
        }

        var LocalizationProjectNames = new List <string>();
        {
            var LocalizationProjectNamesStr = ParseParamValue("LocalizationProjectNames");
            if (LocalizationProjectNamesStr != null)
            {
                foreach (var ProjectName in LocalizationProjectNamesStr.Split(','))
                {
                    LocalizationProjectNames.Add(ProjectName.Trim());
                }
            }
        }

        var LocalizationProviderName = ParseParamValue("LocalizationProvider");

        if (LocalizationProviderName == null)
        {
            LocalizationProviderName = "";
        }

        var LocalizationStepNames = new List <string>();
        {
            var LocalizationStepNamesStr = ParseParamValue("LocalizationSteps");
            if (LocalizationStepNamesStr == null)
            {
                LocalizationStepNames.AddRange(new string[] { "Download", "Gather", "Import", "Export", "Compile", "GenerateReports", "Upload" });
            }
            else
            {
                foreach (var StepName in LocalizationStepNamesStr.Split(','))
                {
                    LocalizationStepNames.Add(StepName.Trim());
                }
            }
            LocalizationStepNames.Add("Monolithic");             // Always allow the monolithic scripts to run as we don't know which steps they do
        }

        var ShouldGatherPlugins = ParseParam("IncludePlugins");
        var IncludePlugins      = new List <string>();
        var ExcludePlugins      = new List <string>();

        if (ShouldGatherPlugins)
        {
            var IncludePluginsStr = ParseParamValue("IncludePlugins");
            if (IncludePluginsStr != null)
            {
                foreach (var PluginName in IncludePluginsStr.Split(','))
                {
                    IncludePlugins.Add(PluginName.Trim());
                }
            }

            var ExcludePluginsStr = ParseParamValue("ExcludePlugins");
            if (ExcludePluginsStr != null)
            {
                foreach (var PluginName in ExcludePluginsStr.Split(','))
                {
                    ExcludePlugins.Add(PluginName.Trim());
                }
            }
        }

        var ShouldGatherPlatforms = ParseParam("IncludePlatforms");

        var AdditionalCommandletArguments = ParseParamValue("AdditionalCommandletArguments");

        if (AdditionalCommandletArguments == null)
        {
            AdditionalCommandletArguments = "";
        }

        var EnableParallelGather = ParseParam("ParallelGather");

        var StartTime = DateTime.UtcNow;

        var LocalizationBatches = new List <LocalizationBatch>();

        // Add the static set of localization projects as a batch
        if (LocalizationProjectNames.Count > 0)
        {
            LocalizationBatches.Add(new LocalizationBatch(UEProjectDirectory, UEProjectDirectory, "", LocalizationProjectNames));
        }

        // Build up any additional batches needed for platforms
        if (ShouldGatherPlatforms)
        {
            var PlatformsRootDirectory = new DirectoryReference(CombinePaths(UEProjectRoot, UEProjectDirectory, "Platforms"));
            if (DirectoryReference.Exists(PlatformsRootDirectory))
            {
                foreach (DirectoryReference PlatformDirectory in DirectoryReference.EnumerateDirectories(PlatformsRootDirectory))
                {
                    // Find the localization targets defined for this platform
                    var PlatformTargetNames = GetLocalizationTargetsFromDirectory(new DirectoryReference(CombinePaths(PlatformDirectory.FullName, "Config", "Localization")));
                    if (PlatformTargetNames.Count > 0)
                    {
                        var RootRelativePluginPath = PlatformDirectory.MakeRelativeTo(new DirectoryReference(UEProjectRoot));
                        RootRelativePluginPath = RootRelativePluginPath.Replace('\\', '/');                         // Make sure we use / as these paths are used with P4

                        LocalizationBatches.Add(new LocalizationBatch(UEProjectDirectory, RootRelativePluginPath, "", PlatformTargetNames));
                    }
                }
            }
        }

        // Build up any additional batches needed for plugins
        if (ShouldGatherPlugins)
        {
            var PluginsRootDirectory = new DirectoryReference(CombinePaths(UEProjectRoot, UEProjectDirectory));
            IReadOnlyList <PluginInfo> AllPlugins = Plugins.ReadPluginsFromDirectory(PluginsRootDirectory, "Plugins", UEProjectName.Length == 0 ? PluginType.Engine : PluginType.Project);

            // Add a batch for each plugin that meets our criteria
            var AvailablePluginNames = new HashSet <string>();
            foreach (var PluginInfo in AllPlugins)
            {
                AvailablePluginNames.Add(PluginInfo.Name);

                bool ShouldIncludePlugin = (IncludePlugins.Count == 0 || IncludePlugins.Contains(PluginInfo.Name)) && !ExcludePlugins.Contains(PluginInfo.Name);
                if (ShouldIncludePlugin && PluginInfo.Descriptor.LocalizationTargets != null && PluginInfo.Descriptor.LocalizationTargets.Length > 0)
                {
                    var RootRelativePluginPath = PluginInfo.Directory.MakeRelativeTo(new DirectoryReference(UEProjectRoot));
                    RootRelativePluginPath = RootRelativePluginPath.Replace('\\', '/');                     // Make sure we use / as these paths are used with P4

                    var PluginTargetNames = new List <string>();
                    foreach (var LocalizationTarget in PluginInfo.Descriptor.LocalizationTargets)
                    {
                        PluginTargetNames.Add(LocalizationTarget.Name);
                    }

                    LocalizationBatches.Add(new LocalizationBatch(UEProjectDirectory, RootRelativePluginPath, PluginInfo.Name, PluginTargetNames));
                }
            }

            // If we had an explicit list of plugins to include, warn if any were missing
            foreach (string PluginName in IncludePlugins)
            {
                if (!AvailablePluginNames.Contains(PluginName))
                {
                    LogWarning("The plugin '{0}' specified by -IncludePlugins wasn't found and will be skipped.", PluginName);
                }
            }
        }

        // Create a single changelist to use for all changes
        int PendingChangeList = 0;

        if (P4Enabled)
        {
            var ChangeListCommitMessage = String.Format("Localization Automation using CL {0}", P4Env.Changelist);
            if (File.Exists(CombinePaths(CmdEnv.LocalRoot, @"Engine/Build/NotForLicensees/EpicInternal.txt")))
            {
                ChangeListCommitMessage += "\n#okforgithub ignore";
            }

            PendingChangeList = P4.CreateChange(P4Env.Client, ChangeListCommitMessage);
        }

        // Prepare to process each localization batch
        var LocalizationTasks = new List <LocalizationTask>();

        foreach (var LocalizationBatch in LocalizationBatches)
        {
            var LocalizationTask = new LocalizationTask(LocalizationBatch, UEProjectRoot, LocalizationProviderName, PendingChangeList, this);
            LocalizationTasks.Add(LocalizationTask);

            // Make sure the Localization configs and content is up-to-date to ensure we don't get errors later on
            if (P4Enabled)
            {
                LogInformation("Sync necessary content to head revision");
                P4.Sync(P4Env.Branch + "/" + LocalizationTask.Batch.LocalizationTargetDirectory + "/Config/Localization/...");
                P4.Sync(P4Env.Branch + "/" + LocalizationTask.Batch.LocalizationTargetDirectory + "/Content/Localization/...");
            }

            // Generate the info we need to gather for each project
            foreach (var ProjectName in LocalizationTask.Batch.LocalizationProjectNames)
            {
                LocalizationTask.ProjectInfos.Add(GenerateProjectInfo(LocalizationTask.RootLocalizationTargetDirectory, ProjectName, LocalizationStepNames));
            }
        }

        // Hash the current PO files on disk so we can work out whether they actually change
        Dictionary <string, byte[]> InitalPOFileHashes = null;

        if (P4Enabled)
        {
            InitalPOFileHashes = GetPOFileHashes(LocalizationBatches, UEProjectRoot);
        }

        // Download the latest translations from our localization provider
        if (LocalizationStepNames.Contains("Download"))
        {
            foreach (var LocalizationTask in LocalizationTasks)
            {
                if (LocalizationTask.LocProvider != null)
                {
                    foreach (var ProjectInfo in LocalizationTask.ProjectInfos)
                    {
                        LocalizationTask.LocProvider.DownloadProjectFromLocalizationProvider(ProjectInfo.ProjectName, ProjectInfo.ImportInfo);
                    }
                }
            }
        }

        // Begin the gather command for each task
        // These can run in parallel when ParallelGather is enabled
        {
            var EditorExe = CombinePaths(CmdEnv.LocalRoot, @"Engine/Binaries/Win64/UE4Editor-Cmd.exe");

            // Set the common basic editor arguments
            var EditorArguments = P4Enabled
                                ? String.Format("-SCCProvider=Perforce -P4Port={0} -P4User={1} -P4Client={2} -P4Passwd={3} -P4Changelist={4} -EnableSCC -DisableSCCSubmit", P4Env.ServerAndPort, P4Env.User, P4Env.Client, P4.GetAuthenticationToken(), PendingChangeList)
                                : "-SCCProvider=None";
            if (IsBuildMachine)
            {
                EditorArguments += " -BuildMachine";
            }
            EditorArguments += " -Unattended -LogLocalizationConflicts";
            if (EnableParallelGather)
            {
                EditorArguments += " -multiprocess";
            }
            if (!String.IsNullOrEmpty(AdditionalCommandletArguments))
            {
                EditorArguments += " " + AdditionalCommandletArguments;
            }

            // Set the common process run options
            var CommandletRunOptions = ERunOptions.Default | ERunOptions.NoLoggingOfRunCommand;             // Disable logging of the run command as it will print the exit code which GUBP can pick up as an error (we do that ourselves later)
            if (EnableParallelGather)
            {
                CommandletRunOptions |= ERunOptions.NoWaitForExit;
            }

            foreach (var LocalizationTask in LocalizationTasks)
            {
                var ProjectArgument = String.IsNullOrEmpty(UEProjectName) ? "" : String.Format("\"{0}\"", Path.Combine(LocalizationTask.RootWorkingDirectory, String.Format("{0}.uproject", UEProjectName)));

                foreach (var ProjectInfo in LocalizationTask.ProjectInfos)
                {
                    var LocalizationConfigFiles = new List <string>();
                    foreach (var LocalizationStep in ProjectInfo.LocalizationSteps)
                    {
                        if (LocalizationStepNames.Contains(LocalizationStep.Name))
                        {
                            LocalizationConfigFiles.Add(LocalizationStep.LocalizationConfigFile);
                        }
                    }

                    if (LocalizationConfigFiles.Count > 0)
                    {
                        var Arguments = String.Format("{0} -run=GatherText -config=\"{1}\" {2}", ProjectArgument, String.Join(";", LocalizationConfigFiles), EditorArguments);
                        LogInformation("Running localization commandlet for '{0}': {1}", ProjectInfo.ProjectName, Arguments);
                        LocalizationTask.GatherProcessResults.Add(Run(EditorExe, Arguments, null, CommandletRunOptions));
                    }
                    else
                    {
                        LocalizationTask.GatherProcessResults.Add(null);
                    }
                }
            }
        }

        // Wait for each commandlet process to finish and report the result.
        // This runs even for non-parallel execution to log the exit state of the process.
        foreach (var LocalizationTask in LocalizationTasks)
        {
            for (int ProjectIndex = 0; ProjectIndex < LocalizationTask.ProjectInfos.Count; ++ProjectIndex)
            {
                var ProjectInfo = LocalizationTask.ProjectInfos[ProjectIndex];
                var RunResult   = LocalizationTask.GatherProcessResults[ProjectIndex];

                if (RunResult != null)
                {
                    RunResult.WaitForExit();
                    RunResult.OnProcessExited();
                    RunResult.DisposeProcess();

                    if (RunResult.ExitCode == 0)
                    {
                        LogInformation("The localization commandlet for '{0}' exited with code 0.", ProjectInfo.ProjectName);
                    }
                    else
                    {
                        LogWarning("The localization commandlet for '{0}' exited with code {1} which likely indicates a crash.", ProjectInfo.ProjectName, RunResult.ExitCode);
                    }
                }
            }
        }

        // Upload the latest sources to our localization provider
        if (LocalizationStepNames.Contains("Upload"))
        {
            foreach (var LocalizationTask in LocalizationTasks)
            {
                if (LocalizationTask.LocProvider != null)
                {
                    // Upload all text to our localization provider
                    for (int ProjectIndex = 0; ProjectIndex < LocalizationTask.ProjectInfos.Count; ++ProjectIndex)
                    {
                        var ProjectInfo = LocalizationTask.ProjectInfos[ProjectIndex];
                        var RunResult   = LocalizationTask.GatherProcessResults[ProjectIndex];

                        if (RunResult != null && RunResult.ExitCode == 0)
                        {
                            // Recalculate the split platform paths before doing the upload, as the export may have changed them
                            ProjectInfo.ExportInfo.CalculateSplitPlatformNames(LocalizationTask.RootLocalizationTargetDirectory);
                            LocalizationTask.LocProvider.UploadProjectToLocalizationProvider(ProjectInfo.ProjectName, ProjectInfo.ExportInfo);
                        }
                        else
                        {
                            LogWarning("Skipping upload to the localization provider for '{0}' due to an earlier commandlet failure.", ProjectInfo.ProjectName);
                        }
                    }
                }
            }
        }

        // Clean-up the changelist so it only contains the changed files, and then submit it (if we were asked to)
        if (P4Enabled)
        {
            // Revert any PO files that haven't changed aside from their header
            {
                var POFilesToRevert = new List <string>();

                var CurrentPOFileHashes = GetPOFileHashes(LocalizationBatches, UEProjectRoot);
                foreach (var CurrentPOFileHashPair in CurrentPOFileHashes)
                {
                    byte[] InitialPOFileHash;
                    if (InitalPOFileHashes.TryGetValue(CurrentPOFileHashPair.Key, out InitialPOFileHash) && InitialPOFileHash.SequenceEqual(CurrentPOFileHashPair.Value))
                    {
                        POFilesToRevert.Add(CurrentPOFileHashPair.Key);
                    }
                }

                if (POFilesToRevert.Count > 0)
                {
                    var P4RevertArgsFilename = CombinePaths(CmdEnv.LocalRoot, "Engine", "Intermediate", String.Format("LocalizationP4RevertArgs-{0}.txt", Guid.NewGuid().ToString()));

                    using (StreamWriter P4RevertArgsWriter = File.CreateText(P4RevertArgsFilename))
                    {
                        foreach (var POFileToRevert in POFilesToRevert)
                        {
                            P4RevertArgsWriter.WriteLine(POFileToRevert);
                        }
                    }

                    P4.LogP4(String.Format("-x{0} revert", P4RevertArgsFilename));
                    DeleteFile_NoExceptions(P4RevertArgsFilename);
                }
            }

            // Revert any other unchanged files
            P4.RevertUnchanged(PendingChangeList);

            // Submit that single changelist now
            if (AllowSubmit)
            {
                int SubmittedChangeList;
                P4.Submit(PendingChangeList, out SubmittedChangeList);
            }
        }

        var RunDuration = (DateTime.UtcNow - StartTime).TotalMilliseconds;

        LogInformation("Localize command finished in {0} seconds", RunDuration / 1000);
    }
Example #5
0
        public string GetWorkingDirectory()
        {
            string localDirectory = null;

            try
            {
                Workspace[] workspaces = Source.VersionControlServer.QueryWorkspaces(null, Source.VersionControlServer.AuthorizedUser, Environment.MachineName);

                foreach (Workspace workspace in workspaces)
                {
                    WorkingFolder workingFolder = workspace.Folders.FirstOrDefault(f => f.ServerItem.ToLower() == "$/" + ProjectName.ToLower());

                    if (workingFolder != null)
                    {
                        if (!workspace.Comment.Equals("Workspace created by team build", StringComparison.InvariantCultureIgnoreCase))
                        {
                            localDirectory = workingFolder.LocalItem;
                        }
                    }
                }

                if (localDirectory == null)
                {
                    throw new Exception(
                              "You do not have a local working folder with this project's source code on your computer.\n\n" +
                              "Use Team Explorer in Visual Studio or the tf.exe console application to map a working folder and get the source code."
                              );
                }
            }
            catch (Exception ex)
            {
                throw new Exception(string.Format("Error connecting to TFS. Error was:\n\n{0}", ex.GetBaseException().Message));
            }

            return(localDirectory);
        }
Example #6
0
 public CreateProjectCommand(UserId userId, ProjectId projectId, ProjectName name) : base(userId)
 {
     ProjectId = projectId;
     Name      = name;
 }
Example #7
0
        public void Overview()
        {
            DateTime startTime    = DateTime.UtcNow;
            string   projectId    = _fixture.ProjectId;
            string   logId        = _fixture.LogId + $"-{Guid.NewGuid()}";
            string   fileName     = "log4net.xml";
            string   resourceName = typeof(GoogleStackdriverAppenderSnippets).Namespace + ".log4net-template.xml";

            string xml;

            using (var stream = typeof(GoogleStackdriverAppenderSnippets).GetTypeInfo().Assembly
                                .GetManifestResourceStream(resourceName))
            {
                using (var reader = new StreamReader(stream))
                {
                    xml = reader.ReadToEnd();
                }
            }
            xml = xml.Replace("PROJECT_ID", projectId).Replace("LOG_ID", logId);
            Assert.False(File.Exists(fileName), "Test would overwrite existing file");
            File.WriteAllText(fileName, xml);

            try
            {
                // Resource: log4net-template.xml log4net_template
                // Sample: Overview
                // Configure log4net to use Google Stackdriver logging from the XML configuration file.
                XmlConfigurator.Configure(LogManager.GetRepository(GetType().GetTypeInfo().Assembly), new FileInfo("log4net.xml"));

                // Retrieve a logger for this context.
                ILog log = LogManager.GetLogger(typeof(Program));
                // Log some information. This log entry will be sent to Google Stackdriver Logging.
                log.Info("An exciting log entry!");

                // Flush buffered log entries before program exit.
                // This is required because log entries are buffered locally before being sent to StackDriver.
                // LogManager.Flush() only works in the full .NET framework (not in .NET Core):
                bool flushCompleted = LogManager.Flush(10_000);
                // On .NET Core, the specific repository needs to be flushed:
                bool repositoryFlushCompleted = ((IFlushable)LogManager.GetRepository(GetType().GetTypeInfo().Assembly)).Flush(10_000);
                // End sample

                Assert.True(repositoryFlushCompleted);

                var logClient = LoggingServiceV2Client.Create();
                var logName   = LogName.FromProjectLog(projectId, logId);

                string formattedTime = XmlConvert.ToString(startTime.AddMinutes(-3), XmlDateTimeSerializationMode.Utc);
                string filter        = $"timestamp >= \"{formattedTime}\" AND logName=\"{logName}\" AND \"An exciting log entry!\"";

                // Wait up to 30 seconds for the log entry to appear in StackDriver.
                for (int i = 0; i < 30; i++)
                {
                    var logEntry = logClient.ListLogEntries(
                        resourceNames: new[] { ProjectName.FromProject(projectId) },
                        filter: filter,
                        orderBy: "timestamp desc")
                                   .FirstOrDefault();
                    if (logEntry != null)
                    {
                        Assert.Contains("An exciting log entry!", logEntry.TextPayload);
                        return;
                    }
                    Thread.Sleep(1_000);
                }
                Assert.False(true, "Log entry failed to appear in StackDriver.");
            }
            finally
            {
                File.Delete(fileName);
            }
        }
Example #8
0
        /// <summary>
        /// Adds an entry to the short name cache returning any conflicting project name.
        /// </summary>
        /// <returns>The first conflicting short name.</returns>
        private void AddShortName(ProjectName projectName)
        {
            HashSet<ProjectName> projectNames;
            if (!_shortNameCache.TryGetValue(projectName.ShortName, out projectNames)) {
                projectNames = new HashSet<ProjectName>();
                _shortNameCache.Add(projectName.ShortName, projectNames);
            }

            projectNames.Add(projectName);
        }
Example #9
0
 internal ConnectionBuilder SetProjectDatabase(ProjectName selectedProject)
 {
     _currentProjectName = selectedProject;
     return(ConnBuilder = GetDefaultConnection(_currentProjectName));
 }
Example #10
0
    public override bool Execute()
    {
        bool isDevice = (TargetOS == TargetNames.iOS || TargetOS == TargetNames.tvOS);

        if (!string.IsNullOrEmpty(MainLibraryFileName))
        {
            if (!File.Exists(Path.Combine(AppDir, MainLibraryFileName)))
            {
                throw new ArgumentException($"MainLibraryFileName='{MainLibraryFileName}' was not found in AppDir='{AppDir}'");
            }
        }

        if (ProjectName.Contains(' '))
        {
            throw new ArgumentException($"ProjectName='{ProjectName}' should not contain spaces");
        }

        string[] excludes = Array.Empty <string>();
        if (ExcludeFromAppDir != null)
        {
            excludes = ExcludeFromAppDir
                       .Where(i => !string.IsNullOrEmpty(i.ItemSpec))
                       .Select(i => i.ItemSpec)
                       .ToArray();
        }

        string binDir = Path.Combine(AppDir, $"bin-{ProjectName}-{Arch}");

        if (!string.IsNullOrEmpty(OutputDirectory))
        {
            binDir = OutputDirectory;
        }
        Directory.CreateDirectory(binDir);

        var assemblerFiles       = new List <string>();
        var assemblerFilesToLink = new List <string>();

        foreach (ITaskItem file in Assemblies)
        {
            // use AOT files if available
            var obj     = file.GetMetadata("AssemblerFile");
            var llvmObj = file.GetMetadata("LlvmObjectFile");
            if (!string.IsNullOrEmpty(obj))
            {
                assemblerFiles.Add(obj);
            }

            if (!string.IsNullOrEmpty(llvmObj))
            {
                assemblerFilesToLink.Add(llvmObj);
            }
        }

        if (((!ForceInterpreter && (isDevice || ForceAOT)) && !assemblerFiles.Any()))
        {
            throw new InvalidOperationException("Need list of AOT files for device builds.");
        }

        if (!string.IsNullOrEmpty(DiagnosticPorts))
        {
            bool validDiagnosticsConfig = false;

            if (string.IsNullOrEmpty(RuntimeComponents))
            {
                validDiagnosticsConfig = false;
            }
            else if (RuntimeComponents.Equals("*", StringComparison.OrdinalIgnoreCase))
            {
                validDiagnosticsConfig = true;
            }
            else if (RuntimeComponents.Contains("diagnostics_tracing", StringComparison.OrdinalIgnoreCase))
            {
                validDiagnosticsConfig = true;
            }

            if (!validDiagnosticsConfig)
            {
                throw new ArgumentException("Using DiagnosticPorts require diagnostics_tracing runtime component.");
            }
        }

        if (EnableAppSandbox && (string.IsNullOrEmpty(DevTeamProvisioning) || DevTeamProvisioning == "-"))
        {
            throw new ArgumentException("DevTeamProvisioning must be set to a valid value when App Sandbox is enabled, using '-' is not supported.");
        }

        var generator = new Xcode(Log, TargetOS, Arch);

        if (GenerateXcodeProject)
        {
            XcodeProjectPath = generator.GenerateXCode(ProjectName, MainLibraryFileName, assemblerFiles, assemblerFilesToLink,
                                                       AppDir, binDir, MonoRuntimeHeaders, !isDevice, UseConsoleUITemplate, ForceAOT, ForceInterpreter, InvariantGlobalization, Optimized, EnableRuntimeLogging, EnableAppSandbox, DiagnosticPorts, RuntimeComponents, NativeMainSource);

            if (BuildAppBundle)
            {
                if (isDevice && string.IsNullOrEmpty(DevTeamProvisioning))
                {
                    // DevTeamProvisioning shouldn't be empty for arm64 builds
                    Log.LogMessage(MessageImportance.High, "DevTeamProvisioning is not set, BuildAppBundle step is skipped.");
                }
                else
                {
                    AppBundlePath = generator.BuildAppBundle(XcodeProjectPath, Optimized, DevTeamProvisioning);
                }
            }
        }
        else if (GenerateCMakeProject)
        {
            generator.GenerateCMake(ProjectName, MainLibraryFileName, assemblerFiles, assemblerFilesToLink,
                                    AppDir, binDir, MonoRuntimeHeaders, !isDevice, UseConsoleUITemplate, ForceAOT, ForceInterpreter, InvariantGlobalization, Optimized, EnableRuntimeLogging, EnableAppSandbox, DiagnosticPorts, RuntimeComponents, NativeMainSource);
        }

        return(true);
    }
        /// <summary>
        /// Given a platform, a build config, and true/false for client, returns the path to the binary for that config. E.g.
        /// Win64, Shipping, false = Binaries\Win64\FooServer-Win64-Shipping.exe
        /// </summary>
        /// <param name="TargetPlatform"></param>
        /// <param name="BuildConfig"></param>
        /// <param name="IsClient"></param>
        /// <returns></returns>
        virtual public string GetRelativeExecutablePath(UnrealTargetRole TargetType, UnrealTargetPlatform TargetPlatform, UnrealTargetConfiguration TargetConfiguration)
        {
            string ExePath;

            if (TargetType.UsesEditor())
            {
                ExePath = string.Format("Engine/Binaries/{0}/UE4Editor{1}", BuildHostPlatform.Current.Platform, Platform.GetExeExtension(TargetPlatform));
            }
            else
            {
                string BuildType = "";

                if (TargetType == UnrealTargetRole.Client)
                {
                    if (!UsesSharedBuildType)
                    {
                        BuildType = "Client";
                    }
                }
                else if (TargetType == UnrealTargetRole.Server)
                {
                    if (!UsesSharedBuildType)
                    {
                        BuildType = "Server";
                    }
                }

                bool IsRunningDev = Globals.Params.ParseParam("dev");

                // Turn FooGame into Foo
                string ExeBase = ProjectName.Replace("Game", "");

                if (TargetPlatform == UnrealTargetPlatform.Android)
                {
                    // use the archive results for android.
                    //var AndroidSource = new AndroidBuild(ProjectName, GetPlatformPath(TargetType, TargetPlatform), TargetConfiguration);

                    // We always (currently..) need to be able to replace the command line
                    BuildFlags Flags = BuildFlags.CanReplaceCommandLine;
                    if (IsRunningDev)
                    {
                        Flags |= BuildFlags.CanReplaceExecutable;
                    }
                    if (Globals.Params.ParseParam("bulk"))
                    {
                        Flags |= BuildFlags.Bulk;
                    }

                    var Build = GetMatchingBuilds(TargetType, TargetPlatform, TargetConfiguration, Flags).FirstOrDefault();

                    if (Build != null)
                    {
                        AndroidBuild AndroidBuild = Build as AndroidBuild;
                        ExePath = AndroidBuild.SourceApkPath;
                    }
                    else
                    {
                        throw new AutomationException("No suitable build for {0} found at {1}", TargetPlatform, BuildPath);
                    }

                    //ExePath = AndroidSource.SourceApkPath;
                }
                else
                {
                    string ExeFileName = string.Format("{0}{1}", ExeBase, BuildType);

                    if (TargetConfiguration != UnrealTargetConfiguration.Development)
                    {
                        ExeFileName += string.Format("-{0}-{1}", TargetPlatform.ToString(), TargetConfiguration.ToString());
                    }

                    ExeFileName += Platform.GetExeExtension(TargetPlatform);

                    string BasePath      = GetPlatformPath(TargetType, TargetPlatform);
                    string ProjectBinary = string.Format("{0}\\Binaries\\{1}\\{2}", ProjectName, TargetPlatform.ToString(), ExeFileName);
                    string StubBinary    = Path.Combine(BasePath, ExeFileName);
                    string DevBinary     = Path.Combine(Environment.CurrentDirectory, ProjectBinary);

                    string NonCodeProjectName   = "UE4Game" + Platform.GetExeExtension(TargetPlatform);
                    string NonCodeProjectBinary = Path.Combine(BasePath, "Engine", "Binaries", TargetPlatform.ToString());
                    NonCodeProjectBinary = Path.Combine(NonCodeProjectBinary, NonCodeProjectName);

                    // check the project binaries folder
                    if (File.Exists(Path.Combine(BasePath, ProjectBinary)))
                    {
                        ExePath = ProjectBinary;
                    }
                    else if (File.Exists(StubBinary))
                    {
                        ExePath = Path.Combine(BasePath, ExeFileName);
                    }
                    else if (IsRunningDev && File.Exists(DevBinary))
                    {
                        ExePath = DevBinary;
                    }
                    else if (File.Exists(NonCodeProjectBinary))
                    {
                        ExePath = NonCodeProjectBinary;
                    }
                    else
                    {
                        List <string> CheckedFiles = new List <String>()
                        {
                            Path.Combine(BasePath, ProjectBinary), StubBinary, NonCodeProjectBinary
                        };
                        if (IsRunningDev)
                        {
                            CheckedFiles.Add(DevBinary);
                        }

                        throw new AutomationException("Executable not found, upstream compile job may have failed.  Could not find executable {0} within {1}, binaries checked: {2}", ExeFileName, BasePath, String.Join(" - ", CheckedFiles));
                    }
                }
            }

            return(Utils.SystemHelpers.CorrectDirectorySeparators(ExePath));
        }
        //保存调查项目
        private void SubmitSurveyProject(out string msg)
        {
            msg = string.Empty;
            string errorMsg = string.Empty;

            #region 信息验证
            int spiId = 0;
            if (!string.IsNullOrEmpty(SPIID))
            {
                if (!int.TryParse(SPIID, out spiId))
                {
                    errorMsg += "不存在此调查项目!</br>";
                }
            }
            if (string.IsNullOrEmpty(ProjectName.Trim()))
            {
                errorMsg += "调查名称不能为空!</br>";
            }
            int bgId = 0;
            if (!int.TryParse(BGID, out bgId))
            {
                errorMsg += "请选择所属分组!</br>";
            }
            int scId = 0;
            if (!int.TryParse(SCID, out scId))
            {
                errorMsg += "请选择分类!</br>";
            }
            if (string.IsNullOrEmpty(Description.Trim()))
            {
                errorMsg += "调查说明不能为空!</br>";
            }
            //if (string.IsNullOrEmpty(BusinessGroup.Trim()))
            //{
            //    errorMsg += "业务组不能为空!</br>";
            //}
            int siId = 0;
            if (!int.TryParse(SIID, out siId))
            {
                errorMsg += "请选择问卷!</br>";
            }
            List <int> personIdArry = new List <int>();
            if (string.IsNullOrEmpty(PersonIDS.Trim()))
            {
                errorMsg += "请选择调查对象!</br>";
            }
            else
            {
                string[] strArry = PersonIDS.Split(',');
                foreach (string str in strArry)
                {
                    int personId = -1;
                    if (int.TryParse(str, out personId))
                    {
                        personIdArry.Add(personId);
                    }
                    else
                    {
                        errorMsg += "调查对象选择有问题!</br>";
                        break;
                    }
                }
            }
            DateTime beginTime = Entities.Constants.Constant.DATE_INVALID_VALUE;
            if (string.IsNullOrEmpty(BeginTime))
            {
                errorMsg += "调查开始时间不能为空!</br>";
            }
            else
            {
                if (!DateTime.TryParse(BeginTime, out beginTime))
                {
                    errorMsg += "调查开始时间格式不正确!</br>";
                }
                else
                {
                    if (beginTime < DateTime.Now)
                    {
                        errorMsg += "调查开始时间不能小于当前时间!</br>";
                    }
                }
            }
            DateTime endTime = Entities.Constants.Constant.DATE_INVALID_VALUE;
            if (string.IsNullOrEmpty(EndTime))
            {
                errorMsg += "调查开始时间不能为空!</br>";
            }
            else
            {
                if (!DateTime.TryParse(EndTime, out endTime))
                {
                    errorMsg += "调查开始时间格式不正确!</br>";
                }
                else
                {
                    if (endTime <= beginTime)
                    {
                        errorMsg += "调查结束时间不能小于开始时间!</br>";
                    }
                }
            }
            #endregion
            if (string.IsNullOrEmpty(errorMsg))
            {
                //如果项目ID小于等于0,新增项目
                if (spiId <= 0)
                {
                    Entities.SurveyProjectInfo model = new Entities.SurveyProjectInfo();
                    model.BGID            = bgId;
                    model.BusinessGroup   = BusinessGroup;
                    model.CreateTime      = DateTime.Now;
                    model.CreateUserID    = BLL.Util.GetLoginUserID();
                    model.Description     = Description;
                    model.Name            = ProjectName;
                    model.SCID            = scId;
                    model.SIID            = siId;
                    model.Status          = 0;
                    model.SurveyEndTime   = endTime;
                    model.SurveyStartTime = beginTime;
                    //新增问卷项目
                    int recId = BLL.SurveyProjectInfo.Instance.Insert(model);

                    //新增调查参与人
                    foreach (int personId in personIdArry)
                    {
                        Entities.SurveyPerson personModel = new Entities.SurveyPerson();
                        personModel.CreateTime   = DateTime.Now;
                        personModel.CreateUserID = BLL.Util.GetLoginUserID();
                        personModel.ExamPersonID = personId;
                        personModel.SPIID        = recId;

                        BLL.SurveyPerson.Instance.Insert(personModel);
                    }
                    msg = "{Result:'success',RecID:'" + recId + "',ErrorMsg:''}";
                }
                else
                {
                    Entities.SurveyProjectInfo info = BLL.SurveyProjectInfo.Instance.GetSurveyProjectInfo(spiId);
                    if (info != null)
                    {
                        if (info.SurveyStartTime <= DateTime.Now)
                        {
                            errorMsg += "此问卷正在调查中,无法进行编辑操作!</br>";
                        }
                        else
                        {
                            info.BGID            = bgId;
                            info.BusinessGroup   = BusinessGroup;
                            info.Description     = Description;
                            info.Name            = ProjectName;
                            info.SCID            = scId;
                            info.SIID            = siId;
                            info.SurveyEndTime   = endTime;
                            info.SurveyStartTime = beginTime;
                            info.ModifyTime      = DateTime.Now;
                            info.ModifyUserID    = BLL.Util.GetLoginUserID();
                            BLL.SurveyProjectInfo.Instance.Update(info);

                            BLL.SurveyPerson.Instance.DeleteBySPIID(spiId);
                            foreach (int personId in personIdArry)
                            {
                                Entities.SurveyPerson personModel = new Entities.SurveyPerson();
                                personModel.CreateTime   = DateTime.Now;
                                personModel.CreateUserID = BLL.Util.GetLoginUserID();
                                personModel.ExamPersonID = personId;
                                personModel.SPIID        = spiId;

                                BLL.SurveyPerson.Instance.Insert(personModel);
                            }
                        }
                    }
                    else
                    {
                        errorMsg += "不存在此问卷项目!</br>";
                    }
                    if (string.IsNullOrEmpty(errorMsg))
                    {
                        msg = "{Result:'success',RecID:'" + spiId + "',ErrorMsg:'" + errorMsg + "'}";
                    }
                    else
                    {
                        msg = "{Result:'error',RecID:'',ErrorMsg:'" + errorMsg + "'}";
                    }
                }
            }
            else
            {
                msg = "{Result:'error',RecID:'',ErrorMsg:'" + errorMsg + "'}";
            }
        }
Example #13
0
        /// <summary>
        /// Gets the hash code
        /// </summary>
        /// <returns>Hash code</returns>
        public override int GetHashCode()
        {
            // credit: http://stackoverflow.com/a/263416/677735
            unchecked // Overflow is fine, just wrap
            {
                int hash = 41;

                // Suitable nullity checks
                hash = hash * 59 + Id.GetHashCode();

                if (LocalArea != null)
                {
                    hash = hash * 59 + LocalArea.GetHashCode();
                }

                if (EquipmentCount != null)
                {
                    hash = hash * 59 + EquipmentCount.GetHashCode();
                }

                if (EquipmentTypeName != null)
                {
                    hash = hash * 59 + EquipmentTypeName.GetHashCode();
                }

                if (DistrictEquipmentName != null)
                {
                    hash = hash * 59 + DistrictEquipmentName.GetHashCode();
                }

                if (ProjectName != null)
                {
                    hash = hash * 59 + ProjectName.GetHashCode();
                }

                if (PrimaryContact != null)
                {
                    hash = hash * 59 + PrimaryContact.GetHashCode();
                }

                if (Status != null)
                {
                    hash = hash * 59 + Status.GetHashCode();
                }

                if (ProjectId != null)
                {
                    hash = hash * 59 + ProjectId.GetHashCode();
                }

                if (ExpectedStartDate != null)
                {
                    hash = hash * 59 + ExpectedStartDate.GetHashCode();
                }

                if (ExpectedEndDate != null)
                {
                    hash = hash * 59 + ExpectedEndDate.GetHashCode();
                }

                return(hash);
            }
        }
Example #14
0
        /// <summary>
        /// Returns true if RentalRequestSearchResultViewModel instances are equal
        /// </summary>
        /// <param name="other">Instance of RentalRequestSearchResultViewModel to be compared</param>
        /// <returns>Boolean</returns>
        public bool Equals(RentalRequestSearchResultViewModel other)
        {
            if (other is null)
            {
                return(false);
            }
            if (ReferenceEquals(this, other))
            {
                return(true);
            }

            return
                ((
                     Id == other.Id ||
                     Id.Equals(other.Id)
                     ) &&
                 (
                     LocalArea == other.LocalArea ||
                     LocalArea != null &&
                     LocalArea.Equals(other.LocalArea)
                 ) &&
                 (
                     EquipmentCount == other.EquipmentCount ||
                     EquipmentCount != null &&
                     EquipmentCount.Equals(other.EquipmentCount)
                 ) &&
                 (
                     EquipmentTypeName == other.EquipmentTypeName ||
                     EquipmentTypeName != null &&
                     EquipmentTypeName.Equals(other.EquipmentTypeName)
                 ) &&
                 (
                     DistrictEquipmentName == other.DistrictEquipmentName ||
                     DistrictEquipmentName != null &&
                     DistrictEquipmentName.Equals(other.DistrictEquipmentName)
                 ) &&
                 (
                     ProjectName == other.ProjectName ||
                     ProjectName != null &&
                     ProjectName.Equals(other.ProjectName)
                 ) &&
                 (
                     PrimaryContact == other.PrimaryContact ||
                     PrimaryContact != null &&
                     PrimaryContact.Equals(other.PrimaryContact)
                 ) &&
                 (
                     Status == other.Status ||
                     Status != null &&
                     Status.Equals(other.Status)
                 ) &&
                 (
                     ProjectId == other.ProjectId ||
                     ProjectId != null &&
                     ProjectId.Equals(other.ProjectId)
                 ) &&
                 (
                     ExpectedStartDate == other.ExpectedStartDate ||
                     ExpectedStartDate != null &&
                     ExpectedStartDate.Equals(other.ExpectedStartDate)
                 ) &&
                 (
                     ExpectedEndDate == other.ExpectedEndDate ||
                     ExpectedEndDate != null &&
                     ExpectedEndDate.Equals(other.ExpectedEndDate)
                 ));
        }
 // [END write_log_entry]
 // [START list_log_entries]
 private void ListLogEntries(string logId)
 {
     var client = LoggingServiceV2Client.Create();
     LogName logName = new LogName(s_projectId, logId);
     ProjectName projectName = new ProjectName(s_projectId);
     IEnumerable<string> projectIds = new string[] { projectName.ToString() };
     var results = client.ListLogEntries(projectIds, $"logName={logName.ToString()}",
         "timestamp desc", callSettings: RetryAWhile);
     foreach (var row in results)
     {
         if (row != null && !String.IsNullOrEmpty(row.TextPayload.Trim()))
         {
             Console.WriteLine($"{row.TextPayload.Trim()}");
         }
         else
         {
             results.GetEnumerator().Dispose();
             break;
         }
     }
 }
Example #16
0
 /// <summary>
 /// Finds a project name by short name, unique name or custom unique name.
 /// </summary>
 /// <param name="name">name of the project</param>
 /// <param name="projectName">project name instance</param>
 /// <returns>true if the project name with the specified name is found.</returns>
 public bool TryGetProjectName(string name, out ProjectName projectName)
 {
     return _projectNamesCache.TryGetValue(name, out projectName) ||
            TryGetProjectNameByShortName(name, out projectName);
 }
Example #17
0
 public bool IsConverted()
 {
     // is converted if the forst part of the name is the Org Code
     return(OrgCode.Equals(ProjectName.Substring(0, 4)));
 }
Example #18
0
        /// <summary>
        /// Removes a project from the short name cache.
        /// </summary>
        /// <param name="projectName">The short name of the project.</param>
        private void RemoveShortName(ProjectName projectName)
        {
            HashSet<ProjectName> projectNames;
            if (_shortNameCache.TryGetValue(projectName.ShortName, out projectNames)) {
                projectNames.Remove(projectName);

                // Remove the item from the dictionary if we've removed the last project
                if (projectNames.Count == 0) {
                    _shortNameCache.Remove(projectName.ShortName);
                }
            }
        }
Example #19
0
 private ProjectAggregationRoot(EntityId id, ProjectName name, ProjectCode code,
                                Money budget, DateAndTime startDate, EntityId clientId)
     : this(Project.NewRequest(id, name, code, startDate, budget, clientId))
 {
 }
Example #20
0
        protected override int Execute()
        {
            var thisAssembly = typeof(GetDocumentCommand).Assembly;

            var toolsDirectory     = ToolsDirectory.Value();
            var packagedAssemblies = Directory
                                     .EnumerateFiles(toolsDirectory, "*.dll")
                                     .Except(new[] { Path.GetFullPath(thisAssembly.Location) })
                                     .ToDictionary(path => Path.GetFileNameWithoutExtension(path), path => new AssemblyInfo(path));

            // Explicitly load all assemblies we need first to preserve target project as much as possible. This
            // executable is always run in the target project's context (either through location or .deps.json file).
            foreach (var keyValuePair in packagedAssemblies)
            {
                try
                {
                    keyValuePair.Value.Assembly = Assembly.Load(new AssemblyName(keyValuePair.Key));
                }
                catch
                {
                    // Ignore all failures because missing assemblies should be loadable from tools directory.
                }
            }

#if NETCOREAPP2_1
            AssemblyLoadContext.Default.Resolving += (loadContext, assemblyName) =>
            {
                var name = assemblyName.Name;
                if (!packagedAssemblies.TryGetValue(name, out var info))
                {
                    return(null);
                }

                var assemblyPath = info.Path;
                if (!File.Exists(assemblyPath))
                {
                    throw new InvalidOperationException(
                              $"Referenced assembly '{name}' was not found in '{toolsDirectory}'.");
                }

                return(loadContext.LoadFromAssemblyPath(assemblyPath));
            };
#elif NETFRAMEWORK
            AppDomain.CurrentDomain.AssemblyResolve += (source, eventArgs) =>
            {
                var assemblyName = new AssemblyName(eventArgs.Name);
                var name         = assemblyName.Name;
                if (!packagedAssemblies.TryGetValue(name, out var info))
                {
                    return(null);
                }

                var assembly = info.Assembly;
                if (assembly != null)
                {
                    // Loaded already
                    return(assembly);
                }

                var assemblyPath = info.Path;
                if (!File.Exists(assemblyPath))
                {
                    throw new InvalidOperationException(
                              $"Referenced assembly '{name}' was not found in '{toolsDirectory}'.");
                }

                return(Assembly.LoadFile(assemblyPath));
            };
#else
#error Target frameworks need to be updated.
#endif

            // Now safe to reference the application's code.
            try
            {
                var assemblyPath = AssemblyPath.Value();
                var context      = new GetDocumentCommandContext
                {
                    AssemblyPath    = assemblyPath,
                    AssemblyName    = Path.GetFileNameWithoutExtension(assemblyPath),
                    FileListPath    = _fileListPath.Value(),
                    OutputDirectory = _output.Value(),
                    ProjectName     = ProjectName.Value(),
                    Reporter        = Reporter,
                };

                return(new GetDocumentCommandWorker(context).Process());
            }
            catch (Exception ex)
            {
                Reporter.WriteError(ex.ToString());
                return(2);
            }
        }
Example #21
0
 public static ProjectAggregationRoot CreateFrom(ProjectName name, ProjectCode code, Money budget, DateAndTime startDate, EntityId clientId)
 {
     return(new ProjectAggregationRoot(EntityId.GetNext(), name, code, budget, startDate, clientId));
 }
        /// <summary>
        ///     After loading from console it will be used to setup valid parameters
        /// </summary>
        public void SetupDefaults()
        {
            if (RootDirectory.IsEmpty())
            {
                RootDirectory = Application.Current.RootDirectory;
            }
            var resolver = Application.Current.Container.Get <IFileNameResolver>();

            resolver.Root = RootDirectory;
            if (ReferenceDirectory.IsEmpty())
            {
                var custom = resolver.Resolve("~/lib", true);
                if (custom.IsNotEmpty())
                {
                    ReferenceDirectory = custom;
                }
                else
                {
                    ReferenceDirectory = EnvironmentInfo.BinDirectory;
                }
            }
            else
            {
                ReferenceDirectory = resolver.Resolve(ReferenceDirectory, false);
            }

            if (ProjectsDirectory.IsEmpty())
            {
                ProjectsDirectory = resolver.Resolve("~/projects", false);
            }
            ProjectsDirectory = resolver.Resolve(ProjectsDirectory, false);
            if (ProjectName.IsEmpty())
            {
                ProjectName = "DefaultProject";
            }
            if (!Path.IsPathRooted(ProjectName))
            {
                ProjectName = Path.Combine(ProjectsDirectory, ProjectName);
            }

            if (OutDirectory.IsEmpty())
            {
                OutDirectory = "bin";
            }
            if (!Path.IsPathRooted(OutDirectory))
            {
                OutDirectory = Path.Combine(ProjectName, OutDirectory);
            }

            if (OutCodeDirectory.IsEmpty())
            {
                OutCodeDirectory = "obj";
            }
            if (!Path.IsPathRooted(OutCodeDirectory))
            {
                OutCodeDirectory = Path.Combine(ProjectName, OutCodeDirectory);
            }
            Directory.CreateDirectory(RootDirectory);
            Directory.CreateDirectory(ReferenceDirectory);
            Directory.CreateDirectory(ProjectsDirectory);
            Directory.CreateDirectory(ProjectName);
            Directory.CreateDirectory(OutDirectory);
            Directory.CreateDirectory(OutCodeDirectory);
        }
Example #23
0
 public override int GetHashCode()
 {
     return(ProjectName.GetHashCode());
 }
Example #24
0
        /// <summary>
        /// Creates the scripture text object.
        /// </summary>
        /// <param name="ptUsername">The paratext username.</param>
        /// <param name="projectName">Name of the project.</param>
        /// <returns>The scripture text object</returns>
        protected virtual ScrText CreateScrText(string ptUsername, ProjectName projectName)
        {
            var associatedUser = new SFParatextUser(ptUsername);

            return(new ScrText(projectName, associatedUser));
        }
Example #25
0
        public static void Main(string[] args)
        {
            // Your Google Cloud Platform project ID.
            string projectId = "YOUR-PROJECT-ID";

            // Create client.
            MetricServiceClient metricServiceClient = MetricServiceClient.Create();

            // Initialize request argument(s).
            ProjectName name = new ProjectName(projectId);

            // Prepare a data point.
            TypedValue salesTotal = new TypedValue
            {
                DoubleValue = 123.45
            };
            Point dataPoint = new Point
            {
                Value = salesTotal
            };
            // Sets data point's interval end time to current time.
            DateTime  UnixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
            Timestamp timeStamp = new Timestamp
            {
                Seconds = (long)(DateTime.UtcNow - UnixEpoch).TotalSeconds
            };
            TimeInterval interval = new TimeInterval
            {
                EndTime = timeStamp
            };

            dataPoint.Interval = interval;

            // Prepare custom metric.
            Metric metric = new Metric
            {
                Type = "custom.googleapis.com/my_metric"
            };

            metric.Labels.Add("store_id", "Pittsburgh");

            // Prepare monitored resource.
            MonitoredResource resource = new MonitoredResource
            {
                Type = "gce_instance"
            };

            resource.Labels.Add("project_id", projectId);
            resource.Labels.Add("instance_id", "1234567890123456789");
            resource.Labels.Add("zone", "us-central1-f");

            // Create a new time series using inputs.
            TimeSeries timeSeriesData = new TimeSeries
            {
                Metric   = metric,
                Resource = resource
            };

            timeSeriesData.Points.Add(dataPoint);

            // Add newly created time series to list of time series to be written.
            IEnumerable <TimeSeries> timeSeries = new List <TimeSeries> {
                timeSeriesData
            };

            // Write time series data.
            metricServiceClient.CreateTimeSeries(name, timeSeries);
            Console.WriteLine("Done writing time series data.");
        }
Example #26
0
    public (string apk, string packageId) BuildApk(
        string sourceDir, string abi, string entryPointLib, string monoRuntimeHeaders)
    {
        if (!Directory.Exists(sourceDir))
        {
            throw new ArgumentException($"sourceDir='{sourceDir}' is empty or doesn't exist");
        }

        if (string.IsNullOrEmpty(abi))
        {
            throw new ArgumentException("abi shoudln't be empty (e.g. x86, x86_64, armeabi-v7a or arm64-v8a");
        }

        string entryPointLibPath = "";

        if (!string.IsNullOrEmpty(entryPointLib))
        {
            entryPointLibPath = Path.Combine(sourceDir, entryPointLib);
            if (!File.Exists(entryPointLibPath))
            {
                throw new ArgumentException($"{entryPointLib} was not found in sourceDir='{sourceDir}'");
            }
        }

        if (string.IsNullOrEmpty(ProjectName))
        {
            if (string.IsNullOrEmpty(entryPointLib))
            {
                throw new ArgumentException("ProjectName needs to be set if entryPointLib is empty.");
            }
            else
            {
                ProjectName = Path.GetFileNameWithoutExtension(entryPointLib);
            }
        }

        if (string.IsNullOrEmpty(OutputDir))
        {
            OutputDir = Path.Combine(sourceDir, "bin-" + abi);
        }

        if (ProjectName.Contains(' '))
        {
            throw new ArgumentException($"ProjectName='{ProjectName}' shouldn't not contain spaces.");
        }

        if (string.IsNullOrEmpty(AndroidSdk))
        {
            AndroidSdk = Environment.GetEnvironmentVariable("ANDROID_SDK_ROOT");
        }

        if (string.IsNullOrEmpty(AndroidNdk))
        {
            AndroidNdk = Environment.GetEnvironmentVariable("ANDROID_NDK_ROOT");
        }

        if (string.IsNullOrEmpty(AndroidSdk) || !Directory.Exists(AndroidSdk))
        {
            throw new ArgumentException($"Android SDK='{AndroidSdk}' was not found or empty (can be set via ANDROID_SDK_ROOT envvar).");
        }

        if (string.IsNullOrEmpty(AndroidNdk) || !Directory.Exists(AndroidNdk))
        {
            throw new ArgumentException($"Android NDK='{AndroidNdk}' was not found or empty (can be set via ANDROID_NDK_ROOT envvar).");
        }

        // Try to get the latest build-tools version if not specified
        if (string.IsNullOrEmpty(BuildToolsVersion))
        {
            BuildToolsVersion = GetLatestBuildTools(AndroidSdk);
        }

        // Try to get the latest API level if not specified
        if (string.IsNullOrEmpty(BuildApiLevel))
        {
            BuildApiLevel = GetLatestApiLevel(AndroidSdk);
        }

        if (string.IsNullOrEmpty(MinApiLevel))
        {
            MinApiLevel = DefaultMinApiLevel;
        }

        // make sure BuildApiLevel >= MinApiLevel
        // only if these api levels are not "preview" (not integers)
        if (int.TryParse(BuildApiLevel, out int intApi) &&
            int.TryParse(MinApiLevel, out int intMinApi) &&
            intApi < intMinApi)
        {
            throw new ArgumentException($"BuildApiLevel={BuildApiLevel} <= MinApiLevel={MinApiLevel}. " +
                                        "Make sure you've downloaded some recent build-tools in Android SDK");
        }

        string buildToolsFolder = Path.Combine(AndroidSdk, "build-tools", BuildToolsVersion);

        if (!Directory.Exists(buildToolsFolder))
        {
            throw new ArgumentException($"{buildToolsFolder} was not found.");
        }

        Directory.CreateDirectory(OutputDir);
        Directory.CreateDirectory(Path.Combine(OutputDir, "bin"));
        Directory.CreateDirectory(Path.Combine(OutputDir, "obj"));
        Directory.CreateDirectory(Path.Combine(OutputDir, "assets-tozip"));
        Directory.CreateDirectory(Path.Combine(OutputDir, "assets"));

        var extensionsToIgnore = new List <string> {
            ".so", ".a", ".gz"
        };

        if (StripDebugSymbols)
        {
            extensionsToIgnore.Add(".pdb");
            extensionsToIgnore.Add(".dbg");
        }

        // Copy sourceDir to OutputDir/assets-tozip (ignore native files)
        // these files then will be zipped and copied to apk/assets/assets.zip
        Utils.DirectoryCopy(sourceDir, Path.Combine(OutputDir, "assets-tozip"), file =>
        {
            string fileName  = Path.GetFileName(file);
            string extension = Path.GetExtension(file);

            if (extensionsToIgnore.Contains(extension))
            {
                // ignore native files, those go to lib/%abi%
                // also, aapt is not happy about zip files
                return(false);
            }
            if (fileName.StartsWith("."))
            {
                // aapt complains on such files
                return(false);
            }
            return(true);
        });

        // tools:
        string dx               = Path.Combine(buildToolsFolder, "dx");
        string aapt             = Path.Combine(buildToolsFolder, "aapt");
        string zipalign         = Path.Combine(buildToolsFolder, "zipalign");
        string apksigner        = Path.Combine(buildToolsFolder, "apksigner");
        string androidJar       = Path.Combine(AndroidSdk, "platforms", "android-" + BuildApiLevel, "android.jar");
        string androidToolchain = Path.Combine(AndroidNdk, "build", "cmake", "android.toolchain.cmake");
        string keytool          = "keytool";
        string javac            = "javac";
        string cmake            = "cmake";
        string zip              = "zip";

        Utils.RunProcess(zip, workingDir: Path.Combine(OutputDir, "assets-tozip"), args: "-q -r ../assets/assets.zip .");
        Directory.Delete(Path.Combine(OutputDir, "assets-tozip"), true);

        if (!File.Exists(androidJar))
        {
            throw new ArgumentException($"API level={BuildApiLevel} is not downloaded in Android SDK");
        }

        // 1. Build libmonodroid.so` via cmake

        string monoRuntimeLib = Path.Combine(sourceDir, "libmonosgen-2.0.a");

        if (!File.Exists(monoRuntimeLib))
        {
            throw new ArgumentException($"libmonosgen-2.0.a was not found in {sourceDir}");
        }

        string cmakeLists = Utils.GetEmbeddedResource("CMakeLists-android.txt")
                            .Replace("%MonoInclude%", monoRuntimeHeaders)
                            .Replace("%NativeLibrariesToLink%", monoRuntimeLib);

        File.WriteAllText(Path.Combine(OutputDir, "CMakeLists.txt"), cmakeLists);

        File.WriteAllText(Path.Combine(OutputDir, "monodroid.c"), Utils.GetEmbeddedResource("monodroid.c"));

        string cmakeGenArgs = $"-DCMAKE_TOOLCHAIN_FILE={androidToolchain} -DANDROID_ABI=\"{abi}\" -DANDROID_STL=none " +
                              $"-DANDROID_NATIVE_API_LEVEL={MinApiLevel} -B monodroid";

        string cmakeBuildArgs = "--build monodroid";

        if (StripDebugSymbols)
        {
            // Use "-s" to strip debug symbols, it complains it's unused but it works
            cmakeGenArgs   += " -DCMAKE_BUILD_TYPE=MinSizeRel -DCMAKE_C_FLAGS=\"-s -Wno-unused-command-line-argument\"";
            cmakeBuildArgs += " --config MinSizeRel";
        }
        else
        {
            cmakeGenArgs   += " -DCMAKE_BUILD_TYPE=Debug";
            cmakeBuildArgs += " --config Debug";
        }

        Utils.RunProcess(cmake, workingDir: OutputDir, args: cmakeGenArgs);
        Utils.RunProcess(cmake, workingDir: OutputDir, args: cmakeBuildArgs);

        // 2. Compile Java files

        string javaSrcFolder = Path.Combine(OutputDir, "src", "net", "dot");

        Directory.CreateDirectory(javaSrcFolder);

        string packageId = $"net.dot.{ProjectName}";

        File.WriteAllText(Path.Combine(javaSrcFolder, "MainActivity.java"),
                          Utils.GetEmbeddedResource("MainActivity.java"));

        string monoRunner = Utils.GetEmbeddedResource("MonoRunner.java")
                            .Replace("%EntryPointLibName%", Path.GetFileName(entryPointLib));

        File.WriteAllText(Path.Combine(javaSrcFolder, "MonoRunner.java"), monoRunner);

        File.WriteAllText(Path.Combine(OutputDir, "AndroidManifest.xml"),
                          Utils.GetEmbeddedResource("AndroidManifest.xml")
                          .Replace("%PackageName%", packageId)
                          .Replace("%MinSdkLevel%", MinApiLevel));

        string javaCompilerArgs = $"-d obj -classpath src -bootclasspath {androidJar} -source 1.8 -target 1.8 ";

        Utils.RunProcess(javac, javaCompilerArgs + Path.Combine(javaSrcFolder, "MainActivity.java"), workingDir: OutputDir);
        Utils.RunProcess(javac, javaCompilerArgs + Path.Combine(javaSrcFolder, "MonoRunner.java"), workingDir: OutputDir);
        Utils.RunProcess(dx, "--dex --output=classes.dex obj", workingDir: OutputDir);

        // 3. Generate APK

        string apkFile = Path.Combine(OutputDir, "bin", $"{ProjectName}.unaligned.apk");

        Utils.RunProcess(aapt, $"package -f -m -F {apkFile} -A assets -M AndroidManifest.xml -I {androidJar}", workingDir: OutputDir);

        var dynamicLibs = new List <string>();

        dynamicLibs.Add(Path.Combine(OutputDir, "monodroid", "libmonodroid.so"));
        dynamicLibs.AddRange(Directory.GetFiles(sourceDir, "*.so").Where(file => Path.GetFileName(file) != "libmonodroid.so"));

        // add all *.so files to lib/%abi%/
        Directory.CreateDirectory(Path.Combine(OutputDir, "lib", abi));
        foreach (var dynamicLib in dynamicLibs)
        {
            string dynamicLibName = Path.GetFileName(dynamicLib);
            if (dynamicLibName == "libmonosgen-2.0.so")
            {
                // we link mono runtime statically into libmonodroid.so
                continue;
            }

            // NOTE: we can run android-strip tool from NDK to shrink native binaries here even more.

            string destRelative = Path.Combine("lib", abi, dynamicLibName);
            File.Copy(dynamicLib, Path.Combine(OutputDir, destRelative), true);
            Utils.RunProcess(aapt, $"add {apkFile} {destRelative}", workingDir: OutputDir);
        }
        Utils.RunProcess(aapt, $"add {apkFile} classes.dex", workingDir: OutputDir);

        // 4. Align APK

        string alignedApk = Path.Combine(OutputDir, "bin", $"{ProjectName}.apk");

        Utils.RunProcess(zipalign, $"-v 4 {apkFile} {alignedApk}", workingDir: OutputDir);
        // we don't need the unaligned one any more
        File.Delete(apkFile);

        // 5. Generate key

        string signingKey = Path.Combine(OutputDir, "debug.keystore");

        if (!File.Exists(signingKey))
        {
            Utils.RunProcess(keytool, "-genkey -v -keystore debug.keystore -storepass android -alias " +
                             "androiddebugkey -keypass android -keyalg RSA -keysize 2048 -noprompt " +
                             "-dname \"CN=Android Debug,O=Android,C=US\"", workingDir: OutputDir, silent: true);
        }

        // 6. Sign APK

        Utils.RunProcess(apksigner, $"sign --min-sdk-version {MinApiLevel} --ks debug.keystore " +
                         $"--ks-pass pass:android --key-pass pass:android {alignedApk}", workingDir: OutputDir);

        Utils.LogInfo($"\nAPK size: {(new FileInfo(alignedApk).Length / 1000_000.0):0.#} Mb.\n");

        return(alignedApk, packageId);
    }
Example #27
0
        public void Insert(ProjectName project)
        {
            IGenericCrystel <ProjectName> modu = new GenericCrystel <ProjectName>();

            modu.Insert(project);
        }
    public override void ExecuteBuild()
    {
        var UEProjectRoot = ParseParamValue("UEProjectRoot");

        if (UEProjectRoot == null)
        {
            UEProjectRoot = CmdEnv.LocalRoot;
        }

        var UEProjectDirectory = ParseParamValue("UEProjectDirectory");

        if (UEProjectDirectory == null)
        {
            throw new AutomationException("Missing required command line argument: 'UEProjectDirectory'");
        }

        var UEProjectName = ParseParamValue("UEProjectName");

        if (UEProjectName == null)
        {
            UEProjectName = "";
        }

        var LocalizationProjectNames = new List <string>();
        {
            var LocalizationProjectNamesStr = ParseParamValue("LocalizationProjectNames");
            if (LocalizationProjectNamesStr != null)
            {
                foreach (var ProjectName in LocalizationProjectNamesStr.Split(','))
                {
                    LocalizationProjectNames.Add(ProjectName.Trim());
                }
            }
        }

        var LocalizationProviderName = ParseParamValue("LocalizationProvider");

        if (LocalizationProviderName == null)
        {
            LocalizationProviderName = "OneSky";
        }

        var LocalizationSteps = new List <string>();
        {
            var LocalizationStepsStr = ParseParamValue("LocalizationSteps");
            if (LocalizationStepsStr == null)
            {
                LocalizationSteps.AddRange(new string[] { "Download", "Gather", "Import", "Export", "Compile", "GenerateReports", "Upload" });
            }
            else
            {
                foreach (var StepName in LocalizationStepsStr.Split(','))
                {
                    LocalizationSteps.Add(StepName.Trim());
                }
            }
            LocalizationSteps.Add("Monolithic");             // Always allow the monolithic scripts to run as we don't know which steps they do
        }

        var ShouldGatherPlugins = ParseParam("IncludePlugins");
        var IncludePlugins      = new List <string>();
        var ExcludePlugins      = new List <string>();

        if (ShouldGatherPlugins)
        {
            var IncludePluginsStr = ParseParamValue("IncludePlugins");
            if (IncludePluginsStr != null)
            {
                foreach (var PluginName in IncludePluginsStr.Split(','))
                {
                    IncludePlugins.Add(PluginName.Trim());
                }
            }

            var ExcludePluginsStr = ParseParamValue("ExcludePlugins");
            if (ExcludePluginsStr != null)
            {
                foreach (var PluginName in ExcludePluginsStr.Split(','))
                {
                    ExcludePlugins.Add(PluginName.Trim());
                }
            }
        }

        var AdditionalCommandletArguments = ParseParamValue("AdditionalCommandletArguments");

        if (AdditionalCommandletArguments == null)
        {
            AdditionalCommandletArguments = "";
        }

        var LocalizationBatches = new List <LocalizationBatch>();

        // Add the static set of localization projects as a batch
        if (LocalizationProjectNames.Count > 0)
        {
            LocalizationBatches.Add(new LocalizationBatch(UEProjectDirectory, UEProjectDirectory, "", LocalizationProjectNames));
        }

        // Build up any additional batches needed for plugins
        if (ShouldGatherPlugins)
        {
            var PluginsRootDirectory = CombinePaths(UEProjectRoot, UEProjectDirectory, "Plugins");
            IReadOnlyList <PluginInfo> AllPlugins = Plugins.ReadPluginsFromDirectory(new DirectoryReference(PluginsRootDirectory), UEProjectName.Length == 0 ? PluginType.Engine : PluginType.Project);

            // Add a batch for each plugin that meets our criteria
            foreach (var PluginInfo in AllPlugins)
            {
                bool ShouldIncludePlugin = (IncludePlugins.Count == 0 || IncludePlugins.Contains(PluginInfo.Name)) && !ExcludePlugins.Contains(PluginInfo.Name);
                if (ShouldIncludePlugin && PluginInfo.Descriptor.LocalizationTargets != null && PluginInfo.Descriptor.LocalizationTargets.Length > 0)
                {
                    var RootRelativePluginPath = PluginInfo.Directory.MakeRelativeTo(new DirectoryReference(UEProjectRoot));
                    RootRelativePluginPath = RootRelativePluginPath.Replace('\\', '/');                     // Make sure we use / as these paths are used with P4

                    var PluginTargetNames = new List <string>();
                    foreach (var LocalizationTarget in PluginInfo.Descriptor.LocalizationTargets)
                    {
                        PluginTargetNames.Add(LocalizationTarget.Name);
                    }

                    LocalizationBatches.Add(new LocalizationBatch(UEProjectDirectory, RootRelativePluginPath, PluginInfo.Name, PluginTargetNames));
                }
            }
        }

        // Create a single changelist to use for all changes, and hash the current PO files on disk so we can work out whether they actually change
        int PendingChangeList = 0;
        Dictionary <string, byte[]> InitalPOFileHashes = null;

        if (P4Enabled)
        {
            PendingChangeList  = P4.CreateChange(P4Env.Client, "Localization Automation");
            InitalPOFileHashes = GetPOFileHashes(LocalizationBatches, UEProjectRoot);
        }

        // Process each localization batch
        foreach (var LocalizationBatch in LocalizationBatches)
        {
            ProcessLocalizationProjects(LocalizationBatch, PendingChangeList, UEProjectRoot, UEProjectName, LocalizationProviderName, LocalizationSteps, AdditionalCommandletArguments);
        }

        // Submit that single changelist now
        if (P4Enabled && AllowSubmit)
        {
            // Revert any PO files that haven't changed aside from their header
            {
                var POFilesToRevert = new List <string>();

                var CurrentPOFileHashes = GetPOFileHashes(LocalizationBatches, UEProjectRoot);
                foreach (var CurrentPOFileHashPair in CurrentPOFileHashes)
                {
                    byte[] InitialPOFileHash;
                    if (InitalPOFileHashes.TryGetValue(CurrentPOFileHashPair.Key, out InitialPOFileHash) && InitialPOFileHash.SequenceEqual(CurrentPOFileHashPair.Value))
                    {
                        POFilesToRevert.Add(CurrentPOFileHashPair.Key);
                    }
                }

                if (POFilesToRevert.Count > 0)
                {
                    var P4RevertArgsFilename = CombinePaths(CmdEnv.LocalRoot, "Engine", "Intermediate", String.Format("LocalizationP4RevertArgs-{0}.txt", Guid.NewGuid().ToString()));

                    using (StreamWriter P4RevertArgsWriter = File.CreateText(P4RevertArgsFilename))
                    {
                        foreach (var POFileToRevert in POFilesToRevert)
                        {
                            P4RevertArgsWriter.WriteLine(POFileToRevert);
                        }
                    }

                    P4.LogP4(String.Format("-x{0} revert", P4RevertArgsFilename));
                    DeleteFile_NoExceptions(P4RevertArgsFilename);
                }
            }

            // Revert any other unchanged files
            P4.RevertUnchanged(PendingChangeList);

            int SubmittedChangeList;
            P4.Submit(PendingChangeList, out SubmittedChangeList);
        }
    }
Example #29
0
        public void Update(ProjectName project)
        {
            IGenericCrystel <ProjectName> modu = new GenericCrystel <ProjectName>();

            modu.Update(project);
        }
        // [END list_log_entries]
        // [START create_log_sink]
        private void CreateSink(string sinkId, string logId)
        {
            var sinkClient = ConfigServiceV2Client.Create();
            CreateSinkRequest sinkRequest = new CreateSinkRequest();
            LogSink myLogSink = new LogSink();
            myLogSink.Name = sinkId;

            // This creates a sink using a Google Cloud Storage bucket
            // named the same as the projectId.
            // This requires editing the bucket's permissions to add the Entity Group
            // named '*****@*****.**' with 'Owner' access for the bucket.
            // If this is being run with a Google Cloud service account,
            // that account will need to be granted 'Owner' access to the Project.
            // In Powershell, use this command:
            // PS > Add-GcsBucketAcl <your-bucket-name> -Role OWNER -Group [email protected]
            myLogSink.Destination = "storage.googleapis.com/" + s_projectId;
            LogName logName = new LogName(s_projectId, logId);
            myLogSink.Filter = $"logName={logName.ToString()}AND severity<=ERROR";
            ProjectName projectName = new ProjectName(s_projectId);
            sinkRequest.Sink = myLogSink;
            sinkClient.CreateSink(ParentNameOneof.From(projectName), myLogSink, RetryAWhile);
            Console.WriteLine($"Created sink: {sinkId}.");
        }
Example #31
0
    public (string apk, string packageId) BuildApk(
        string abi,
        string mainLibraryFileName,
        string monoRuntimeHeaders)
    {
        if (string.IsNullOrEmpty(AppDir) || !Directory.Exists(AppDir))
        {
            throw new ArgumentException($"AppDir='{AppDir}' is empty or doesn't exist");
        }

        if (!string.IsNullOrEmpty(mainLibraryFileName) && !File.Exists(Path.Combine(AppDir, mainLibraryFileName)))
        {
            throw new ArgumentException($"MainLibraryFileName='{mainLibraryFileName}' was not found in AppDir='{AppDir}'");
        }

        if (string.IsNullOrEmpty(abi))
        {
            throw new ArgumentException("abi should not be empty (e.g. x86, x86_64, armeabi-v7a or arm64-v8a");
        }

        if (!string.IsNullOrEmpty(ProjectName) && ProjectName.Contains(' '))
        {
            throw new ArgumentException($"ProjectName='{ProjectName}' should not not contain spaces.");
        }

        if (string.IsNullOrEmpty(AndroidSdk))
        {
            AndroidSdk = Environment.GetEnvironmentVariable("ANDROID_SDK_ROOT");
        }

        if (string.IsNullOrEmpty(AndroidNdk))
        {
            AndroidNdk = Environment.GetEnvironmentVariable("ANDROID_NDK_ROOT");
        }

        if (string.IsNullOrEmpty(AndroidSdk) || !Directory.Exists(AndroidSdk))
        {
            throw new ArgumentException($"Android SDK='{AndroidSdk}' was not found or empty (can be set via ANDROID_SDK_ROOT envvar).");
        }

        if (string.IsNullOrEmpty(AndroidNdk) || !Directory.Exists(AndroidNdk))
        {
            throw new ArgumentException($"Android NDK='{AndroidNdk}' was not found or empty (can be set via ANDROID_NDK_ROOT envvar).");
        }

        if (ForceInterpreter && ForceAOT)
        {
            throw new InvalidOperationException("Interpreter and AOT cannot be enabled at the same time");
        }

        if (!string.IsNullOrEmpty(DiagnosticPorts))
        {
            bool validDiagnosticsConfig = false;

            if (string.IsNullOrEmpty(RuntimeComponents))
            {
                validDiagnosticsConfig = false;
            }
            else if (RuntimeComponents.Equals("*", StringComparison.OrdinalIgnoreCase))
            {
                validDiagnosticsConfig = true;
            }
            else if (RuntimeComponents.Contains("diagnostics_tracing", StringComparison.OrdinalIgnoreCase))
            {
                validDiagnosticsConfig = true;
            }

            if (!validDiagnosticsConfig)
            {
                throw new ArgumentException("Using DiagnosticPorts require diagnostics_tracing runtime component.");
            }
        }

        // Try to get the latest build-tools version if not specified
        if (string.IsNullOrEmpty(BuildToolsVersion))
        {
            BuildToolsVersion = GetLatestBuildTools(AndroidSdk);
        }

        // Try to get the latest API level if not specified
        if (string.IsNullOrEmpty(BuildApiLevel))
        {
            BuildApiLevel = GetLatestApiLevel(AndroidSdk);
        }

        if (string.IsNullOrEmpty(MinApiLevel))
        {
            MinApiLevel = DefaultMinApiLevel;
        }

        // make sure BuildApiLevel >= MinApiLevel
        // only if these api levels are not "preview" (not integers)
        if (int.TryParse(BuildApiLevel, out int intApi) &&
            int.TryParse(MinApiLevel, out int intMinApi) &&
            intApi < intMinApi)
        {
            throw new ArgumentException($"BuildApiLevel={BuildApiLevel} <= MinApiLevel={MinApiLevel}. " +
                                        "Make sure you've downloaded some recent build-tools in Android SDK");
        }

        string buildToolsFolder = Path.Combine(AndroidSdk, "build-tools", BuildToolsVersion);

        if (!Directory.Exists(buildToolsFolder))
        {
            throw new ArgumentException($"{buildToolsFolder} was not found.");
        }

        var assemblerFiles       = new StringBuilder();
        var assemblerFilesToLink = new StringBuilder();
        var aotLibraryFiles      = new List <string>();

        foreach (ITaskItem file in Assemblies)
        {
            // use AOT files if available
            var obj     = file.GetMetadata("AssemblerFile");
            var llvmObj = file.GetMetadata("LlvmObjectFile");
            var lib     = file.GetMetadata("LibraryFile");

            if (!string.IsNullOrEmpty(obj))
            {
                var name = Path.GetFileNameWithoutExtension(obj);
                assemblerFiles.AppendLine($"add_library({name} OBJECT {obj})");
                assemblerFilesToLink.AppendLine($"    {name}");
            }

            if (!string.IsNullOrEmpty(llvmObj))
            {
                var name = Path.GetFileNameWithoutExtension(llvmObj);
                assemblerFilesToLink.AppendLine($"    {llvmObj}");
            }

            if (!string.IsNullOrEmpty(lib))
            {
                aotLibraryFiles.Add(lib);
            }
        }

        if (ForceAOT && assemblerFiles.Length == 0 && aotLibraryFiles.Count == 0)
        {
            throw new InvalidOperationException("Need list of AOT files.");
        }

        Directory.CreateDirectory(OutputDir);
        Directory.CreateDirectory(Path.Combine(OutputDir, "bin"));
        Directory.CreateDirectory(Path.Combine(OutputDir, "obj"));
        Directory.CreateDirectory(Path.Combine(OutputDir, "assets-tozip"));
        Directory.CreateDirectory(Path.Combine(OutputDir, "assets"));

        var extensionsToIgnore = new List <string> {
            ".so", ".a", ".gz"
        };

        if (StripDebugSymbols)
        {
            extensionsToIgnore.Add(".pdb");
            extensionsToIgnore.Add(".dbg");
        }

        // Copy sourceDir to OutputDir/assets-tozip (ignore native files)
        // these files then will be zipped and copied to apk/assets/assets.zip
        var assetsToZipDirectory = Path.Combine(OutputDir, "assets-tozip");

        Utils.DirectoryCopy(AppDir, assetsToZipDirectory, file =>
        {
            string fileName  = Path.GetFileName(file);
            string extension = Path.GetExtension(file);

            if (extensionsToIgnore.Contains(extension))
            {
                // ignore native files, those go to lib/%abi%
                // also, aapt is not happy about zip files
                return(false);
            }
            if (fileName.StartsWith("."))
            {
                // aapt complains on such files
                return(false);
            }
            return(true);
        });

        // add AOT .so libraries
        foreach (var aotlib in aotLibraryFiles)
        {
            File.Copy(aotlib, Path.Combine(assetsToZipDirectory, Path.GetFileName(aotlib)));
        }

        // tools:
        string dx               = Path.Combine(buildToolsFolder, "dx");
        string d8               = Path.Combine(buildToolsFolder, "d8");
        string aapt             = Path.Combine(buildToolsFolder, "aapt");
        string zipalign         = Path.Combine(buildToolsFolder, "zipalign");
        string apksigner        = Path.Combine(buildToolsFolder, "apksigner");
        string androidJar       = Path.Combine(AndroidSdk, "platforms", "android-" + BuildApiLevel, "android.jar");
        string androidToolchain = Path.Combine(AndroidNdk, "build", "cmake", "android.toolchain.cmake");
        string javac            = "javac";
        string cmake            = "cmake";
        string zip              = "zip";

        Utils.RunProcess(logger, zip, workingDir: assetsToZipDirectory, args: "-q -r ../assets/assets.zip .");
        Directory.Delete(assetsToZipDirectory, true);

        if (!File.Exists(androidJar))
        {
            throw new ArgumentException($"API level={BuildApiLevel} is not downloaded in Android SDK");
        }

        // 1. Build libmonodroid.so` via cmake

        string nativeLibraries = "";
        string monoRuntimeLib  = "";

        if (StaticLinkedRuntime)
        {
            monoRuntimeLib = Path.Combine(AppDir, "libmonosgen-2.0.a");
        }
        else
        {
            monoRuntimeLib = Path.Combine(AppDir, "libmonosgen-2.0.so");
        }

        if (!File.Exists(monoRuntimeLib))
        {
            throw new ArgumentException($"{monoRuntimeLib} was not found");
        }
        else
        {
            nativeLibraries += $"{monoRuntimeLib}{Environment.NewLine}";
        }

        if (StaticLinkedRuntime)
        {
            string[] staticComponentStubLibs = Directory.GetFiles(AppDir, "libmono-component-*-stub-static.a");
            bool     staticLinkAllComponents = false;
            string[] staticLinkedComponents  = Array.Empty <string>();

            if (!string.IsNullOrEmpty(RuntimeComponents) && RuntimeComponents.Equals("*", StringComparison.OrdinalIgnoreCase))
            {
                staticLinkAllComponents = true;
            }
            else if (!string.IsNullOrEmpty(RuntimeComponents))
            {
                staticLinkedComponents = RuntimeComponents.Split(";");
            }

            // by default, component stubs will be linked and depending on how mono runtime has been build,
            // stubs can disable or dynamic load components.
            foreach (string staticComponentStubLib in staticComponentStubLibs)
            {
                string componentLibToLink = staticComponentStubLib;
                if (staticLinkAllComponents)
                {
                    // static link component.
                    componentLibToLink = componentLibToLink.Replace("-stub-static.a", "-static.a", StringComparison.OrdinalIgnoreCase);
                }
                else
                {
                    foreach (string staticLinkedComponent in staticLinkedComponents)
                    {
                        if (componentLibToLink.Contains(staticLinkedComponent, StringComparison.OrdinalIgnoreCase))
                        {
                            // static link component.
                            componentLibToLink = componentLibToLink.Replace("-stub-static.a", "-static.a", StringComparison.OrdinalIgnoreCase);
                            break;
                        }
                    }
                }

                // if lib doesn't exist (primarly due to runtime build without static lib support), fallback linking stub lib.
                if (!File.Exists(componentLibToLink))
                {
                    logger.LogMessage(MessageImportance.High, $"\nCouldn't find static component library: {componentLibToLink}, linking static component stub library: {staticComponentStubLib}.\n");
                    componentLibToLink = staticComponentStubLib;
                }

                nativeLibraries += $"    {componentLibToLink}{Environment.NewLine}";
            }

            // There's a circular dependecy between static mono runtime lib and static component libraries.
            // Adding mono runtime lib before and after component libs will resolve issues with undefined symbols
            // due to circular dependecy.
            nativeLibraries += $"    {monoRuntimeLib}{Environment.NewLine}";
        }

        nativeLibraries += assemblerFilesToLink.ToString();

        string aotSources = assemblerFiles.ToString();

        string cmakeLists = Utils.GetEmbeddedResource("CMakeLists-android.txt")
                            .Replace("%MonoInclude%", monoRuntimeHeaders)
                            .Replace("%NativeLibrariesToLink%", nativeLibraries)
                            .Replace("%AotSources%", aotSources)
                            .Replace("%AotModulesSource%", string.IsNullOrEmpty(aotSources) ? "" : "modules.c");

        var defines = new StringBuilder();

        if (ForceInterpreter)
        {
            defines.AppendLine("add_definitions(-DFORCE_INTERPRETER=1)");
        }
        else if (ForceAOT)
        {
            defines.AppendLine("add_definitions(-DFORCE_AOT=1)");
            if (aotLibraryFiles.Count == 0)
            {
                defines.AppendLine("add_definitions(-DSTATIC_AOT=1)");
            }
        }

        if (!string.IsNullOrEmpty(DiagnosticPorts))
        {
            defines.AppendLine("add_definitions(-DDIAGNOSTIC_PORTS=\"" + DiagnosticPorts + "\")");
        }

        cmakeLists = cmakeLists.Replace("%Defines%", defines.ToString());

        File.WriteAllText(Path.Combine(OutputDir, "CMakeLists.txt"), cmakeLists);

        File.WriteAllText(Path.Combine(OutputDir, "monodroid.c"), Utils.GetEmbeddedResource("monodroid.c"));

        string cmakeGenArgs = $"-DCMAKE_TOOLCHAIN_FILE={androidToolchain} -DANDROID_ABI=\"{abi}\" -DANDROID_STL=none " +
                              $"-DANDROID_NATIVE_API_LEVEL={MinApiLevel} -B monodroid";

        string cmakeBuildArgs = "--build monodroid";

        if (StripDebugSymbols)
        {
            // Use "-s" to strip debug symbols, it complains it's unused but it works
            cmakeGenArgs   += " -DCMAKE_BUILD_TYPE=MinSizeRel -DCMAKE_C_FLAGS=\"-s -Wno-unused-command-line-argument\"";
            cmakeBuildArgs += " --config MinSizeRel";
        }
        else
        {
            cmakeGenArgs   += " -DCMAKE_BUILD_TYPE=Debug";
            cmakeBuildArgs += " --config Debug";
        }

        Utils.RunProcess(logger, cmake, workingDir: OutputDir, args: cmakeGenArgs);
        Utils.RunProcess(logger, cmake, workingDir: OutputDir, args: cmakeBuildArgs);

        // 2. Compile Java files

        string javaSrcFolder = Path.Combine(OutputDir, "src", "net", "dot");

        Directory.CreateDirectory(javaSrcFolder);

        string javaActivityPath = Path.Combine(javaSrcFolder, "MainActivity.java");
        string monoRunnerPath   = Path.Combine(javaSrcFolder, "MonoRunner.java");

        Regex checkNumerics = new Regex(@"\.(\d)");

        if (!string.IsNullOrEmpty(ProjectName) && checkNumerics.IsMatch(ProjectName))
        {
            ProjectName = checkNumerics.Replace(ProjectName, @"_$1");
        }

        string packageId = $"net.dot.{ProjectName}";

        File.WriteAllText(javaActivityPath,
                          Utils.GetEmbeddedResource("MainActivity.java")
                          .Replace("%EntryPointLibName%", Path.GetFileName(mainLibraryFileName)));
        if (!string.IsNullOrEmpty(NativeMainSource))
        {
            File.Copy(NativeMainSource, javaActivityPath, true);
        }

        string envVariables = "";

        foreach (ITaskItem item in EnvironmentVariables)
        {
            string name  = item.ItemSpec;
            string value = item.GetMetadata("Value");
            envVariables += $"\t\tsetEnv(\"{name}\", \"{value}\");\n";
        }

        string monoRunner = Utils.GetEmbeddedResource("MonoRunner.java")
                            .Replace("%EntryPointLibName%", Path.GetFileName(mainLibraryFileName))
                            .Replace("%EnvVariables%", envVariables);

        File.WriteAllText(monoRunnerPath, monoRunner);

        File.WriteAllText(Path.Combine(OutputDir, "AndroidManifest.xml"),
                          Utils.GetEmbeddedResource("AndroidManifest.xml")
                          .Replace("%PackageName%", packageId)
                          .Replace("%MinSdkLevel%", MinApiLevel));

        string javaCompilerArgs = $"-d obj -classpath src -bootclasspath {androidJar} -source 1.8 -target 1.8 ";

        Utils.RunProcess(logger, javac, javaCompilerArgs + javaActivityPath, workingDir: OutputDir);
        Utils.RunProcess(logger, javac, javaCompilerArgs + monoRunnerPath, workingDir: OutputDir);

        if (File.Exists(d8))
        {
            string[] classFiles = Directory.GetFiles(Path.Combine(OutputDir, "obj"), "*.class", SearchOption.AllDirectories);

            if (!classFiles.Any())
            {
                throw new InvalidOperationException("Didn't find any .class files");
            }

            Utils.RunProcess(logger, d8, $"--no-desugaring {string.Join(" ", classFiles)}", workingDir: OutputDir);
        }
        else
        {
            Utils.RunProcess(logger, dx, "--dex --output=classes.dex obj", workingDir: OutputDir);
        }

        // 3. Generate APK

        string debugModeArg = StripDebugSymbols ? string.Empty : "--debug-mode";
        string apkFile      = Path.Combine(OutputDir, "bin", $"{ProjectName}.unaligned.apk");

        Utils.RunProcess(logger, aapt, $"package -f -m -F {apkFile} -A assets -M AndroidManifest.xml -I {androidJar} {debugModeArg}", workingDir: OutputDir);

        var dynamicLibs = new List <string>();

        dynamicLibs.Add(Path.Combine(OutputDir, "monodroid", "libmonodroid.so"));
        dynamicLibs.AddRange(Directory.GetFiles(AppDir, "*.so").Where(file => Path.GetFileName(file) != "libmonodroid.so"));

        // add all *.so files to lib/%abi%/

        string[] dynamicLinkedComponents  = Array.Empty <string>();
        bool     dynamicLinkAllComponents = false;

        if (!StaticLinkedRuntime && !string.IsNullOrEmpty(RuntimeComponents) && RuntimeComponents.Equals("*", StringComparison.OrdinalIgnoreCase))
        {
            dynamicLinkAllComponents = true;
        }
        if (!string.IsNullOrEmpty(RuntimeComponents) && !StaticLinkedRuntime)
        {
            dynamicLinkedComponents = RuntimeComponents.Split(";");
        }

        Directory.CreateDirectory(Path.Combine(OutputDir, "lib", abi));
        foreach (var dynamicLib in dynamicLibs)
        {
            string dynamicLibName = Path.GetFileName(dynamicLib);
            string destRelative   = Path.Combine("lib", abi, dynamicLibName);

            if (dynamicLibName == "libmonosgen-2.0.so" && StaticLinkedRuntime)
            {
                // we link mono runtime statically into libmonodroid.so
                // make sure dynamic runtime is not included in package.
                if (File.Exists(destRelative))
                {
                    File.Delete(destRelative);
                }
                continue;
            }

            if (dynamicLibName.Contains("libmono-component-", StringComparison.OrdinalIgnoreCase))
            {
                bool includeComponent = dynamicLinkAllComponents;
                if (!StaticLinkedRuntime && !includeComponent)
                {
                    foreach (string dynamicLinkedComponent in dynamicLinkedComponents)
                    {
                        if (dynamicLibName.Contains(dynamicLinkedComponent, StringComparison.OrdinalIgnoreCase))
                        {
                            includeComponent = true;
                            break;
                        }
                    }
                }
                if (!includeComponent)
                {
                    // make sure dynamic component is not included in package.
                    if (File.Exists(destRelative))
                    {
                        File.Delete(destRelative);
                    }
                    continue;
                }
            }

            // NOTE: we can run android-strip tool from NDK to shrink native binaries here even more.

            File.Copy(dynamicLib, Path.Combine(OutputDir, destRelative), true);
            Utils.RunProcess(logger, aapt, $"add {apkFile} {destRelative}", workingDir: OutputDir);
        }
        Utils.RunProcess(logger, aapt, $"add {apkFile} classes.dex", workingDir: OutputDir);

        // 4. Align APK

        string alignedApk = Path.Combine(OutputDir, "bin", $"{ProjectName}.apk");

        AlignApk(apkFile, alignedApk, zipalign);
        // we don't need the unaligned one any more
        File.Delete(apkFile);

        // 5. Generate key (if needed) & sign the apk
        SignApk(alignedApk, apksigner);

        logger.LogMessage(MessageImportance.High, $"\nAPK size: {(new FileInfo(alignedApk).Length / 1000_000.0):0.#} Mb.\n");

        return(alignedApk, packageId);
    }
 // [END create_log_sink]
 // [START list_log_sinks]
 private void ListSinks()
 {
     var sinkClient = ConfigServiceV2Client.Create();
     ProjectName projectName = new ProjectName(s_projectId);
     var listOfSinks = sinkClient.ListSinks(ParentNameOneof.From(projectName),
         callSettings: RetryAWhile);
     foreach (var sink in listOfSinks)
     {
         Console.WriteLine($"{sink.Name} {sink.ToString()}");
     }
 }
Example #33
0
        /// <summary>
        /// The default project-file file-name-without-extension is the same as the project-name.
        /// </summary>
        public static FileNameWithoutExtension ProjectFileNameWithoutExtensionFromProjectName(ProjectName projectName)
        {
            var projectFileNameWithoutExtension = new FileNameWithoutExtension(projectName.Value);

            return(projectFileNameWithoutExtension);
        }
Example #34
0
        /// <summary>
        /// Tries to find a project by short name. Returns the project name if and only if it is non-ambiguous.
        /// </summary>
        public bool TryGetProjectNameByShortName(string name, out ProjectName projectName)
        {
            projectName = null;

            HashSet<ProjectName> projectNames;
            if (_shortNameCache.TryGetValue(name, out projectNames)) {
                // Get the item at the front of the queue
                projectName = projectNames.Count == 1 ? projectNames.Single() : null;

                // Only return true if the short name is unambiguous
                return projectName != null;
            }

            return false;
        }
Example #35
0
        /// <summary>
        /// The default project-name is the same as the project-file file-name-without-extension.
        /// </summary>
        public static ProjectName ProjectNameFromProjectFileNameWithoutExtension(FileNameWithoutExtension projectFileNameWithoutExtension)
        {
            var projectName = new ProjectName(projectFileNameWithoutExtension.Value);

            return(projectName);
        }
Example #36
0
 /// <summary>
 /// Removes a project from the project name dictionary.
 /// </summary>
 private void RemoveProjectName(ProjectName projectName)
 {
     _projectNamesCache.Remove(projectName.CustomUniqueName);
     _projectNamesCache.Remove(projectName.UniqueName);
     _projectNamesCache.Remove(projectName.FullName);
     _projectCache.Remove(projectName);
 }
Example #37
0
 public override int GetHashCode()
 {
     return(Start.GetHashCode() ^ End.GetHashCode() ^ ProjectName.GetHashCode() ^ Comment.GetHashCode());
 }
Example #38
0
    public override bool Execute()
    {
        Utils.Logger = Log;
        bool isDevice = Arch.Equals("arm64", StringComparison.InvariantCultureIgnoreCase);

        if (!File.Exists(Path.Combine(AppDir, MainLibraryFileName)))
        {
            throw new ArgumentException($"MainLibraryFileName='{MainLibraryFileName}' was not found in AppDir='{AppDir}'");
        }

        if (ProjectName.Contains(" "))
        {
            throw new ArgumentException($"ProjectName='{ProjectName}' should not contain spaces");
        }

        string[] excludes = Array.Empty <string>();
        if (ExcludeFromAppDir != null)
        {
            excludes = ExcludeFromAppDir
                       .Where(i => !string.IsNullOrEmpty(i.ItemSpec))
                       .Select(i => i.ItemSpec)
                       .ToArray();
        }

        string binDir = Path.Combine(AppDir, $"bin-{ProjectName}-{Arch}");

        if (!string.IsNullOrEmpty(OutputDirectory))
        {
            binDir = OutputDirectory;
        }
        Directory.CreateDirectory(binDir);

        var assemblerFiles = new List <string>();

        foreach (ITaskItem file in Assemblies)
        {
            // use AOT files if available
            var obj = file.GetMetadata("AssemblerFile");
            if (!string.IsNullOrEmpty(obj))
            {
                assemblerFiles.Add(obj);
            }
        }

        if ((isDevice || UseAotForSimulator) && !assemblerFiles.Any())
        {
            throw new InvalidOperationException("Need list of AOT files for device builds.");
        }

        // generate modules.m
        GenerateLinkAllFile(
            assemblerFiles,
            Path.Combine(binDir, "modules.m"));

        if (GenerateXcodeProject)
        {
            XcodeProjectPath = Xcode.GenerateXCode(ProjectName, MainLibraryFileName, assemblerFiles,
                                                   AppDir, binDir, MonoRuntimeHeaders, !isDevice, UseConsoleUITemplate, UseAotForSimulator, Optimized, NativeMainSource);

            if (BuildAppBundle)
            {
                if (isDevice && string.IsNullOrEmpty(DevTeamProvisioning))
                {
                    // DevTeamProvisioning shouldn't be empty for arm64 builds
                    Utils.LogInfo("DevTeamProvisioning is not set, BuildAppBundle step is skipped.");
                }
                else
                {
                    AppBundlePath = Xcode.BuildAppBundle(
                        Path.Combine(binDir, ProjectName, ProjectName + ".xcodeproj"),
                        Arch, Optimized, DevTeamProvisioning);
                }
            }
        }

        return(true);
    }
Example #39
0
    public (string apk, string packageId) BuildApk(
        string sourceDir, string abi, string entryPointLib, string monoRuntimeHeaders)
    {
        if (!Directory.Exists(sourceDir))
        {
            throw new ArgumentException($"sourceDir='{sourceDir}' is empty or doesn't exist");
        }

        if (string.IsNullOrEmpty(abi))
        {
            throw new ArgumentException("abi shoudln't be empty (e.g. x86, x86_64, armeabi, armeabi-v7a or arm64-v8a");
        }

        if (string.IsNullOrEmpty(entryPointLib))
        {
            throw new ArgumentException("entryPointLib shouldn't be empty");
        }

        if (!File.Exists(Path.Combine(sourceDir, entryPointLib)))
        {
            throw new ArgumentException($"{entryPointLib} was not found in sourceDir='{sourceDir}'");
        }

        if (string.IsNullOrEmpty(ProjectName))
        {
            ProjectName = Path.GetFileNameWithoutExtension(entryPointLib);
        }

        if (string.IsNullOrEmpty(OutputDir))
        {
            OutputDir = Path.Combine(sourceDir, "bin-" + abi);
        }

        if (ProjectName.Contains(' '))
        {
            throw new ArgumentException($"ProjectName='{ProjectName}' shouldn't not contain spaces.");
        }

        if (string.IsNullOrEmpty(AndroidSdk))
        {
            AndroidSdk = Environment.GetEnvironmentVariable("ANDROID_SDK_ROOT");
        }

        if (string.IsNullOrEmpty(AndroidNdk))
        {
            AndroidNdk = Environment.GetEnvironmentVariable("ANDROID_NDK_ROOT");
        }

        if (string.IsNullOrEmpty(AndroidSdk) || !Directory.Exists(AndroidSdk))
        {
            throw new ArgumentException($"Android SDK='{AndroidSdk}' was not found or empty (can be set via ANDROID_SDK_ROOT envvar).");
        }

        if (string.IsNullOrEmpty(AndroidNdk) || !Directory.Exists(AndroidNdk))
        {
            throw new ArgumentException($"Android NDK='{AndroidNdk}' was not found or empty (can be set via ANDROID_NDK_ROOT envvar).");
        }

        // Try to get the latest build-tools version if not specified
        if (string.IsNullOrEmpty(BuildToolsVersion))
        {
            BuildToolsVersion = GetLatestBuildTools(AndroidSdk);
        }

        // Try to get the latest API level if not specified
        if (string.IsNullOrEmpty(BuildApiLevel))
        {
            BuildApiLevel = GetLatestApiLevel(AndroidSdk);
        }

        if (string.IsNullOrEmpty(MinApiLevel))
        {
            MinApiLevel = DefaultMinApiLevel;
        }

        // make sure BuildApiLevel >= MinApiLevel
        // only if these api levels are not "preview" (not integers)
        if (int.TryParse(BuildApiLevel, out int intApi) &&
            int.TryParse(MinApiLevel, out int intMinApi) &&
            intApi < intMinApi)
        {
            throw new ArgumentException($"BuildApiLevel={BuildApiLevel} <= MinApiLevel={MinApiLevel}. " +
                                        "Make sure you've downloaded some recent build-tools in Android SDK");
        }

        string buildToolsFolder = Path.Combine(AndroidSdk, "build-tools", BuildToolsVersion);

        if (!Directory.Exists(buildToolsFolder))
        {
            throw new ArgumentException($"{buildToolsFolder} was not found.");
        }

        Directory.CreateDirectory(OutputDir);
        Directory.CreateDirectory(Path.Combine(OutputDir, "bin"));
        Directory.CreateDirectory(Path.Combine(OutputDir, "obj"));
        Directory.CreateDirectory(Path.Combine(OutputDir, "assets"));

        // Copy AppDir to OutputDir/assets (ignore native files)
        Utils.DirectoryCopy(sourceDir, Path.Combine(OutputDir, "assets"), file =>
        {
            string fileName  = Path.GetFileName(file);
            string extension = Path.GetExtension(file);
            // ignore native files, those go to lib/%abi%
            if (extension == ".so" || extension == ".a")
            {
                // ignore ".pdb" and ".dbg" to make APK smaller
                return(false);
            }
            if (fileName.StartsWith("."))
            {
                // aapt complains on such files
                return(false);
            }
            return(true);
        });

        // tools:
        string dx               = Path.Combine(buildToolsFolder, "dx");
        string aapt             = Path.Combine(buildToolsFolder, "aapt");
        string zipalign         = Path.Combine(buildToolsFolder, "zipalign");
        string apksigner        = Path.Combine(buildToolsFolder, "apksigner");
        string androidJar       = Path.Combine(AndroidSdk, "platforms", "android-" + BuildApiLevel, "android.jar");
        string androidToolchain = Path.Combine(AndroidNdk, "build", "cmake", "android.toolchain.cmake");
        string keytool          = "keytool";
        string javac            = "javac";
        string cmake            = "cmake";

        if (!File.Exists(androidJar))
        {
            throw new ArgumentException($"API level={BuildApiLevel} is not downloaded in Android SDK");
        }

        // 1. Build libruntime-android.so` via cmake

        string monoRuntimeLib = Path.Combine(sourceDir, "libmonosgen-2.0.a");

        if (!File.Exists(monoRuntimeLib))
        {
            throw new ArgumentException($"libmonosgen-2.0.a was not found in {sourceDir}");
        }

        string cmakeLists = Utils.GetEmbeddedResource("CMakeLists-android.txt")
                            .Replace("%MonoInclude%", monoRuntimeHeaders)
                            .Replace("%NativeLibrariesToLink%", monoRuntimeLib);

        File.WriteAllText(Path.Combine(OutputDir, "CMakeLists.txt"), cmakeLists);

        string runtimeAndroidSrc = Utils.GetEmbeddedResource("runtime-android.c")
                                   .Replace("%EntryPointLibName%", Path.GetFileName(entryPointLib));

        File.WriteAllText(Path.Combine(OutputDir, "runtime-android.c"), runtimeAndroidSrc);

        Utils.RunProcess(cmake, workingDir: OutputDir,
                         args: $"-DCMAKE_TOOLCHAIN_FILE={androidToolchain} -DANDROID_ABI=\"{abi}\" -DANDROID_STL=none " +
                         $"-DANDROID_NATIVE_API_LEVEL={MinApiLevel} -B runtime-android");
        Utils.RunProcess("make", workingDir: Path.Combine(OutputDir, "runtime-android"));

        // 2. Compile Java files

        string javaSrcFolder = Path.Combine(OutputDir, "src", "net", "dot");

        Directory.CreateDirectory(javaSrcFolder);

        string packageId = $"net.dot.{ProjectName}";

        File.WriteAllText(Path.Combine(javaSrcFolder, "MainActivity.java"),
                          Utils.GetEmbeddedResource("MainActivity.java"));
        File.WriteAllText(Path.Combine(javaSrcFolder, "MonoRunner.java"),
                          Utils.GetEmbeddedResource("MonoRunner.java"));
        File.WriteAllText(Path.Combine(OutputDir, "AndroidManifest.xml"),
                          Utils.GetEmbeddedResource("AndroidManifest.xml")
                          .Replace("%PackageName%", packageId)
                          .Replace("%MinSdkLevel%", MinApiLevel));

        string javaCompilerArgs = $"-d obj -classpath src -bootclasspath {androidJar} -source 1.8 -target 1.8 ";

        Utils.RunProcess(javac, javaCompilerArgs + Path.Combine(javaSrcFolder, "MainActivity.java"), workingDir: OutputDir);
        Utils.RunProcess(javac, javaCompilerArgs + Path.Combine(javaSrcFolder, "MonoRunner.java"), workingDir: OutputDir);
        Utils.RunProcess(dx, "--dex --output=classes.dex obj", workingDir: OutputDir);

        // 3. Generate APK

        string apkFile = Path.Combine(OutputDir, "bin", $"{ProjectName}.unaligned.apk");

        Utils.RunProcess(aapt, $"package -f -m -F {apkFile} -A assets -M AndroidManifest.xml -I {androidJar}", workingDir: OutputDir);

        var dynamicLibs = new List <string>();

        dynamicLibs.Add(Path.Combine(OutputDir, "runtime-android", "libruntime-android.so"));
        dynamicLibs.AddRange(Directory.GetFiles(sourceDir, "*.so"));

        // add all *.so files to lib/%abi%/
        Directory.CreateDirectory(Path.Combine(OutputDir, "lib", abi));
        foreach (var dynamicLib in dynamicLibs)
        {
            string destRelative = Path.Combine("lib", abi, Path.GetFileName(dynamicLib));
            File.Copy(dynamicLib, Path.Combine(OutputDir, destRelative), true);
            Utils.RunProcess(aapt, $"add {apkFile} {destRelative}", workingDir: OutputDir);
        }
        Utils.RunProcess(aapt, $"add {apkFile} classes.dex", workingDir: OutputDir);

        // 4. Align APK

        string alignedApk = Path.Combine(OutputDir, "bin", $"{ProjectName}.apk");

        Utils.RunProcess(zipalign, $"-v 4 {apkFile} {alignedApk}", workingDir: OutputDir);

        // 5. Generate key

        string signingKey = Path.Combine(OutputDir, "debug.keystore");

        if (!File.Exists(signingKey))
        {
            Utils.RunProcess(keytool, "-genkey -v -keystore debug.keystore -storepass android -alias " +
                             "androiddebugkey -keypass android -keyalg RSA -keysize 2048 -noprompt " +
                             "-dname \"CN=Android Debug,O=Android,C=US\"", workingDir: OutputDir, silent: true);
        }

        // 6. Sign APK

        Utils.RunProcess(apksigner, $"sign --min-sdk-version {MinApiLevel} --ks debug.keystore " +
                         $"--ks-pass pass:android --key-pass pass:android {alignedApk}", workingDir: OutputDir);

        return(alignedApk, packageId);
    }