public sealed override bool Execute()
        {
            try
            {
                LocateSolution();

                ConfigurationPath = ConfigHelper.GetConfigurationPath(ProjectDirectory);
                _config           = ConfigHelper.GetConfig(ConfigurationPath);
//#if DEBUG
//                if (!Debugger.IsAttached && !RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
//                    Debugger.Launch();
//#endif
                ExecuteInternal(this);
            }
            catch (Exception ex)
            {
#if DEBUG
                if (!Debugger.IsAttached && !RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
                {
                    Debugger.Launch();
                }
#endif
                Log.LogError($"Unhandled error while executing {GetType().Name}");
                Log.LogErrorFromException(ex);

                if (ConfigHelper.Exists(ConfigurationPath) &&
                    ConfigHelper.GetConfig(ConfigurationPath).Debug)
                {
                    Log.LogWarning("**************** DEBUG OUTPUT ****************");
                    Log.LogWarning(ex.ToString());
                }
            }

            return(!Log.HasLoggedErrors);
        }
        public void IncludesCompileConfigurationDirectory(string directory, string configuration, int expectedPaths)
        {
            var config = new BuildToolsConfig
            {
                Images = new ImageResize
                {
                    ConditionalDirectories = new Dictionary <string, IEnumerable <string> >
                    {
                        { directory, new[] { Path.Combine(ConfigPath, "images", directory) } },
                        { "Fake", new[] { Path.Combine(Environment.CurrentDirectory, "images", "Fake") } },
                    },
                    Directories = new List <string>
                    {
                        "images"
                    }
                }
            };

            var paths = ImageSearchUtil.GetSearchPaths(config, Platform.Android, configuration, ConfigPath);

            Assert.Equal(expectedPaths, paths.Count());
            Assert.Contains(paths, p => p == Path.Combine(ConfigPath, "images"));
            if (expectedPaths > 1)
            {
                Assert.Contains(paths, p => p == Path.Combine(ConfigPath, "images", directory));
            }
        }
        public static void SaveConfig(BuildToolsConfig config, string path)
        {
            var filePath = GetConfigFilePath(path);
            var json     = JsonConvert.SerializeObject(config, GetSerializerSettings());

            lock (lockObject)
            {
                File.WriteAllText(filePath, json);
            }
        }
        private bool ShouldEnableSecrets(BuildToolsConfig config)
        {
            var secretsFileExists = File.Exists(Path.Combine(ProjectDir, Constants.SecretsJsonFileName));
            var secretsConfig     = ConfigHelper.GetSecretsConfig(ProjectName, ProjectDir, config);

            if (secretsConfig is null)
            {
                // Intentionally disable this condition in CI incase somebody checked in the secrets.json
                return(secretsFileExists && !CIBuildEnvironmentUtils.IsBuildHost);
            }

            return(!secretsConfig.Disable);
        }
        public void PropertyHandlesDirectoryPathWithBackSlash()
        {
            var config = new BuildToolsConfig
            {
                Images = new ImageResize
                {
                    ConditionalDirectories = new Dictionary <string, IEnumerable <string> >(),
                    Directories            = new List <string>
                    {
                        @"images\test"
                    }
                }
            };

            var paths = ImageSearchUtil.GetSearchPaths(config, Platform.Android, "Debug", ConfigPath);

            Assert.Single(paths);
            Assert.Contains(paths, p => p == Path.Combine(ConfigPath, "images", "test"));
        }
        public void LogsAndRemovesPathsNotPresent()
        {
            var fakePath = Path.Combine(ConfigPath, "images", "Fake");
            var logger   = new Mock <ILog>();
            var config   = new BuildToolsConfig
            {
                Images = new ImageResize
                {
                    Directories = new List <string>
                    {
                        ConfigPath,
                        fakePath
                    }
                }
            };

            var paths = ImageSearchUtil.GetSearchPaths(config, Platform.Android, "Release", ConfigPath, logger: logger.Object);

            Assert.Single(paths);
            logger.Verify(x => x.LogWarning(It.IsAny <string>()));
        }
        public static void SaveDefaultConfig(string path)
        {
            var config = new BuildToolsConfig
            {
                ArtifactCopy = new ArtifactCopy {
                    Disable = false
                },
                AppConfig = new AppConfig
                {
                    Strategy = AppConfigStrategy.TransformOnly
                },
                AutomaticVersioning = new AutomaticVersioning
                {
                    Behavior      = VersionBehavior.PreferBuildNumber,
                    Environment   = VersionEnvironment.All,
                    VersionOffset = 0
                },
                Css = new XamarinCss
                {
                    Minify     = false,
                    BundleScss = false
                },
                Images = new ImageResize
                {
                    ConditionalDirectories = new Dictionary <string, IEnumerable <string> >
                    {
                        { "Debug", Array.Empty <string>() },
                        { "!Debug", Array.Empty <string>() },
                        { "iOS", Array.Empty <string>() },
                        { "Android", Array.Empty <string>() },
                    },
                    Directories = new List <string>()
                },
                Manifests = new TemplatedManifest
                {
                    Disable = false,
                    Token   = "$",
                    MissingTokensAsErrors = false,
                    VariablePrefix        = "Manifest_"
                },
                ReleaseNotes = new ReleaseNotesOptions
                {
                    Disable        = false,
                    CharacterLimit = 250,
                    CreateInRoot   = false,
                    FileName       = "ReleaseNotes.txt",
                    MaxCommit      = 10,
                    MaxDays        = 7
                },
                Environment = new EnvironmentSettings
                {
                    Configuration = new Dictionary <string, Dictionary <string, string> >
                    {
                        { "Debug", new Dictionary <string, string>() }
                    },
                    Defaults = new Dictionary <string, string>()
                }
            };

            var imagesRootDir = Path.Combine(path, "Images");

            if (Directory.Exists(imagesRootDir))
            {
                if (Directory.GetDirectories(imagesRootDir).Length > 0)
                {
                    var allDirectories = Directory.GetDirectories(imagesRootDir).Select(x => GetRelativePath(x, path));
                    config.Images.Directories = allDirectories.Where(x => !conditionalDefaults.Any(d => x.Equals(d.Key, StringComparison.InvariantCultureIgnoreCase)))
                                                .Select(x => Path.Combine("Images", x)).ToList();
                    config.Images.ConditionalDirectories = allDirectories.Where(x => conditionalDefaults.Any(d => x.Equals(d.Key, StringComparison.InvariantCultureIgnoreCase)))
                                                           .ToDictionary(x => conditionalDefaults[x], x => (IEnumerable <string>) new[] { Path.Combine("Images", x) });
                }
                else
                {
                    config.Images.Directories = new List <string> {
                        GetRelativePath(imagesRootDir, path)
                    };
                }
            }

            SaveConfig(config, path);

#if !DEBUG // Do not generate .gitignore for local debug builds
            var requiredContents = @"# Mobile.BuildTools
appsettings.json
appsettings.*.json
";
            var gitignoreFile    = Path.Combine(path, ".gitignore");
            if (!File.Exists(gitignoreFile))
            {
                File.WriteAllText(gitignoreFile, requiredContents);
            }
            else if (!File.ReadAllText(gitignoreFile).Contains(Constants.SecretsJsonFileName))
            {
                File.AppendAllText(gitignoreFile, $"\n\n{requiredContents}");
            }
#endif
        }
        public static IEnumerable <SettingsConfig> GetSettingsConfig(string projectName, BuildToolsConfig config)
        {
            if (config.AppSettings != null && config.AppSettings.Any(x => x.Key == projectName))
            {
                return(config.AppSettings[projectName]);
            }

            return(Array.Empty <SettingsConfig>());
        }
 private bool ShouldEnableSecrets(BuildToolsConfig config)
 {
     return(config.AppSettings is not null && config.AppSettings.ContainsKey(ProjectName) && config.AppSettings[ProjectName].Any());
 }
Exemple #10
0
        public static SecretsConfig GetSecretsConfig(string projectName, string projectDir, BuildToolsConfig config)
        {
            var configPath = Path.Combine(projectDir, Constants.SecretsConfigFileName);

            if (File.Exists(configPath))
            {
                var json = File.ReadAllText(configPath);
                return(JsonConvert.DeserializeObject <SecretsConfig>(json));
            }

            if (config.ProjectSecrets != null && config.ProjectSecrets.Any(x => x.Key == projectName))
            {
                return(config.ProjectSecrets.First(x => x.Key == projectName).Value);
            }

            return(null);
        }
        public static IEnumerable <string> GetSearchPaths(BuildToolsConfig config, Platform platform, string buildConfiguration, string buildToolsConfigPath, string additionalSearchPaths = null, bool?ignoreDefaultSearchPaths = null)
        {
            if (string.IsNullOrEmpty(buildToolsConfigPath))
            {
                return(Array.Empty <string>());
            }

            if (!File.GetAttributes(buildToolsConfigPath).HasFlag(FileAttributes.Directory))
            {
                buildToolsConfigPath = new FileInfo(buildToolsConfigPath).DirectoryName;
            }

            var searchPaths    = new List <string>();
            var imageConfig    = config.Images;
            var cliSearchPaths = !string.IsNullOrEmpty(additionalSearchPaths) ? additionalSearchPaths.Split(';') : Array.Empty <string>();

            if (cliSearchPaths.Any())
            {
                searchPaths.AddRange(additionalSearchPaths.Split(';').Select(x => GetSearchPath(x, buildToolsConfigPath)));
            }

            if (cliSearchPaths.Any() && ignoreDefaultSearchPaths.HasValue && ignoreDefaultSearchPaths.Value)
            {
                return(searchPaths.Distinct());
            }


            if (imageConfig?.Directories?.Any() ?? false)
            {
                searchPaths.AddRange(imageConfig.Directories.Select(x => GetSearchPath(x, buildToolsConfigPath)));
            }

            var monoandroidKey = GetKey(imageConfig?.ConditionalDirectories?.Keys, "monoandroid", "android", "droid");
            var xamariniOSKey  = GetKey(imageConfig?.ConditionalDirectories?.Keys, "xamarin.ios", "xamarinios", "ios", "apple");
            var xamarinMacKey  = GetKey(imageConfig?.ConditionalDirectories?.Keys, "xamarin.mac", "xamarinmac", "mac", "apple");
            var xamarinTVOSKey = GetKey(imageConfig?.ConditionalDirectories?.Keys, "xamarin.tvos", "xamarintvos", "tvos", "apple");

            var platformKeys = new[] { monoandroidKey, xamariniOSKey, xamarinMacKey, xamarinTVOSKey }.Where(x => x != null);

            switch (platform)
            {
            case Platform.Android:
                if (!string.IsNullOrEmpty(monoandroidKey))
                {
                    searchPaths.AddRange(imageConfig.ConditionalDirectories[monoandroidKey].Select(x => GetSearchPath(x, buildToolsConfigPath)));
                }
                break;

            case Platform.iOS:
                if (!string.IsNullOrEmpty(xamariniOSKey))
                {
                    searchPaths.AddRange(imageConfig.ConditionalDirectories[xamariniOSKey].Select(x => GetSearchPath(x, buildToolsConfigPath)));
                }
                break;

            case Platform.macOS:
                if (!string.IsNullOrEmpty(xamarinMacKey))
                {
                    searchPaths.AddRange(imageConfig.ConditionalDirectories[xamarinMacKey].Select(x => GetSearchPath(x, buildToolsConfigPath)));
                }
                break;

            case Platform.TVOS:
                if (!string.IsNullOrEmpty(xamarinTVOSKey))
                {
                    searchPaths.AddRange(imageConfig.ConditionalDirectories[xamarinTVOSKey].Select(x => GetSearchPath(x, buildToolsConfigPath)));
                }
                break;
            }

            // TODO: Make this even smarter with conditions like `Release || Store`... perhaps we also should consider evaluating the defined constants.
            var keys = imageConfig?.ConditionalDirectories?.Keys.Where(k => IsValidConditionalDirectory(k, platformKeys, buildConfiguration)) ?? Array.Empty <string>();

            foreach (var validCondition in keys)
            {
                searchPaths.AddRange(imageConfig.ConditionalDirectories[validCondition].Select(x => GetSearchPath(x, buildToolsConfigPath)));
            }

            return(searchPaths.Where(x => !string.IsNullOrEmpty(x)).Distinct());
        }