From de4c5fdcefa46ff0864c010012be4fd88933f886 Mon Sep 17 00:00:00 2001 From: Shachar Menashe Date: Thu, 31 Oct 2024 18:07:43 +0200 Subject: [PATCH] cocoapods-audit --- commands/audit/sca/cocoapods/cocoapods.go | 300 ++++++++++ .../audit/sca/cocoapods/cocoapods_test.go | 82 +++ commands/audit/sca/cocoapods/podcommand.go | 177 ++++++ commands/audit/scarunner.go | 3 + .../package-managers/cocoapods/Podfile | 7 + .../package-managers/cocoapods/Podfile.lock | 35 ++ .../cocoapods/Test.xcodeproj/project.pbxproj | 529 ++++++++++++++++++ utils/techutils/techutils.go | 92 +-- 8 files changed, 1184 insertions(+), 41 deletions(-) create mode 100644 commands/audit/sca/cocoapods/cocoapods.go create mode 100644 commands/audit/sca/cocoapods/cocoapods_test.go create mode 100644 commands/audit/sca/cocoapods/podcommand.go create mode 100644 tests/testdata/projects/package-managers/cocoapods/Podfile create mode 100644 tests/testdata/projects/package-managers/cocoapods/Podfile.lock create mode 100644 tests/testdata/projects/package-managers/cocoapods/Test.xcodeproj/project.pbxproj diff --git a/commands/audit/sca/cocoapods/cocoapods.go b/commands/audit/sca/cocoapods/cocoapods.go new file mode 100644 index 00000000..08164906 --- /dev/null +++ b/commands/audit/sca/cocoapods/cocoapods.go @@ -0,0 +1,300 @@ +package cocoapods + +import ( + "errors" + "fmt" + "github.com/jfrog/gofrog/datastructures" + "github.com/jfrog/jfrog-cli-core/v2/utils/coreutils" + "github.com/jfrog/jfrog-cli-security/utils" + "github.com/jfrog/jfrog-cli-security/utils/formats/sarifutils" + "github.com/jfrog/jfrog-cli-security/utils/techutils" + "github.com/jfrog/jfrog-client-go/utils/log" + xrayUtils "github.com/jfrog/jfrog-client-go/xray/services/utils" + "github.com/owenrumney/go-sarif/v2/sarif" + "os" + "path" + "path/filepath" + "regexp" + "strings" +) + +const ( + VersionForMainModule = "0.0.0" +) + +var ( + mainDepRegex = regexp.MustCompile(`- ([\w/+.\-]+) \(([\d.]+)\)`) + subDepRegex = regexp.MustCompile(`\s{2}- ([\w/+.\-]+)`) + versionRegex = regexp.MustCompile(`\((\d+(\.\d+){0,2})\)`) +) + +func GetTechDependencyLocation(directDependencyName, directDependencyVersion string, descriptorPaths ...string) ([]*sarif.Location, error) { + var podPositions []*sarif.Location + for _, descriptorPath := range descriptorPaths { + path.Clean(descriptorPath) + if !strings.HasSuffix(descriptorPath, "Podfile") { + log.Logger.Warn("Cannot support other files besides Podfile: %s", descriptorPath) + continue + } + data, err := os.ReadFile(descriptorPath) + if err != nil { + continue + } + lines := strings.Split(string(data), "\n") + var startLine, startCol, endLine, endCol int + foundDependency := false + var tempIndex int + for i, line := range lines { + if strings.Contains(line, directDependencyName) { + startLine = i + startCol = strings.Index(line, directDependencyName) + foundDependency = true + tempIndex = i + } + // This means we are in a new dependency (we cannot find dependency name and version together) + if i > tempIndex && foundDependency && strings.Contains(line, "pod") { + foundDependency = false + } else if foundDependency && strings.Contains(line, directDependencyVersion) { + endLine = i + endCol = len(line) + var snippet string + if endLine == startLine { + snippet = lines[startLine][startCol:endCol] + } else { + for snippetLine := 1; snippetLine < endLine-startLine+1; snippetLine++ { + switch snippetLine { + case 0: + snippet += "\n" + lines[snippetLine][startLine:] + case endLine - startLine: + snippet += "\n" + lines[snippetLine][:endCol] + default: + snippet += "\n" + lines[snippetLine] + } + } + } + podPositions = append(podPositions, sarifutils.CreateLocation(descriptorPath, startLine, endLine, startCol, endCol, snippet)) + foundDependency = false + } + } + } + return podPositions, nil +} + +func FixTechDependency(dependencyName, dependencyVersion, fixVersion string, descriptorPaths ...string) error { + for _, descriptorPath := range descriptorPaths { + path.Clean(descriptorPath) + if !strings.HasSuffix(descriptorPath, "Podfile") { + log.Logger.Warn("Cannot support other files besides Podfile: %s", descriptorPath) + continue + } + data, err := os.ReadFile(descriptorPath) + var newLines []string + if err != nil { + continue + } + lines := strings.Split(string(data), "\n") + foundDependency := false + var tempIndex int + for index, line := range lines { + if strings.Contains(line, dependencyName) { + foundDependency = true + tempIndex = index + } + // This means we are in a new dependency (we cannot find dependency name and version together) + if index > tempIndex && foundDependency && strings.Contains(line, "pod") { + foundDependency = false + } else if foundDependency && strings.Contains(line, dependencyVersion) { + newLine := strings.Replace(line, dependencyVersion, fixVersion, 1) + newLines = append(newLines, newLine) + foundDependency = false + } else { + newLines = append(newLines, line) + } + } + output := strings.Join(newLines, "\n") + err = os.WriteFile(descriptorPath, []byte(output), 0644) + if err != nil { + return fmt.Errorf("failed to write file: %v", err) + } + } + return nil +} + +func GetPackageName(longPkgName string) string { + if strings.Contains(longPkgName, "/") { + splitNameParts := strings.Split(longPkgName, "/") + longPkgName = splitNameParts[0] + } + return longPkgName +} + +func GetPodDependenciesGraph(data string) (map[string][]string, map[string]string) { + var currentMainDep string + lines := strings.Split(data, "\n") + dependencyMap := make(map[string][]string, len(lines)) + versionMap := make(map[string]string, len(lines)) + for _, line := range lines { + line = strings.ReplaceAll(line, "\"", "") + mainDepMatch := mainDepRegex.FindStringSubmatch(line) + if len(mainDepMatch) == 3 { + versionMatch := versionRegex.FindStringSubmatch(line) + currentMainDep = GetPackageName(mainDepMatch[1]) + _, ok := dependencyMap[currentMainDep] + if !ok { + dependencyMap[currentMainDep] = []string{} + versionMap[currentMainDep] = versionMatch[1] + } + continue + } + subDepMatch := subDepRegex.FindStringSubmatch(line) + if len(subDepMatch) == 2 && currentMainDep != "" { + subDependency := subDepMatch[1] + if subDependency == GetPackageName(subDependency) { + dependencyMap[currentMainDep] = append(dependencyMap[currentMainDep], subDependency) + } + } + } + return dependencyMap, versionMap +} + +func extractPodsSection(filePath string) (string, error) { + data, err := os.ReadFile(filePath) + if err != nil { + return "", err + } + content := string(data) + startIndex := strings.Index(content, "PODS:") + if startIndex == -1 { + return "", fmt.Errorf("PODS: section not found") + } + subContent := content[startIndex:] + endIndex := strings.Index(subContent, "DEPENDENCIES:") + if endIndex == -1 { + endIndex = strings.Index(subContent, "SPEC REPOS:") + } + if endIndex != -1 { + subContent = subContent[:endIndex] + } + return subContent, nil +} + +func shouldRunPodInstall(currentDir string) (bool, error) { + podlockInfo, err := os.Stat(filepath.Join(currentDir, "Podfile.lock")) + if err != nil { + if errors.Is(err, os.ErrNotExist) { + // Lockfile doesn't exist, run install to generate it + return true, nil + } + return false, err + } + + podfileInfo, err := os.Stat(filepath.Join(currentDir, "Podfile")) + if err != nil { + return false, err + } + + // Run install if podfile newer than lockfile + return podfileInfo.ModTime().After(podlockInfo.ModTime()), nil +} + +func GetDependenciesData(exePath, currentDir string) (string, error) { + runPodInstall, err := shouldRunPodInstall(currentDir) + if err != nil { + return "", err + } + if runPodInstall { + _, _, err = runPodCmd(exePath, currentDir, []string{"install"}) + if err != nil { + return "", err + } + } + result, err := extractPodsSection(filepath.Join(currentDir, "Podfile.lock")) + if err != nil { + return "", err + } + return result, nil +} + +func BuildDependencyTree(params utils.AuditParams) (dependencyTree []*xrayUtils.GraphNode, uniqueDeps []string, err error) { + currentDir, err := coreutils.GetWorkingDirectory() + if err != nil { + return nil, nil, err + } + + clearResolutionServerFunc, err := configPodResolutionServerIfNeeded(params) + if err != nil { + err = fmt.Errorf("failed while configuring a resolution server: %s", err.Error()) + return nil, nil, err + } + defer func() { + if clearResolutionServerFunc != nil { + err = errors.Join(err, clearResolutionServerFunc()) + } + }() + + packageName := filepath.Base(currentDir) + packageInfo := fmt.Sprintf("%s:%s", packageName, VersionForMainModule) + _, podExecutablePath, err := getPodVersionAndExecPath() + if err != nil { + err = fmt.Errorf("failed while retrieving pod path: %s", err.Error()) + return + } + // Calculate pod dependencies + data, err := GetDependenciesData(podExecutablePath, currentDir) + if err != nil { + return nil, nil, err + } + uniqueDepsSet := datastructures.MakeSet[string]() + dependenciesGraph, versionMap := GetPodDependenciesGraph(data) + for key := range dependenciesGraph { + if key != packageName { + dependenciesGraph[packageName] = append(dependenciesGraph[packageName], key) + } + } + versionMap[packageName] = VersionForMainModule + rootNode := &xrayUtils.GraphNode{ + Id: techutils.Cocoapods.GetPackageTypeId() + packageInfo, + Nodes: []*xrayUtils.GraphNode{}, + } + // Parse the dependencies into Xray dependency tree format + parsePodDependenciesList(rootNode, dependenciesGraph, versionMap, uniqueDepsSet) + dependencyTree = []*xrayUtils.GraphNode{rootNode} + uniqueDeps = uniqueDepsSet.ToSlice() + return +} + +// Generates a .netrc file to configure an Artifactory server as the resolver server. +func configPodResolutionServerIfNeeded(params utils.AuditParams) (clearResolutionServerFunc func() error, err error) { + // If we don't have an artifactory repo's name we don't need to configure any Artifactory server as resolution server + if params.DepsRepo() == "" { + return + } + + serverDetails, err := params.ServerDetails() + if err != nil { + return + } + + clearResolutionServerFunc, err = setArtifactoryAsResolutionServer(serverDetails, params.DepsRepo()) + return +} + +// Parse the dependencies into a Xray dependency tree format +func parsePodDependenciesList(currNode *xrayUtils.GraphNode, dependenciesGraph map[string][]string, versionMap map[string]string, uniqueDepsSet *datastructures.Set[string]) { + if currNode.NodeHasLoop() { + return + } + uniqueDepsSet.Add(currNode.Id) + pkgName := strings.Split(strings.TrimPrefix(currNode.Id, techutils.Cocoapods.GetPackageTypeId()), ":")[0] + currDepChildren := dependenciesGraph[pkgName] + for _, childName := range currDepChildren { + fullChildName := fmt.Sprintf("%s:%s", childName, versionMap[childName]) + childNode := &xrayUtils.GraphNode{ + Id: techutils.Cocoapods.GetPackageTypeId() + fullChildName, + Nodes: []*xrayUtils.GraphNode{}, + Parent: currNode, + } + currNode.Nodes = append(currNode.Nodes, childNode) + parsePodDependenciesList(childNode, dependenciesGraph, versionMap, uniqueDepsSet) + } +} diff --git a/commands/audit/sca/cocoapods/cocoapods_test.go b/commands/audit/sca/cocoapods/cocoapods_test.go new file mode 100644 index 00000000..e6e8cb1c --- /dev/null +++ b/commands/audit/sca/cocoapods/cocoapods_test.go @@ -0,0 +1,82 @@ +package cocoapods + +import ( + "fmt" + "github.com/jfrog/jfrog-cli-core/v2/utils/coreutils" + "github.com/jfrog/jfrog-cli-core/v2/utils/tests" + "github.com/jfrog/jfrog-cli-security/utils/techutils" + "os" + "path/filepath" + "strings" + "testing" + + "github.com/jfrog/jfrog-cli-core/v2/utils/config" + "github.com/jfrog/jfrog-cli-security/commands/audit/sca" + xrayutils "github.com/jfrog/jfrog-cli-security/utils" + + "github.com/stretchr/testify/assert" +) + +func TestBuildGoDependencyList(t *testing.T) { + // Create and change directory to test workspace + _, cleanUp := sca.CreateTestWorkspace(t, filepath.Join("projects", "package-managers", "cocoapods")) + defer cleanUp() + + // Run getModulesDependencyTrees + server := &config.ServerDetails{ + Url: "https://api.cocoapods.here", + ArtifactoryUrl: "https://api.cocoapods.here/artifactory", + User: "user", + AccessToken: "sdsdccs2232", + } + currentDir, err := coreutils.GetWorkingDirectory() + assert.NoError(t, err) + packageName := filepath.Base(currentDir) + packageInfo := fmt.Sprintf("%s:%s", packageName, VersionForMainModule) + expectedUniqueDeps := []string{ + techutils.Cocoapods.GetPackageTypeId() + "AppAuth:1.7.5", + techutils.Cocoapods.GetPackageTypeId() + "GoogleSignIn:6.2.4", + techutils.Cocoapods.GetPackageTypeId() + "GTMAppAuth:1.3.1", + techutils.Cocoapods.GetPackageTypeId() + "GTMSessionFetcher:2.3.0", + techutils.Cocoapods.GetPackageTypeId() + packageInfo, + } + + auditBasicParams := (&xrayutils.AuditBasicParams{}).SetServerDetails(server) + rootNode, uniqueDeps, err := BuildDependencyTree(auditBasicParams) + assert.NoError(t, err) + assert.ElementsMatch(t, uniqueDeps, expectedUniqueDeps, "First is actual, Second is Expected") + assert.NotEmpty(t, rootNode) + + assert.Equal(t, rootNode[0].Id, techutils.Cocoapods.GetPackageTypeId()+packageInfo) + assert.Len(t, rootNode[0].Nodes, 4) + + child1 := tests.GetAndAssertNode(t, rootNode[0].Nodes, "GTMSessionFetcher:2.3.0") + assert.Len(t, child1.Nodes, 0) + + child2 := tests.GetAndAssertNode(t, rootNode[0].Nodes, "GoogleSignIn:6.2.4") + assert.Len(t, child2.Nodes, 2) +} + +func TestGetTechDependencyLocation(t *testing.T) { + _, cleanUp := sca.CreateTestWorkspace(t, filepath.Join("projects", "package-managers", "cocoapods")) + defer cleanUp() + currentDir, err := coreutils.GetWorkingDirectory() + assert.NoError(t, err) + locations, err := GetTechDependencyLocation("GoogleSignIn", "6.2.4", filepath.Join(currentDir, "Podfile")) + assert.NoError(t, err) + assert.Len(t, locations, 1) + assert.Equal(t, *locations[0].PhysicalLocation.Region.Snippet.Text, "GoogleSignIn', '~> 6.2.4'") +} + +func TestFixTechDependency(t *testing.T) { + _, cleanUp := sca.CreateTestWorkspace(t, filepath.Join("projects", "package-managers", "cocoapods")) + defer cleanUp() + currentDir, err := coreutils.GetWorkingDirectory() + assert.NoError(t, err) + err = FixTechDependency("GoogleSignIn", "6.2.4", "6.2.5", filepath.Join(currentDir, "Podfile")) + assert.NoError(t, err) + file, err := os.ReadFile(filepath.Join(currentDir, "Podfile")) + assert.NoError(t, err) + lines := strings.Split(string(file), "\n") + assert.Contains(t, lines, "pod 'GoogleSignIn', '~> 6.2.5'") +} diff --git a/commands/audit/sca/cocoapods/podcommand.go b/commands/audit/sca/cocoapods/podcommand.go new file mode 100644 index 00000000..3b6e5927 --- /dev/null +++ b/commands/audit/sca/cocoapods/podcommand.go @@ -0,0 +1,177 @@ +package cocoapods + +import ( + "bytes" + "fmt" + "github.com/jfrog/gofrog/version" + "github.com/jfrog/jfrog-cli-core/v2/utils/config" + "github.com/jfrog/jfrog-cli-core/v2/utils/coreutils" + "github.com/jfrog/jfrog-cli-core/v2/utils/ioutils" + "github.com/jfrog/jfrog-client-go/auth" + "github.com/jfrog/jfrog-client-go/utils/errorutils" + "github.com/jfrog/jfrog-client-go/utils/log" + "os" + "os/exec" + "path/filepath" + "strings" +) + +const ( + minSupportedPodVersion = "1.15.2" + podNetRcfileName = ".netrc" + podrcBackupFileName = ".jfrog.netrc.backup" +) + +type PodCommand struct { + cmdName string + serverDetails *config.ServerDetails + podVersion *version.Version + authArtDetails auth.ServiceDetails + restoreNetrcFunc func() error + workingDirectory string + executablePath string +} + +func getPodVersionAndExecPath() (*version.Version, string, error) { + podExecPath, err := exec.LookPath("pod") + if err != nil { + return nil, "", fmt.Errorf("could not find the 'pod' executable in the system PATH %w", err) + } + log.Debug("Using pod executable:", podExecPath) + versionData, _, err := runPodCmd(podExecPath, "", []string{"--version"}) + if err != nil { + return nil, "", err + } + return version.NewVersion(strings.TrimSpace(string(versionData))), podExecPath, nil +} + +func runPodCmd(executablePath, srcPath string, podArgs []string) (stdResult, errResult []byte, err error) { + args := make([]string, 0) + for i := 0; i < len(podArgs); i++ { + if strings.TrimSpace(podArgs[i]) != "" { + args = append(args, podArgs[i]) + } + } + log.Debug("Running 'pod " + strings.Join(podArgs, " ") + "' command.") + command := exec.Command(executablePath, args...) + command.Dir = srcPath + outBuffer := bytes.NewBuffer([]byte{}) + command.Stdout = outBuffer + errBuffer := bytes.NewBuffer([]byte{}) + command.Stderr = errBuffer + err = command.Run() + errResult = errBuffer.Bytes() + stdResult = outBuffer.Bytes() + if err != nil { + err = fmt.Errorf("error while running '%s %s': %s\n%s", executablePath, strings.Join(args, " "), err.Error(), strings.TrimSpace(string(errResult))) + return + } + log.Debug("npm '" + strings.Join(args, " ") + "' standard output is:\n" + strings.TrimSpace(string(stdResult))) + return +} + +func (pc *PodCommand) SetServerDetails(serverDetails *config.ServerDetails) *PodCommand { + pc.serverDetails = serverDetails + return pc +} + +func (pc *PodCommand) RestoreNetrcFunc() func() error { + return pc.restoreNetrcFunc +} + +func (pc *PodCommand) GetData() ([]byte, error) { + var filteredConf []string + filteredConf = append(filteredConf, "machine ", pc.serverDetails.Url, "\n") + filteredConf = append(filteredConf, "login ", pc.serverDetails.User, "\n") + filteredConf = append(filteredConf, "password ", pc.serverDetails.AccessToken, "\n") + + return []byte(strings.Join(filteredConf, "")), nil +} + +func (pc *PodCommand) CreateTempNetrc() error { + data, err := pc.GetData() + if err != nil { + return err + } + if err = removeNetrcIfExists(pc.workingDirectory); err != nil { + return err + } + log.Debug("Creating temporary .netrc file.") + return errorutils.CheckError(os.WriteFile(filepath.Join(pc.workingDirectory, podNetRcfileName), data, 0755)) +} + +func (pc *PodCommand) setRestoreNetrcFunc() error { + restoreNetrcFunc, err := ioutils.BackupFile(filepath.Join(pc.workingDirectory, podNetRcfileName), podrcBackupFileName) + if err != nil { + return err + } + pc.restoreNetrcFunc = func() error { + return restoreNetrcFunc() + } + return nil +} + +func (pc *PodCommand) setArtifactoryAuth() error { + authArtDetails, err := pc.serverDetails.CreateArtAuthConfig() + if err != nil { + return err + } + if authArtDetails.GetSshAuthHeaders() != nil { + return errorutils.CheckErrorf("SSH authentication is not supported in this command") + } + pc.authArtDetails = authArtDetails + return nil +} + +func newPodInstallCommand() *PodCommand { + return &PodCommand{cmdName: "install"} +} + +func (pc *PodCommand) PreparePrerequisites() error { + log.Debug("Preparing prerequisites...") + var err error + pc.podVersion, pc.executablePath, err = getPodVersionAndExecPath() + if err != nil { + return err + } + if pc.podVersion.Compare(minSupportedPodVersion) > 0 { + return errorutils.CheckErrorf( + "JFrog CLI cocoapods %s command requires cocoapods client version %s or higher. The Current version is: %s", pc.cmdName, minSupportedPodVersion, pc.podVersion.GetVersion()) + } + + pc.workingDirectory, err = coreutils.GetWorkingDirectory() + if err != nil { + return err + } + log.Debug("Working directory set to:", pc.workingDirectory) + if err = pc.setArtifactoryAuth(); err != nil { + return err + } + + return pc.setRestoreNetrcFunc() +} + +func removeNetrcIfExists(workingDirectory string) error { + if _, err := os.Stat(filepath.Join(workingDirectory, podNetRcfileName)); err != nil { + if os.IsNotExist(err) { + return nil + } + return errorutils.CheckError(err) + } + + log.Debug("Removing existing .npmrc file") + return errorutils.CheckError(os.Remove(filepath.Join(workingDirectory, podNetRcfileName))) +} + +func setArtifactoryAsResolutionServer(serverDetails *config.ServerDetails, depsRepo string) (clearResolutionServerFunc func() error, err error) { + podCmd := newPodInstallCommand().SetServerDetails(serverDetails) + if err = podCmd.PreparePrerequisites(); err != nil { + return + } + if err = podCmd.CreateTempNetrc(); err != nil { + return + } + clearResolutionServerFunc = podCmd.RestoreNetrcFunc() + log.Info(fmt.Sprintf("Resolving dependencies from '%s' from repo '%s'", serverDetails.Url, depsRepo)) + return +} diff --git a/commands/audit/scarunner.go b/commands/audit/scarunner.go index 5794e890..5a40bbe0 100644 --- a/commands/audit/scarunner.go +++ b/commands/audit/scarunner.go @@ -17,6 +17,7 @@ import ( "github.com/jfrog/gofrog/parallel" "github.com/jfrog/jfrog-cli-core/v2/utils/config" "github.com/jfrog/jfrog-cli-security/commands/audit/sca" + "github.com/jfrog/jfrog-cli-security/commands/audit/sca/cocoapods" _go "github.com/jfrog/jfrog-cli-security/commands/audit/sca/go" "github.com/jfrog/jfrog-cli-security/commands/audit/sca/java" "github.com/jfrog/jfrog-cli-security/commands/audit/sca/npm" @@ -249,6 +250,8 @@ func GetTechDependencyTree(params xrayutils.AuditParams, artifactoryServerDetail }) case techutils.Nuget: depTreeResult.FullDepTrees, uniqueDeps, err = nuget.BuildDependencyTree(params) + case techutils.Cocoapods: + depTreeResult.FullDepTrees, uniqueDeps, err = cocoapods.BuildDependencyTree(params) default: err = errorutils.CheckErrorf("%s is currently not supported", string(tech)) } diff --git a/tests/testdata/projects/package-managers/cocoapods/Podfile b/tests/testdata/projects/package-managers/cocoapods/Podfile new file mode 100644 index 00000000..1dba3c2d --- /dev/null +++ b/tests/testdata/projects/package-managers/cocoapods/Podfile @@ -0,0 +1,7 @@ +platform :ios, '9.0' + +target 'Test' do + use_frameworks! +pod 'GoogleSignIn', '~> 6.2.4' + +end \ No newline at end of file diff --git a/tests/testdata/projects/package-managers/cocoapods/Podfile.lock b/tests/testdata/projects/package-managers/cocoapods/Podfile.lock new file mode 100644 index 00000000..52f4bcbb --- /dev/null +++ b/tests/testdata/projects/package-managers/cocoapods/Podfile.lock @@ -0,0 +1,35 @@ +PODS: + - AppAuth (1.7.5): + - AppAuth/Core (= 1.7.5) + - AppAuth/ExternalUserAgent (= 1.7.5) + - AppAuth/Core (1.7.5) + - AppAuth/ExternalUserAgent (1.7.5): + - AppAuth/Core + - GoogleSignIn (6.2.4): + - AppAuth (~> 1.5) + - GTMAppAuth (~> 1.3) + - GTMSessionFetcher/Core (< 3.0, >= 1.1) + - GTMAppAuth (1.3.1): + - AppAuth/Core (~> 1.6) + - GTMSessionFetcher/Core (< 3.0, >= 1.5) + - GTMSessionFetcher/Core (2.3.0) + +DEPENDENCIES: + - GoogleSignIn + +SPEC REPOS: + trunk: + - AppAuth + - GoogleSignIn + - GTMAppAuth + - GTMSessionFetcher + +SPEC CHECKSUMS: + AppAuth: 501c04eda8a8d11f179dbe8637b7a91bb7e5d2fa + GoogleSignIn: 5651ce3a61e56ca864160e79b484cd9ed3f49b7a + GTMAppAuth: 0ff230db599948a9ad7470ca667337803b3fc4dd + GTMSessionFetcher: 3a63d75eecd6aa32c2fc79f578064e1214dfdec2 + +PODFILE CHECKSUM: 9a72df5964257b4fba6943aeff4eadc48f8ad808 + +COCOAPODS: 1.15.2 diff --git a/tests/testdata/projects/package-managers/cocoapods/Test.xcodeproj/project.pbxproj b/tests/testdata/projects/package-managers/cocoapods/Test.xcodeproj/project.pbxproj new file mode 100644 index 00000000..049d42ff --- /dev/null +++ b/tests/testdata/projects/package-managers/cocoapods/Test.xcodeproj/project.pbxproj @@ -0,0 +1,529 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 50; + objects = { + +/* Begin PBXBuildFile section */ + 88AE4B8E01AFFF3A45DC9B88 /* Pods_Test.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 474904C1D18515D2338FE798 /* Pods_Test.framework */; }; + D50D70A420B9443D00F9D88B /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = D50D70A320B9443D00F9D88B /* GoogleService-Info.plist */; }; + D5418B3220B9A02A001D620C /* google1.png in Resources */ = {isa = PBXBuildFile; fileRef = D5418B2B20B9A027001D620C /* google1.png */; }; + D5418B3320B9A02A001D620C /* fb2.png in Resources */ = {isa = PBXBuildFile; fileRef = D5418B2C20B9A027001D620C /* fb2.png */; }; + D5418B3420B9A02A001D620C /* signup.png in Resources */ = {isa = PBXBuildFile; fileRef = D5418B2D20B9A028001D620C /* signup.png */; }; + D5418B3520B9A02A001D620C /* fb1.png in Resources */ = {isa = PBXBuildFile; fileRef = D5418B2E20B9A028001D620C /* fb1.png */; }; + D5418B3620B9A02A001D620C /* fb3.png in Resources */ = {isa = PBXBuildFile; fileRef = D5418B2F20B9A029001D620C /* fb3.png */; }; + D5418B3720B9A02A001D620C /* google2.png in Resources */ = {isa = PBXBuildFile; fileRef = D5418B3020B9A029001D620C /* google2.png */; }; + D5418B3820B9A02A001D620C /* home.png in Resources */ = {isa = PBXBuildFile; fileRef = D5418B3120B9A029001D620C /* home.png */; }; + D5418B3B20B9A512001D620C /* firebase1.png in Resources */ = {isa = PBXBuildFile; fileRef = D5418B3920B9A512001D620C /* firebase1.png */; }; + D5418B3C20B9A512001D620C /* firebase2.png in Resources */ = {isa = PBXBuildFile; fileRef = D5418B3A20B9A512001D620C /* firebase2.png */; }; + D5418B3E20B9A938001D620C /* swiftxcode.jpg in Resources */ = {isa = PBXBuildFile; fileRef = D5418B3D20B9A938001D620C /* swiftxcode.jpg */; }; + D54BB52720B54ACF0085C370 /* FirebaseViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D54BB52620B54ACF0085C370 /* FirebaseViewController.swift */; }; + D5D3F10D20B6AA0F00C5C2AA /* FirebaseAuthenticator.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5D3F10C20B6AA0F00C5C2AA /* FirebaseAuthenticator.swift */; }; + D5D4807920AEF552004F5ADF /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5D4807820AEF552004F5ADF /* AppDelegate.swift */; }; + D5D4807B20AEF552004F5ADF /* LoginViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5D4807A20AEF552004F5ADF /* LoginViewController.swift */; }; + D5D4807E20AEF552004F5ADF /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = D5D4807C20AEF552004F5ADF /* Main.storyboard */; }; + D5D4808020AEF555004F5ADF /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = D5D4807F20AEF555004F5ADF /* Assets.xcassets */; }; + D5D4808320AEF555004F5ADF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = D5D4808120AEF555004F5ADF /* LaunchScreen.storyboard */; }; + D5D4809420B2A9B6004F5ADF /* SignupViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5D4809320B2A9B6004F5ADF /* SignupViewController.swift */; }; + D5D4809620B2CEB8004F5ADF /* BaseViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5D4809520B2CEB8004F5ADF /* BaseViewController.swift */; }; + D5D4809D20B3E95D004F5ADF /* LoginMain.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = D5D4809C20B3E95D004F5ADF /* LoginMain.storyboard */; }; + D5D4809F20B3FB67004F5ADF /* CustomCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5D4809E20B3FB67004F5ADF /* CustomCollectionViewCell.swift */; }; + D5D480A120B3FBBF004F5ADF /* MainCollectionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5D480A020B3FBBF004F5ADF /* MainCollectionViewController.swift */; }; + D5FDF0F720B7EE5E00D68D8D /* SocialAuthenticator.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5FDF0F620B7EE5E00D68D8D /* SocialAuthenticator.swift */; }; + D5FDF0FA20B8263500D68D8D /* ResponseDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5FDF0F920B8263500D68D8D /* ResponseDelegate.swift */; }; + D5FDF0FC20B8266100D68D8D /* SocialDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5FDF0FB20B8266100D68D8D /* SocialDelegate.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 474904C1D18515D2338FE798 /* Pods_Test.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Test.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + 64BF18EB7EA0A352287C2039 /* Pods-Test.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Test.debug.xcconfig"; path = "Pods/Target Support Files/Pods-Test/Pods-Test.debug.xcconfig"; sourceTree = ""; }; + C84725ECA8AC99708758BF82 /* Pods-Test.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Test.release.xcconfig"; path = "Pods/Target Support Files/Pods-Test/Pods-Test.release.xcconfig"; sourceTree = ""; }; + D50D70A320B9443D00F9D88B /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = ""; }; + D5418B2B20B9A027001D620C /* google1.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = google1.png; sourceTree = ""; }; + D5418B2C20B9A027001D620C /* fb2.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = fb2.png; sourceTree = ""; }; + D5418B2D20B9A028001D620C /* signup.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = signup.png; sourceTree = ""; }; + D5418B2E20B9A028001D620C /* fb1.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = fb1.png; sourceTree = ""; }; + D5418B2F20B9A029001D620C /* fb3.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = fb3.png; sourceTree = ""; }; + D5418B3020B9A029001D620C /* google2.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = google2.png; sourceTree = ""; }; + D5418B3120B9A029001D620C /* home.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = home.png; sourceTree = ""; }; + D5418B3920B9A512001D620C /* firebase1.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = firebase1.png; sourceTree = ""; }; + D5418B3A20B9A512001D620C /* firebase2.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = firebase2.png; sourceTree = ""; }; + D5418B3D20B9A938001D620C /* swiftxcode.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = swiftxcode.jpg; sourceTree = ""; }; + D54BB52620B54ACF0085C370 /* FirebaseViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FirebaseViewController.swift; sourceTree = ""; }; + D5D3F10C20B6AA0F00C5C2AA /* FirebaseAuthenticator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FirebaseAuthenticator.swift; sourceTree = ""; }; + D5D4807520AEF552004F5ADF /* Test.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Test.app; sourceTree = BUILT_PRODUCTS_DIR; }; + D5D4807820AEF552004F5ADF /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; + D5D4807A20AEF552004F5ADF /* LoginViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginViewController.swift; sourceTree = ""; }; + D5D4807D20AEF552004F5ADF /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; + D5D4807F20AEF555004F5ADF /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + D5D4808220AEF555004F5ADF /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + D5D4808420AEF555004F5ADF /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + D5D4809320B2A9B6004F5ADF /* SignupViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SignupViewController.swift; sourceTree = ""; }; + D5D4809520B2CEB8004F5ADF /* BaseViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BaseViewController.swift; sourceTree = ""; }; + D5D4809C20B3E95D004F5ADF /* LoginMain.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = LoginMain.storyboard; sourceTree = ""; }; + D5D4809E20B3FB67004F5ADF /* CustomCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomCollectionViewCell.swift; sourceTree = ""; }; + D5D480A020B3FBBF004F5ADF /* MainCollectionViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainCollectionViewController.swift; sourceTree = ""; }; + D5FDF0F620B7EE5E00D68D8D /* SocialAuthenticator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SocialAuthenticator.swift; sourceTree = ""; }; + D5FDF0F920B8263500D68D8D /* ResponseDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ResponseDelegate.swift; sourceTree = ""; }; + D5FDF0FB20B8266100D68D8D /* SocialDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SocialDelegate.swift; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + D5D4807220AEF552004F5ADF /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 88AE4B8E01AFFF3A45DC9B88 /* Pods_Test.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 6D4AE5F2DED4F2D75679768C /* Pods */ = { + isa = PBXGroup; + children = ( + 64BF18EB7EA0A352287C2039 /* Pods-Test.debug.xcconfig */, + C84725ECA8AC99708758BF82 /* Pods-Test.release.xcconfig */, + ); + name = Pods; + sourceTree = ""; + }; + 76A856C51E4B61E4FCC4DBDF /* Frameworks */ = { + isa = PBXGroup; + children = ( + 474904C1D18515D2338FE798 /* Pods_Test.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + D520BEC820B5467D009A5272 /* Network */ = { + isa = PBXGroup; + children = ( + D5D3F10C20B6AA0F00C5C2AA /* FirebaseAuthenticator.swift */, + D5FDF0F620B7EE5E00D68D8D /* SocialAuthenticator.swift */, + ); + path = Network; + sourceTree = ""; + }; + D5418B2A20B99C84001D620C /* Screenshots */ = { + isa = PBXGroup; + children = ( + D5418B3D20B9A938001D620C /* swiftxcode.jpg */, + D5418B3920B9A512001D620C /* firebase1.png */, + D5418B3A20B9A512001D620C /* firebase2.png */, + D5418B2E20B9A028001D620C /* fb1.png */, + D5418B2C20B9A027001D620C /* fb2.png */, + D5418B2F20B9A029001D620C /* fb3.png */, + D5418B2B20B9A027001D620C /* google1.png */, + D5418B3020B9A029001D620C /* google2.png */, + D5418B3120B9A029001D620C /* home.png */, + D5418B2D20B9A028001D620C /* signup.png */, + ); + path = Screenshots; + sourceTree = ""; + }; + D5D4806C20AEF552004F5ADF = { + isa = PBXGroup; + children = ( + 76A856C51E4B61E4FCC4DBDF /* Frameworks */, + 6D4AE5F2DED4F2D75679768C /* Pods */, + D5D4807620AEF552004F5ADF /* Products */, + D5D4807720AEF552004F5ADF /* Test */, + ); + sourceTree = ""; + }; + D5D4807620AEF552004F5ADF /* Products */ = { + isa = PBXGroup; + children = ( + D5D4807520AEF552004F5ADF /* Test.app */, + ); + name = Products; + sourceTree = ""; + }; + D5D4807720AEF552004F5ADF /* Test */ = { + isa = PBXGroup; + children = ( + D5418B2A20B99C84001D620C /* Screenshots */, + D50D70A320B9443D00F9D88B /* GoogleService-Info.plist */, + D5FDF0F820B8225500D68D8D /* Delegate */, + D5D4807C20AEF552004F5ADF /* Main.storyboard */, + D5D4808420AEF555004F5ADF /* Info.plist */, + D5D4807820AEF552004F5ADF /* AppDelegate.swift */, + D5D4809520B2CEB8004F5ADF /* BaseViewController.swift */, + D5D4809320B2A9B6004F5ADF /* SignupViewController.swift */, + D5D4807A20AEF552004F5ADF /* LoginViewController.swift */, + D5D4807F20AEF555004F5ADF /* Assets.xcassets */, + D5D4808120AEF555004F5ADF /* LaunchScreen.storyboard */, + D520BEC820B5467D009A5272 /* Network */, + D5D4809920B3E8F8004F5ADF /* MainLogin */, + ); + path = Test; + sourceTree = ""; + }; + D5D4809920B3E8F8004F5ADF /* MainLogin */ = { + isa = PBXGroup; + children = ( + D54BB52620B54ACF0085C370 /* FirebaseViewController.swift */, + D5D4809C20B3E95D004F5ADF /* LoginMain.storyboard */, + D5D4809E20B3FB67004F5ADF /* CustomCollectionViewCell.swift */, + D5D480A020B3FBBF004F5ADF /* MainCollectionViewController.swift */, + ); + path = MainLogin; + sourceTree = ""; + }; + D5FDF0F820B8225500D68D8D /* Delegate */ = { + isa = PBXGroup; + children = ( + D5FDF0F920B8263500D68D8D /* ResponseDelegate.swift */, + D5FDF0FB20B8266100D68D8D /* SocialDelegate.swift */, + ); + name = Delegate; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + D5D4807420AEF552004F5ADF /* Test */ = { + isa = PBXNativeTarget; + buildConfigurationList = D5D4808720AEF555004F5ADF /* Build configuration list for PBXNativeTarget "Test" */; + buildPhases = ( + D905B27F086A3993E6CC203D /* [CP] Check Pods Manifest.lock */, + D5D4807120AEF552004F5ADF /* Sources */, + D5D4807220AEF552004F5ADF /* Frameworks */, + D5D4807320AEF552004F5ADF /* Resources */, + 84D5C8B19799EFD0F35C8BA9 /* [CP] Embed Pods Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = Test; + productName = swiftconcepts; + productReference = D5D4807520AEF552004F5ADF /* Test.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + D5D4806D20AEF552004F5ADF /* Project object */ = { + isa = PBXProject; + attributes = { + LastSwiftUpdateCheck = 0930; + LastUpgradeCheck = 0930; + ORGANIZATIONNAME = yuvraj; + TargetAttributes = { + D5D4807420AEF552004F5ADF = { + CreatedOnToolsVersion = 9.3.1; + }; + }; + }; + buildConfigurationList = D5D4807020AEF552004F5ADF /* Build configuration list for PBXProject "Test" */; + compatibilityVersion = "Xcode 9.3"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = D5D4806C20AEF552004F5ADF; + productRefGroup = D5D4807620AEF552004F5ADF /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + D5D4807420AEF552004F5ADF /* Test */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + D5D4807320AEF552004F5ADF /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + D5D4808320AEF555004F5ADF /* LaunchScreen.storyboard in Resources */, + D5418B3620B9A02A001D620C /* fb3.png in Resources */, + D5D4808020AEF555004F5ADF /* Assets.xcassets in Resources */, + D5D4807E20AEF552004F5ADF /* Main.storyboard in Resources */, + D5418B3520B9A02A001D620C /* fb1.png in Resources */, + D5418B3420B9A02A001D620C /* signup.png in Resources */, + D5D4809D20B3E95D004F5ADF /* LoginMain.storyboard in Resources */, + D5418B3220B9A02A001D620C /* google1.png in Resources */, + D5418B3820B9A02A001D620C /* home.png in Resources */, + D5418B3B20B9A512001D620C /* firebase1.png in Resources */, + D5418B3720B9A02A001D620C /* google2.png in Resources */, + D5418B3320B9A02A001D620C /* fb2.png in Resources */, + D5418B3E20B9A938001D620C /* swiftxcode.jpg in Resources */, + D50D70A420B9443D00F9D88B /* GoogleService-Info.plist in Resources */, + D5418B3C20B9A512001D620C /* firebase2.png in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 84D5C8B19799EFD0F35C8BA9 /* [CP] Embed Pods Frameworks */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Test/Pods-Test-frameworks-${CONFIGURATION}-input-files.xcfilelist", + ); + name = "[CP] Embed Pods Frameworks"; + outputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-Test/Pods-Test-frameworks-${CONFIGURATION}-output-files.xcfilelist", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Test/Pods-Test-frameworks.sh\"\n"; + showEnvVarsInLog = 0; + }; + D905B27F086A3993E6CC203D /* [CP] Check Pods Manifest.lock */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Test-checkManifestLockResult.txt", + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + D5D4807120AEF552004F5ADF /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + D5D4809420B2A9B6004F5ADF /* SignupViewController.swift in Sources */, + D54BB52720B54ACF0085C370 /* FirebaseViewController.swift in Sources */, + D5D4809F20B3FB67004F5ADF /* CustomCollectionViewCell.swift in Sources */, + D5D3F10D20B6AA0F00C5C2AA /* FirebaseAuthenticator.swift in Sources */, + D5FDF0FC20B8266100D68D8D /* SocialDelegate.swift in Sources */, + D5D480A120B3FBBF004F5ADF /* MainCollectionViewController.swift in Sources */, + D5FDF0F720B7EE5E00D68D8D /* SocialAuthenticator.swift in Sources */, + D5D4807B20AEF552004F5ADF /* LoginViewController.swift in Sources */, + D5D4809620B2CEB8004F5ADF /* BaseViewController.swift in Sources */, + D5D4807920AEF552004F5ADF /* AppDelegate.swift in Sources */, + D5FDF0FA20B8263500D68D8D /* ResponseDelegate.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXVariantGroup section */ + D5D4807C20AEF552004F5ADF /* Main.storyboard */ = { + isa = PBXVariantGroup; + children = ( + D5D4807D20AEF552004F5ADF /* Base */, + ); + name = Main.storyboard; + sourceTree = ""; + }; + D5D4808120AEF555004F5ADF /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + D5D4808220AEF555004F5ADF /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + D5D4808520AEF555004F5ADF /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + D5D4808620AEF555004F5ADF /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + CODE_SIGN_IDENTITY = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + GCC_C_LANGUAGE_STANDARD = gnu11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + MTL_ENABLE_DEBUG_INFO = NO; + SDKROOT = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + SWIFT_OPTIMIZATION_LEVEL = "-O"; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + D5D4808820AEF555004F5ADF /* Debug */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = 64BF18EB7EA0A352287C2039 /* Pods-Test.debug.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_STYLE = Automatic; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/swiftconcepts", + ); + INFOPLIST_FILE = Test/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.yuvraj.Test; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 4.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + D5D4808920AEF555004F5ADF /* Release */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = C84725ECA8AC99708758BF82 /* Pods-Test.release.xcconfig */; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CODE_SIGN_STYLE = Automatic; + FRAMEWORK_SEARCH_PATHS = ( + "$(inherited)", + "$(PROJECT_DIR)/swiftconcepts", + ); + INFOPLIST_FILE = Test/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 9.0; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.yuvraj.Test; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 4.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + D5D4807020AEF552004F5ADF /* Build configuration list for PBXProject "Test" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + D5D4808520AEF555004F5ADF /* Debug */, + D5D4808620AEF555004F5ADF /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + D5D4808720AEF555004F5ADF /* Build configuration list for PBXNativeTarget "Test" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + D5D4808820AEF555004F5ADF /* Debug */, + D5D4808920AEF555004F5ADF /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = D5D4806D20AEF552004F5ADF /* Project object */; +} diff --git a/utils/techutils/techutils.go b/utils/techutils/techutils.go index 8aa8a89b..1d70ff3e 100644 --- a/utils/techutils/techutils.go +++ b/utils/techutils/techutils.go @@ -24,20 +24,21 @@ import ( type Technology string const ( - Maven Technology = "maven" - Gradle Technology = "gradle" - Npm Technology = "npm" - Pnpm Technology = "pnpm" - Yarn Technology = "yarn" - Go Technology = "go" - Pip Technology = "pip" - Pipenv Technology = "pipenv" - Poetry Technology = "poetry" - Nuget Technology = "nuget" - Dotnet Technology = "dotnet" - Docker Technology = "docker" - Oci Technology = "oci" - Conan Technology = "conan" + Maven Technology = "maven" + Gradle Technology = "gradle" + Npm Technology = "npm" + Pnpm Technology = "pnpm" + Yarn Technology = "yarn" + Go Technology = "go" + Pip Technology = "pip" + Pipenv Technology = "pipenv" + Poetry Technology = "poetry" + Nuget Technology = "nuget" + Dotnet Technology = "dotnet" + Docker Technology = "docker" + Oci Technology = "oci" + Conan Technology = "conan" + Cocoapods Technology = "cocoapods" ) const Pypi = "pypi" @@ -46,27 +47,29 @@ var AllTechnologiesStrings = []string{Maven.String(), Gradle.String(), Npm.Strin type CodeLanguage string const ( - JavaScript CodeLanguage = "javascript" - Python CodeLanguage = "python" - GoLang CodeLanguage = "go" - Java CodeLanguage = "java" - CSharp CodeLanguage = "C#" - CPP CodeLanguage = "C++" + JavaScript CodeLanguage = "javascript" + Python CodeLanguage = "python" + GoLang CodeLanguage = "go" + Java CodeLanguage = "java" + CSharp CodeLanguage = "C#" + CPP CodeLanguage = "C++" + CocoapodsLang CodeLanguage = "any" ) // Associates a technology with project type (used in config commands for the package-managers). // Docker is not present, as there is no docker-config command and, consequently, no docker.yaml file we need to operate on. var TechToProjectType = map[Technology]project.ProjectType{ - Maven: project.Maven, - Gradle: project.Gradle, - Npm: project.Npm, - Yarn: project.Yarn, - Go: project.Go, - Pip: project.Pip, - Pipenv: project.Pipenv, - Poetry: project.Poetry, - Nuget: project.Nuget, - Dotnet: project.Dotnet, + Maven: project.Maven, + Gradle: project.Gradle, + Npm: project.Npm, + Yarn: project.Yarn, + Go: project.Go, + Pip: project.Pip, + Pipenv: project.Pipenv, + Poetry: project.Poetry, + Nuget: project.Nuget, + Dotnet: project.Dotnet, + Cocoapods: project.Cocoapods, } var packageTypes = map[string]string{ @@ -194,6 +197,12 @@ var technologiesData = map[Technology]TechData{ packageDescriptors: []string{"conanfile.txt", "conanfile.py "}, formal: "Conan", }, + Cocoapods: { + indicators: []string{"Podfile", "Podfile.lock"}, + packageDescriptors: []string{"Podfile", "Podfile.lock"}, + formal: "Cocoapods", + packageTypeId: "cocoapods://", + }, } var ( @@ -223,17 +232,18 @@ func pyProjectTomlIndicatorContent(tech Technology) ContentValidator { func TechnologyToLanguage(technology Technology) CodeLanguage { languageMap := map[Technology]CodeLanguage{ - Npm: JavaScript, - Pip: Python, - Poetry: Python, - Pipenv: Python, - Go: GoLang, - Maven: Java, - Gradle: Java, - Nuget: CSharp, - Dotnet: CSharp, - Yarn: JavaScript, - Pnpm: JavaScript, + Npm: JavaScript, + Pip: Python, + Poetry: Python, + Pipenv: Python, + Go: GoLang, + Maven: Java, + Gradle: Java, + Nuget: CSharp, + Dotnet: CSharp, + Yarn: JavaScript, + Pnpm: JavaScript, + Cocoapods: CocoapodsLang, } return languageMap[technology] }