func contentsOfCartfileResolved(pth string) (string, error) {
	content, err := fileutil.ReadStringFromFile(pth)
	if err != nil {
		return "", err
	}
	return content, nil
}
func cocoapodsVersionFromPodfileLock(podfileLockPth string) (string, error) {
	content, err := fileutil.ReadStringFromFile(podfileLockPth)
	if err != nil {
		return "", err
	}
	return cocoapodsVersionFromPodfileLockContent(content), nil
}
func readLocalisedRecentChanges(recentChangesDir string) (map[string]string, error) {
	recentChangesMap := map[string]string{}

	pattern := filepath.Join(recentChangesDir, "whatsnew-*-*")
	recentChangesPaths, err := filepath.Glob(pattern)
	if err != nil {
		return map[string]string{}, err
	}

	pattern = `whatsnew-(?P<local>.*-.*)`
	re := regexp.MustCompile(pattern)

	for _, recentChangesPath := range recentChangesPaths {
		matches := re.FindStringSubmatch(recentChangesPath)
		if len(matches) == 2 {
			lanugage := matches[1]
			content, err := fileutil.ReadStringFromFile(recentChangesPath)
			if err != nil {
				return map[string]string{}, err
			}

			recentChangesMap[lanugage] = content
		}
	}

	return recentChangesMap, nil
}
func calabashAndroidVersionFromGemfileLock(gemfileLockPth string) (string, error) {
	content, err := fileutil.ReadStringFromFile(gemfileLockPth)
	if err != nil {
		return "", err
	}
	return calabashAndroidFromGemfileLockContent(content), nil
}
Exemple #5
0
// CheckIsSetupWasDoneForVersion ...
func CheckIsSetupWasDoneForVersion(ver string) bool {
	configPth := getBitriseConfigVersionSetupFilePath()
	cont, err := fileutil.ReadStringFromFile(configPth)
	if err != nil {
		return false
	}
	return (cont == ver)
}
func isCacheAvailable(srcDir string) (bool, error) {
	carthageDir := filepath.Join(srcDir, carthageDirName)
	if exist, err := pathutil.IsPathExists(carthageDir); err != nil {
		return false, err
	} else if !exist {
		return false, nil
	}

	buildDir := filepath.Join(carthageDir, buildDirName)
	if exist, err := pathutil.IsPathExists(buildDir); err != nil {
		return false, err
	} else if exist {
		pattern := filepath.Join(buildDir, "*")
		files, err := filepath.Glob(pattern)
		if err != nil {
			return false, err
		}
		if len(files) == 0 {
			return false, nil
		}
	} else {
		return false, nil
	}

	// read cahce
	cacheContent := ""

	cacheFilePth := filepath.Join(srcDir, carthageDirName, cacheFileName)
	if exist, err := pathutil.IsPathExists(cacheFilePth); err != nil {
		return false, err
	} else if exist {
		cacheContent, err = fileutil.ReadStringFromFile(cacheFilePth)
		if err != nil {
			return false, err
		}
	} else {
		return false, nil
	}

	swiftVersion, err := swiftVersion()
	if err != nil {
		return false, err
	}

	resolvedFilePath := filepath.Join(srcDir, resolvedFileName)
	resolved, err := contentsOfCartfileResolved(resolvedFilePath)
	if err != nil {
		return false, err
	}

	desiredCacheContent := fmt.Sprintf("--Swift version: %s --Swift version \n --%s: %s --%s", swiftVersion, resolvedFileName, resolved, resolvedFileName)

	return cacheContent == desiredCacheContent, nil
}
func testResultLogContent(pth string) (string, error) {
	if exist, err := pathutil.IsPathExists(pth); err != nil {
		return "", fmt.Errorf("Failed to check if path (%s) exist, error: %s", pth, err)
	} else if !exist {
		return "", fmt.Errorf("test result not exist at: %s", pth)
	}

	content, err := fileutil.ReadStringFromFile(pth)
	if err != nil {
		return "", fmt.Errorf("Failed to read file (%s), error: %s", pth, err)
	}

	return content, nil
}
Exemple #8
0
func scanXamarinProject(cmd *cobra.Command, args []string) error {
	absExportOutputDirPath, err := initExportOutputDir()
	if err != nil {
		return printXamarinScanFinishedWithError("Failed to prepare Export directory: %s", err)
	}

	logOutput := ""
	xamarinCmd := xamarin.CommandModel{}
	if paramXamarinOutputLogFilePath != "" {
		xamLog, err := fileutil.ReadStringFromFile(paramXamarinOutputLogFilePath)
		if err != nil {
			return printXamarinScanFinishedWithError("Failed to read log from the specified log file, error: %s", err)
		}
		logOutput = xamLog
	} else {
		// --- Inputs ---

		// Xamarin Solution Path
		xamarinCmd.SolutionFilePath = paramXamarinSolutionFilePath
		if xamarinCmd.SolutionFilePath == "" {
			askText := `Please drag-and-drop your Xamarin Solution (` + colorstring.Green(".sln") + `)
   file here, and then hit Enter`
			fmt.Println()
			projpth, err := goinp.AskForPath(askText)
			if err != nil {
				return printXamarinScanFinishedWithError("Failed to read input: %s", err)
			}
			xamarinCmd.SolutionFilePath = projpth
		}
		log.Debugf("xamSolutionPth: %s", xamarinCmd.SolutionFilePath)

		xamSln, err := solution.New(xamarinCmd.SolutionFilePath, true)
		if err != nil {
			return printXamarinScanFinishedWithError("Failed to analyze Xamarin solution: %s", err)
		}
		log.Debugf("xamSln: %#v", xamSln)
		// filter only the iOS "app"" projects
		xamarinProjectsToChooseFrom := []project.Model{}
		for _, aXamarinProject := range xamSln.ProjectMap {
			switch aXamarinProject.ProjectType {
			case constants.ProjectTypeIOS, constants.ProjectTypeTvOS, constants.ProjectTypeMacOS:
				if aXamarinProject.OutputType == "exe" {
					// possible project
					xamarinProjectsToChooseFrom = append(xamarinProjectsToChooseFrom, aXamarinProject)
				}
			default:
				continue
			}
		}
		log.Debugf("len(xamarinProjectsToChooseFrom): %#v", len(xamarinProjectsToChooseFrom))
		log.Debugf("xamarinProjectsToChooseFrom: %#v", xamarinProjectsToChooseFrom)

		// Xamarin Project
		selectedXamarinProject := project.Model{}
		{
			if len(xamarinProjectsToChooseFrom) < 1 {
				return printXamarinScanFinishedWithError(
					"No acceptable Project found in the provided Solution, or none can be used for iOS Archive.",
				)
			}

			if paramXamarinProjectName != "" {
				// project specified via flag/param
				for _, aProj := range xamarinProjectsToChooseFrom {
					if paramXamarinProjectName == aProj.Name {
						selectedXamarinProject = aProj
						break
					}
				}
				if selectedXamarinProject.Name == "" {
					return printXamarinScanFinishedWithError(
						`Invalid Project specified (%s), either not found in the provided Solution or it can't be used for iOS "Archive for Publishing".`,
						paramXamarinProjectName)
				}
			} else {
				// no project CLI param specified
				if len(xamarinProjectsToChooseFrom) == 1 {
					selectedXamarinProject = xamarinProjectsToChooseFrom[0]
				} else {
					projectNames := []string{}
					for _, aProj := range xamarinProjectsToChooseFrom {
						projectNames = append(projectNames, aProj.Name)
					}
					fmt.Println()
					answerValue, err := goinp.SelectFromStrings(
						`Select the Project Name you use for "Archive for Publishing" (usually ends with ".iOS", e.g.: MyProject.iOS)?`,
						projectNames,
					)
					if err != nil {
						return printXamarinScanFinishedWithError("Failed to select Project: %s", err)
					}
					log.Debugf("selected project: %v", answerValue)
					for _, aProj := range xamarinProjectsToChooseFrom {
						if answerValue == aProj.Name {
							selectedXamarinProject = aProj
							break
						}
					}
				}
			}
		}
		xamarinCmd.ProjectName = selectedXamarinProject.Name
		log.Debugf("xamarinCmd.ProjectName: %s", xamarinCmd.ProjectName)

		log.Debugf("selectedXamarinProject.Configs: %#v", selectedXamarinProject.Configs)

		// Xamarin Configuration Name
		selectedXamarinConfigurationName := ""
		{
			acceptableConfigs := []string{}
			for configName, aConfig := range selectedXamarinProject.Configs {
				if aConfig.Platform == "iPhone" {
					if aConfig.Configuration == "Release" {
						// ios & tvOS app
						acceptableConfigs = append(acceptableConfigs, configName)
					}
				} else if aConfig.Platform == "x86" {
					if aConfig.Configuration == "Release" || aConfig.Configuration == "Debug" {
						// MacOS app
						acceptableConfigs = append(acceptableConfigs, configName)
					}
				}
			}
			if len(acceptableConfigs) < 1 {
				return printXamarinScanFinishedWithError(
					`No acceptable Configuration found in the provided Solution and Project, or none can be used for iOS "Archive for Publishing".`,
				)
			}

			if paramXamarinConfigurationName != "" {
				// configuration specified via flag/param
				for _, aConfigName := range acceptableConfigs {
					if paramXamarinConfigurationName == aConfigName {
						selectedXamarinConfigurationName = aConfigName
						break
					}
				}
				if selectedXamarinConfigurationName == "" {
					return printXamarinScanFinishedWithError(
						"Invalid Configuration specified (%s), either not found in the provided Solution and Project or it can't be used for iOS Archive.",
						paramXamarinConfigurationName)
				}
			} else {
				// no configuration CLI param specified
				if len(acceptableConfigs) == 1 {
					selectedXamarinConfigurationName = acceptableConfigs[0]
				} else {
					fmt.Println()
					answerValue, err := goinp.SelectFromStrings(
						`Select the Configuration Name you use for "Archive for Publishing" (usually Release|iPhone)?`,
						acceptableConfigs,
					)
					if err != nil {
						return printXamarinScanFinishedWithError("Failed to select Configuration: %s", err)
					}
					log.Debugf("selected configuration: %v", answerValue)
					selectedXamarinConfigurationName = answerValue
				}
			}
		}
		if selectedXamarinConfigurationName == "" {
			return printXamarinScanFinishedWithError(
				`No acceptable Configuration found (it was empty) in the provided Solution and Project, or none can be used for iOS "Archive for Publishing".`,
			)
		}
		xamarinCmd.ConfigurationName = selectedXamarinConfigurationName

		fmt.Println()
		fmt.Println()
		log.Println(`🔦  Running a Build, to get all the required code signing settings...`)
		xamLogOut, err := xamarinCmd.GenerateLog()
		logOutput = xamLogOut
		// save the xamarin output into a debug log file
		logOutputFilePath := filepath.Join(absExportOutputDirPath, "xamarin-build-output.log")
		{
			log.Infof("  💡  "+colorstring.Yellow("Saving xamarin output into file")+": %s", logOutputFilePath)
			if logWriteErr := fileutil.WriteStringToFile(logOutputFilePath, logOutput); logWriteErr != nil {
				log.Errorf("Failed to save xamarin build output into file (%s), error: %s", logOutputFilePath, logWriteErr)
			} else if err != nil {
				log.Infoln(colorstring.Yellow("Please check the logfile (" + logOutputFilePath + ") to see what caused the error"))
				log.Infoln(colorstring.Red(`and make sure that you can "Archive for Publishing" this project from Xamarin!`))
				fmt.Println()
				log.Infoln("Open the project: ", xamarinCmd.SolutionFilePath)
				log.Infoln(`And do "Archive for Publishing", after selecting the Configuration: `, xamarinCmd.ConfigurationName)
				fmt.Println()
			}
		}
		if err != nil {
			return printXamarinScanFinishedWithError("Failed to run xamarin build command: %s", err)
		}
	}

	codeSigningSettings, err := xamarinCmd.ScanCodeSigningSettings(logOutput)
	if err != nil {
		return printXamarinScanFinishedWithError("Failed to detect code signing settings: %s", err)
	}
	log.Debugf("codeSigningSettings: %#v", codeSigningSettings)

	return exportCodeSigningFiles("Xamarin Studio", absExportOutputDirPath, codeSigningSettings)
}
func analyzeSolution(pth string, analyzeProjects bool) (Model, error) {
	absPth, err := pathutil.AbsPath(pth)
	if err != nil {
		return Model{}, fmt.Errorf("Failed to expand path (%s), error: %s", pth, err)
	}

	fileName := filepath.Base(absPth)
	ext := filepath.Ext(absPth)
	fileName = strings.TrimSuffix(fileName, ext)

	solution := Model{
		Pth:        absPth,
		Name:       fileName,
		ConfigMap:  map[string]string{},
		ProjectMap: map[string]project.Model{},
	}

	isSolutionConfigurationPlatformsSection := false
	isProjectConfigurationPlatformsSection := false

	solutionDir := filepath.Dir(absPth)

	content, err := fileutil.ReadStringFromFile(absPth)
	if err != nil {
		return Model{}, fmt.Errorf("failed to read solution (%s), error: %s", absPth, err)
	}

	scanner := bufio.NewScanner(strings.NewReader(content))
	for scanner.Scan() {
		line := strings.TrimSpace(scanner.Text())

		// Projects
		if matches := regexp.MustCompile(solutionProjectsPattern).FindStringSubmatch(line); len(matches) == 5 {
			ID := strings.ToUpper(matches[1])
			projectName := matches[2]
			projectID := strings.ToUpper(matches[4])
			projectRelativePth := utility.FixWindowsPath(matches[3])
			projectPth := filepath.Join(solutionDir, projectRelativePth)

			if strings.HasSuffix(projectPth, constants.CSProjExt) ||
				strings.HasSuffix(projectPth, constants.SHProjExt) ||
				strings.HasSuffix(projectPth, constants.FSProjExt) {

				project := project.Model{
					ID:   projectID,
					Name: projectName,
					Pth:  projectPth,

					ConfigMap: map[string]string{},
					Configs:   map[string]project.ConfigurationPlatformModel{},
				}
				solution.ProjectMap[projectID] = project
			}

			solution.ID = ID

			continue
		}

		// GlobalSection(SolutionConfigurationPlatforms) = preSolution
		if isSolutionConfigurationPlatformsSection {
			if match := regexp.MustCompile(solutionConfigurationPlatformsSectionEndPattern).FindString(line); match != "" {
				isSolutionConfigurationPlatformsSection = false
				continue
			}
		}

		if match := regexp.MustCompile(solutionConfigurationPlatformsSectionStartPattern).FindString(line); match != "" {
			isSolutionConfigurationPlatformsSection = true
			continue
		}

		if isSolutionConfigurationPlatformsSection {
			if matches := regexp.MustCompile(solutionConfigurationPlatformPattern).FindStringSubmatch(line); len(matches) == 5 {
				configuration := matches[1]
				platform := matches[2]

				mappedConfiguration := matches[3]
				mappedPlatform := matches[4]

				solution.ConfigMap[utility.ToConfig(configuration, platform)] = utility.ToConfig(mappedConfiguration, mappedPlatform)

				continue
			}
		}

		// GlobalSection(ProjectConfigurationPlatforms) = postSolution
		if isProjectConfigurationPlatformsSection {
			if match := regexp.MustCompile(projectConfigurationPlatformsSectionEndPattern).FindString(line); match != "" {
				isProjectConfigurationPlatformsSection = false
				continue
			}
		}

		if match := regexp.MustCompile(projectConfigurationPlatformsSectionStartPattern).FindString(line); match != "" {
			isProjectConfigurationPlatformsSection = true
			continue
		}

		if isProjectConfigurationPlatformsSection {
			if matches := regexp.MustCompile(projectConfigurationPlatformPattern).FindStringSubmatch(line); len(matches) == 6 {
				projectID := strings.ToUpper(matches[1])
				solutionConfiguration := matches[2]
				solutionPlatform := matches[3]
				projectConfiguration := matches[4]
				projectPlatform := matches[5]
				if projectPlatform == "Any CPU" {
					projectPlatform = "AnyCPU"
				}

				project, found := solution.ProjectMap[projectID]
				if !found {
					return Model{}, fmt.Errorf("no project found with ID: %s", projectID)
				}

				project.ConfigMap[utility.ToConfig(solutionConfiguration, solutionPlatform)] = utility.ToConfig(projectConfiguration, projectPlatform)

				solution.ProjectMap[projectID] = project

				continue
			}
		}
	}
	if err := scanner.Err(); err != nil {
		return Model{}, err
	}

	if analyzeProjects {
		projectMap := map[string]project.Model{}

		for projectID, proj := range solution.ProjectMap {
			projectDefinition, err := project.New(proj.Pth)
			if err != nil {
				return Model{}, fmt.Errorf("failed to analyze project (%s), error: %s", proj.Pth, err)
			}

			projectDefinition.Name = proj.Name
			projectDefinition.Pth = proj.Pth
			projectDefinition.ConfigMap = proj.ConfigMap

			projectMap[projectID] = projectDefinition
		}

		solution.ProjectMap = projectMap
	}

	return solution, nil
}
Exemple #10
0
// WriteChangelog ...
func WriteChangelog(commits, taggedCommits []git.CommitModel, config Config, append bool) error {
	newChangelog := generateChangelogContent(commits, taggedCommits, config.Release.Version)

	headerStr := ""
	footerStr := ""
	contentStr := ""

	//
	// Generate changelog header
	if config.Changelog.HeaderTemplate == "" && config.Changelog.FooterTemplate == "" {

		log.Debug()
		log.Debug("Write changelog WITHOUT header and footer template")
	}

	// Header
	if config.Changelog.HeaderTemplate != "" {

		log.Debug()
		log.Debug("Write changelog with header and footer template")

		headerTemplate := template.New("changelog_header").Funcs(changelogTemplateFuncMap)
		headerTemplate, err := headerTemplate.Parse(config.Changelog.HeaderTemplate)
		if err != nil {
			log.Fatalf("Failed to parse header template, error: %#v", err)
		}

		var headerBytes bytes.Buffer
		err = headerTemplate.Execute(&headerBytes, newChangelog)
		if err != nil {
			log.Fatalf("Failed to execute layout template, error: %#v", err)
		}
		headerStr = headerBytes.String()
		headerStr += "\n\n" + separator + "\n"
	}

	// Footer
	if config.Changelog.FooterTemplate != "" {
		footerTemplate := template.New("changelog_footer").Funcs(changelogTemplateFuncMap)
		footerTemplate, err := footerTemplate.Parse(config.Changelog.FooterTemplate)
		if err != nil {
			log.Fatalf("Failed to parse footer template, error: %#v", err)
		}

		var footerBytes bytes.Buffer
		err = footerTemplate.Execute(&footerBytes, newChangelog)
		if err != nil {
			log.Fatalf("Failed to execute footer template, error: %#v", err)
		}
		footerStr = footerBytes.String()
		footerStr = separator + "\n\n" + footerStr
	}

	log.Debug()
	log.Debug("Layout header: %s", headerStr)
	log.Debug("Layout footer: %s", footerStr)

	//
	// Generate changelog content
	changelogContentTemplateStr := ChangelogContentTemplate
	if config.Changelog.ContentTemplate != "" {
		changelogContentTemplateStr = config.Changelog.ContentTemplate
	}

	contentTemplate := template.New("changelog_content").Funcs(changelogTemplateFuncMap)
	contentTemplate, err := contentTemplate.Parse(changelogContentTemplateStr)
	if err != nil {
		log.Fatalf("Failed to parse content template, error: %#v", err)
	}

	var newContentBytes bytes.Buffer
	err = contentTemplate.Execute(&newContentBytes, newChangelog)
	if err != nil {
		log.Fatalf("Failed to execute template, error: %#v", err)
	}
	newContentStr := newContentBytes.String()

	newContentSplit := strings.Split(newContentStr, "\n")
	if len(newContentSplit) > 0 {
		newContentSplit = newContentSplit[0 : len(newContentSplit)-1]
		newContentStr = strings.Join(newContentSplit, "\n")
	}

	log.Debug()
	log.Debug("Content:")
	for _, line := range strings.Split(newContentStr, "\n") {
		log.Debug("%s", line)
	}

	// Join header and content
	if append {

		log.Debug()
		log.Debug("Previous changelog exist, append new conent")

		prevChangelogStr, err := fileutil.ReadStringFromFile(config.Changelog.Path)
		if err != nil {
			return err
		}

		prevContentStr := ""
		if config.Changelog.HeaderTemplate != "" && config.Changelog.FooterTemplate != "" {
			tmpPrevContentStr, err := parseChangelog(prevChangelogStr)
			if err != nil {
				log.Warnf("Failed to parse previous changelog: %s", err)
			} else {
				prevContentStr = tmpPrevContentStr
			}
		} else {
			prevContentStr = prevChangelogStr
		}

		log.Debug()
		log.Debug("Prev content:")

		for _, line := range strings.Split(prevContentStr, "\n") {
			log.Debugf("%s", line)
		}

		contentStr = fmt.Sprintf("%s\n%s", newContentStr, prevContentStr)

		log.Debug()
		log.Debug("Merged content:")

		contentSplits := strings.Split(contentStr, "\n")

		for _, line := range contentSplits {
			log.Debugf("%s", line)
		}
	} else {

		log.Debug()
		log.Debug("NO previous changelog exist")

		contentStr = newContentStr
	}

	changelogStr := headerStr + "\n" + contentStr + "\n" + footerStr

	return fileutil.WriteStringToFile(config.Changelog.Path, changelogStr)
}
Exemple #11
0
func analyzeTargetDefinition(project Model, pth string) (Model, error) {
	configurationPlatform := ConfigurationPlatformModel{}

	isPropertyGroupSection := false
	isProjectReferenceSection := false

	projectDir := filepath.Dir(pth)

	projectDefinitionFileContent, err := fileutil.ReadStringFromFile(pth)
	if err != nil {
		return Model{}, fmt.Errorf("failed to read project (%s), error: %s", pth, err)
	}

	scanner := bufio.NewScanner(strings.NewReader(projectDefinitionFileContent))
	for scanner.Scan() {
		line := strings.TrimSpace(scanner.Text())

		// Target definition
		if matches := regexp.MustCompile(targetDefinitionPattern).FindStringSubmatch(line); len(matches) == 2 {
			targetDefinitionRelativePth := utility.FixWindowsPath(matches[1])

			if !strings.Contains(targetDefinitionRelativePth, "$(MSBuild") {
				targetDefinitionPth := filepath.Join(projectDir, targetDefinitionRelativePth)

				if exist, err := pathutil.IsPathExists(targetDefinitionPth); err != nil {
					return Model{}, err
				} else if exist {
					proj, err := analyzeTargetDefinition(project, targetDefinitionPth)
					if err != nil {
						return Model{}, err
					}
					project = proj
				}
			}

			continue
		}

		// ProjectGuid
		if matches := regexp.MustCompile(guidPattern).FindStringSubmatch(line); len(matches) == 2 {
			project.ID = matches[1]
			continue
		}

		// OutputType
		if matches := regexp.MustCompile(outputTpyePattern).FindStringSubmatch(line); len(matches) == 2 {
			project.OutputType = strings.ToLower(matches[1])
			continue
		}

		// AssemblyName
		if matches := regexp.MustCompile(assemblyNamePattern).FindStringSubmatch(line); len(matches) == 2 {
			project.AssemblyName = matches[1]
			continue
		}

		// AndroidManifest
		if matches := regexp.MustCompile(manifestPattern).FindStringSubmatch(line); len(matches) == 2 {
			manifestRelativePth := utility.FixWindowsPath(matches[1])

			project.ManifestPth = filepath.Join(projectDir, manifestRelativePth)
			continue
		}

		// AndroidApplication
		if match := regexp.MustCompile(androidApplicationPattern).FindString(line); match != "" {
			project.AndroidApplication = true
			continue
		}

		//
		// PropertyGroups

		if isPropertyGroupSection {
			if match := regexp.MustCompile(propertyGroupEndPattern).FindString(line); match != "" {
				project.Configs[utility.ToConfig(configurationPlatform.Configuration, configurationPlatform.Platform)] = configurationPlatform

				configurationPlatform = ConfigurationPlatformModel{}

				isPropertyGroupSection = false
				continue
			}
		}

		// PropertyGroup with Condition (Configuration & Platform)
		if matches := regexp.MustCompile(propertyGroupWithConditionConfigurationAndPlatformPattern).FindStringSubmatch(line); len(matches) == 3 {
			platform := matches[2]
			/*
				if platform == "AnyCPU" {
					platform = "Any CPU"
				}
			*/

			configurationPlatform = ConfigurationPlatformModel{
				Configuration: matches[1],
				Platform:      platform,
			}

			isPropertyGroupSection = true
			continue
		}

		// PropertyGroup with Condition (Configuration)
		if matches := regexp.MustCompile(propertyGroupWithConditionConfigurationPattern).FindStringSubmatch(line); len(matches) == 2 {
			configurationPlatform = ConfigurationPlatformModel{
				Configuration: matches[1],
			}

			isPropertyGroupSection = true
			continue
		}

		// PropertyGroup with Condition (Platform)
		if matches := regexp.MustCompile(propertyGroupWithConditionPlatformPattern).FindStringSubmatch(line); len(matches) == 2 {
			platform := matches[2]
			/*
				if platform == "AnyCPU" {
					platform = "Any CPU"
				}
			*/

			configurationPlatform = ConfigurationPlatformModel{
				Platform: platform,
			}

			isPropertyGroupSection = true
			continue
		}

		if isPropertyGroupSection {
			// OutputPath
			if matches := regexp.MustCompile(outputPathPattern).FindStringSubmatch(line); len(matches) == 2 {
				outputRelativePth := utility.FixWindowsPath(matches[1])
				strings.Replace(outputRelativePth, "$(Configuration)", configurationPlatform.Configuration, -1)
				strings.Replace(outputRelativePth, "$(Platform)", configurationPlatform.Platform, -1)

				configurationPlatform.OutputDir = filepath.Join(projectDir, outputRelativePth)
				continue
			}

			// MtouchArch
			if matches := regexp.MustCompile(mtouchArchPattern).FindStringSubmatch(line); len(matches) == 2 {
				configurationPlatform.MtouchArchs = utility.SplitAndStripList(matches[1], ",")
				continue
			}

			// AndroidKeyStore
			if match := regexp.MustCompile(androidKeystorePattern).FindString(line); match != "" {
				configurationPlatform.SignAndroid = true
				continue
			}

			/*
				// IpaPackageName
				if match := regexp.MustCompile(ipaPackageNamePattern).FindString(line); match != "" {
					configurationPlatform.IpaPackage = true
					continue
				}
			*/

			// BuildIpa ...
			if match := regexp.MustCompile(buildIpaPattern).FindString(line); match != "" {
				configurationPlatform.BuildIpa = true
				continue
			}
		}

		//
		// API

		// ProjectTypeGuids
		if matches := regexp.MustCompile(typeGUIDsPattern).FindStringSubmatch(line); len(matches) == 2 {
			projectType := constants.ProjectTypeUnknown
			projectTypeList := strings.Split(matches[1], ";")
			for _, guid := range projectTypeList {
				guid = strings.TrimPrefix(guid, "{")
				guid = strings.TrimSuffix(guid, "}")

				projectType, err = constants.ParseProjectTypeGUID(guid)
				if err == nil {
					break
				}
			}

			project.ProjectType = projectType
			continue
		}

		if match := regexp.MustCompile(referenceXamarinUITestPattern).FindString(line); match != "" {
			project.TestFramworks = append(project.TestFramworks, constants.XamarinUITest)
			continue
		}

		if match := regexp.MustCompile(referenceNunitFramework).FindString(line); match != "" {
			project.TestFramworks = append(project.TestFramworks, constants.NunitTest)
			continue
		}

		if match := regexp.MustCompile(referenceNunitLiteFramework).FindString(line); match != "" {
			project.TestFramworks = append(project.TestFramworks, constants.NunitLiteTest)
			continue
		}

		//
		// ProjectReference

		if isProjectReferenceSection {
			if match := regexp.MustCompile(projectRefernceEndPattern).FindString(line); match != "" {
				isProjectReferenceSection = false
			}
		}

		// ProjectReference
		if matches := regexp.MustCompile(projectRefernceStartPattern).FindStringSubmatch(line); len(matches) == 2 {
			/*
				projectRelativePth := fixWindowsPath(matches[1])
				projectPth := filepath.Join(projectDir, projectRelativePth)
			*/

			isProjectReferenceSection = true
			continue
		}

		if isProjectReferenceSection {
			if matches := regexp.MustCompile(referredProjectIDPattern).FindStringSubmatch(line); len(matches) == 2 {
				project.ReferredProjectIDs = append(project.ReferredProjectIDs, matches[1])
			}
			continue
		}

	}
	if err := scanner.Err(); err != nil {
		return Model{}, err
	}

	return project, nil
}
Exemple #12
0
func scanXcodeProject(cmd *cobra.Command, args []string) error {
	absExportOutputDirPath, err := initExportOutputDir()
	if err != nil {
		return printXcodeScanFinishedWithError("Failed to prepare Export directory: %s", err)
	}

	xcodebuildOutput := ""
	xcodeCmd := xcode.CommandModel{}
	if paramXcodebuildOutputLogFilePath != "" {
		xcLog, err := fileutil.ReadStringFromFile(paramXcodebuildOutputLogFilePath)
		if err != nil {
			return printXcodeScanFinishedWithError("Failed to read log from the specified log file, error: %s", err)
		}
		xcodebuildOutput = xcLog
	} else {
		projectPath := paramXcodeProjectFilePath
		if projectPath == "" {
			askText := `Please drag-and-drop your Xcode Project (` + colorstring.Green(".xcodeproj") + `)
   or Workspace (` + colorstring.Green(".xcworkspace") + `) file, the one you usually open in Xcode,
   then hit Enter.

  (Note: if you have a Workspace file you should most likely use that)`
			fmt.Println()
			projpth, err := goinp.AskForPath(askText)
			if err != nil {
				return printXcodeScanFinishedWithError("Failed to read input: %s", err)
			}
			projectPath = projpth
		}
		log.Debugf("projectPath: %s", projectPath)
		xcodeCmd.ProjectFilePath = projectPath

		schemeToUse := paramXcodeScheme
		if schemeToUse == "" {
			fmt.Println()
			fmt.Println()
			log.Println("🔦  Scanning Schemes ...")
			schemes, err := xcodeCmd.ScanSchemes()
			if err != nil {
				return printXcodeScanFinishedWithError("Failed to scan Schemes: %s", err)
			}
			log.Debugf("schemes: %v", schemes)

			fmt.Println()
			selectedScheme, err := goinp.SelectFromStrings("Select the Scheme you usually use in Xcode", schemes)
			if err != nil {
				return printXcodeScanFinishedWithError("Failed to select Scheme: %s", err)
			}
			log.Debugf("selected scheme: %v", selectedScheme)
			schemeToUse = selectedScheme
		}
		xcodeCmd.Scheme = schemeToUse

		fmt.Println()
		fmt.Println()
		log.Println("🔦  Running an Xcode Archive, to get all the required code signing settings...")
		xcLog, err := xcodeCmd.GenerateLog()
		xcodebuildOutput = xcLog
		// save the xcodebuild output into a debug log file
		xcodebuildOutputFilePath := filepath.Join(absExportOutputDirPath, "xcodebuild-output.log")
		{
			log.Infof("  💡  "+colorstring.Yellow("Saving xcodebuild output into file")+": %s", xcodebuildOutputFilePath)
			if logWriteErr := fileutil.WriteStringToFile(xcodebuildOutputFilePath, xcodebuildOutput); logWriteErr != nil {
				log.Errorf("Failed to save xcodebuild output into file (%s), error: %s", xcodebuildOutputFilePath, logWriteErr)
			} else if err != nil {
				log.Infoln(colorstring.Yellow("Please check the logfile (" + xcodebuildOutputFilePath + ") to see what caused the error"))
				log.Infoln(colorstring.Red("and make sure that you can Archive this project from Xcode!"))
				fmt.Println()
				log.Infoln("Open the project:", xcodeCmd.ProjectFilePath)
				log.Infoln("and Archive, using the Scheme:", xcodeCmd.Scheme)
				fmt.Println()
			}
		}
		if err != nil {
			return printXcodeScanFinishedWithError("Failed to run Xcode Archive: %s", err)
		}
	}

	codeSigningSettings, err := xcodeCmd.ScanCodeSigningSettings(xcodebuildOutput)
	if err != nil {
		return printXcodeScanFinishedWithError("Failed to detect code signing settings: %s", err)
	}
	log.Debugf("codeSigningSettings: %#v", codeSigningSettings)

	return exportCodeSigningFiles("Xcode", absExportOutputDirPath, codeSigningSettings)
}