Example #1
0
File: main.go Project: GarX/go-pac
func main() {
	flag.Parse()
	logger.Level = *verbose
	if outfile == nil || *outfile == "" {
		logger.Debug("Please specified the output file")
		os.Exit(1)
	}
	err := worker.Run(*infile, *outfile)
	if err != nil {
		logger.Debug(err.Error())
	}

}
Example #2
0
File: cmd.go Project: GarX/go-pac
//SyncCmd can run a command synchronically
func SyncCmd(name string, arg []string) error {
	if arg == nil {
		return errors.New("invalid args")
	}
	logger.Debug(name + " " + strings.Join(arg, " "))
	cmd := exec.Command(name, arg...)
	b, err := cmd.Output()
	if string(b) != "" {
		logger.Debug(string(b))
	}
	if err != nil {
		return err
	}
	return nil
}
Example #3
0
func compileUnity(config *conf.UnityConfig, outfile string) (err error) {
	// find the *.unity file under the ./Assets recursively.
	err = changeProjectPath(config.ProjectPath)
	if err != nil {
		return
	}
	assetsDir, err := os.Open("./Assets")
	defer assetsDir.Close()
	if err != nil {
		return
	}
	unityReg, err := regexp.Compile("\\.unity$")
	if err != nil {
		return
	}
	curwd, err := os.Getwd()
	if err != nil {
		return
	}
	_, files := findRecursively(assetsDir, unityReg, curwd+"/Assets")
	if len(files) == 0 {
		err = errors.New("no .unity file was found")
		return
	}
	// make up a scenes string to generate the build file
	// scenes string like like such pattern: "a.unity","b.unity","c,unity"
	scenes := strings.Join(files, "\",\"")
	scenes = "\"" + scenes + "\""
	logger.Debug("Found scenes: " + scenes)
	var buildTarget string
	if config.Android != nil {
		buildTarget = "Android"
	}
	if config.Xcode != nil {
		buildTarget = "iPhone"
	}
	if buildTarget == "" {
		err = errors.New("no unity target specified")
		return
	}
	// get bundleIdentifier,if it is not set.just keep it as a empty string.
	var bundle string
	if config.BundleIdentifier != nil {
		bundle = *config.BundleIdentifier
	}
	var content, content0, content1, content2 string
	content0 = fmt.Sprintf(unityBuildTemplate0, bundle, bundle)
	content2 = fmt.Sprintf(unityBuildTemplate2, scenes, buildTarget)
	if androidCanSign(config.Android) == true {
		content1 = fmt.Sprintf(unityBuildTemplate1, *config.Android.Store, *config.Android.StorePassword, *config.Android.Alias, *config.Android.AliasPassword)
	} else {
		content1 = fmt.Sprintf(unityBuildTemplate1, "", "", "", "")
	}
	content = content0 + content1 + content2
	err = os.MkdirAll("./Assets/Editor", 0755)
	if err != nil {
		return
	}
	os.Remove("./Assets/Editor/GoPacBuild.cs")
	csFile, err := os.OpenFile("./Assets/Editor/GoPacBuild.cs", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0777)
	if err != nil {
		return
	}
	csFile.WriteString(content)
	csFile.Close()

	// start unity project building
	os.Remove(home + "/Library/Logs/Unity/Editor.log")
	// store the error and not return instantly
	// return the error after reading the log
	errtmp := cmd.SyncCmd("/Applications/Unity/Unity.app/Contents/MacOS/Unity", []string{"-batchMode", "-projectPath", curwd, "-executeMethod", "GoPacBuild.main", "-quit"})

	//read the log file
	unityLog, err := os.Open(home + "/Library/Logs/Unity/Editor.log")
	defer unityLog.Close()
	if err != nil {
		return
	}
	bytes, err := ioutil.ReadAll(unityLog)
	if err != nil {
		return
	}
	logger.Debug(string(bytes))
	if errtmp != nil {
		err = errtmp
		return
	}
	// check redevelopment settings. set it false if it is not set in the json file
	if config.Redevelopment == nil {
		config.Redevelopment = new(bool)
		*config.Redevelopment = false
	}
	if config.Xcode != nil {
		if *config.Redevelopment == true {
			err = cmd.SyncCmd("mv", []string{"-v", "GoPacPrj", filepath.Base(outfile)}) //rename the project
			if err != nil {
				return
			}
			if strings.HasPrefix(outfile, "/") == false { // change the file to absolute path
				outfile = workdir + "/" + outfile
			}
			err = cmd.SyncCmd("mv", []string{"-v", filepath.Base(outfile), filepath.Dir(outfile)}) // move the directory to the specified path
			if err != nil {
				return
			}
		} else {
			err = os.Chdir("./GoPacPrj")
			if err != nil {
				return
			}
			err = compileXcode(config.Xcode, outfile)
		}
		return
	}
	if config.Android != nil {
		if strings.HasPrefix(outfile, "/") == false {
			outfile = workdir + "/" + outfile
		}
		if *config.Redevelopment == true {
			err = os.MkdirAll(outfile, 0777)
			if err != nil {
				return
			}
			err = cmd.SyncCmd("unzip", []string{"GoPacPrj", "-d", outfile})
			if err != nil {
				return
			}
		} else {
			err = cmd.SyncCmd("cp", []string{"GoPacPrj", outfile})
			if err != nil {
				return
			}
		}
		return
	}
	return
}
Example #4
0
// clone or pull the repo from remote
// ATTENTION!!! : The working directory changed after the function is called
func fetchFromRemote(repo *string, vcs *string) (err error) {
	if repo == nil {
		err = errors.New("repository must be set")
		return
	}
	if vcs == nil {
		err = errors.New("vcs must be set")
		return
	}
	if *vcs != "git" && *vcs != "hg" {
		err = errors.New("invalid vcs is set")
		return
	}
	logger.Debug("Home: " + home)
	owner, dir, err := getRepoDir(*repo)
	if err != nil {
		return
	}
	err = os.MkdirAll(home+"/Library/go-pac/"+*vcs+owner+"/"+dir, 0755)
	if err != nil {
		return
	}
	logger.Debug("Enter ~/Library/go-pac/" + *vcs + owner + "/" + dir)
	err = os.Chdir(home + "/Library/go-pac/" + *vcs + owner + "/" + dir)
	if err != nil {
		return
	}

	switch *vcs {
	case "git":
		err = cmd.SyncCmd("git", []string{"init"})
		if err != nil {
			return
		}
		cmd.SyncCmd("git", []string{"reset", "--hard", "HEAD"}) // checkout to the latest version to avoid the conflict. if it is a new repo without any content, the command will cause an error. it is no need to check the error

		err = cmd.SyncCmd("git", []string{"clean", "-f"}) // clean the untracked files
		if err != nil {
			return
		}
		err = cmd.SyncCmd("git", []string{"pull", *repo})
		if err != nil {
			return
		}
	case "hg":
		cmd.SyncCmd("hg", []string{"init"})                        // hg re-init will cause an error. no need for you to check the error.
		err = cmd.SyncCmd("hg", []string{"revert", "-C", "--all"}) // revert all changes to avoid the conflict. no error if it is a new repo.
		if err != nil {
			return
		}
		err = cmd.SyncCmd("hg", []string{"purge"}) // clean the untracked files
		if err != nil {
			return
		}
		err = cmd.SyncCmd("hg", []string{"pull", *repo, "-u"}) // fetch from remote
		if err != nil {
			return
		}

	}
	return nil
}
Example #5
0
func compileAndroid(config *conf.AndroidConfig, outfile string) (err error) {
	var file *os.File

	err = changeProjectPath(config.ProjectPath)
	if err != nil {
		return
	}
	// remove the old build
	err = cmd.SyncCmd("ant", []string{"clean", "-Dsdk.dir=/usr/lib/android/sdk"})
	if err != nil {
		return
	}
	sign := androidCanSign(config)
	// generate ant.properties for ant to sign the apk while compliling and packing.
	if sign == true {
		str := fmt.Sprintf(antPropertyTemplate, AbPath(*config.Store), *config.StorePassword, *config.Alias, *config.AliasPassword)
		file, err = os.OpenFile("ant.properties", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0777)
		if err != nil {
			return
		}
		_, err = file.WriteString(str)
		if err != nil {
			return
		}
	}
	// use ant release to build and pack the project.
	err = cmd.SyncCmd("ant", []string{"release", "-Dsdk.dir=/usr/lib/android/sdk"})
	if err != nil {
		return
	}

	// remove the ant.properties will avoid the git conflict
	if sign == true {
		err = os.Remove("ant.properties")
		if err != nil {
			return
		}
	}

	// Anaylse the build directory and found .apk file.
	// If sign is set false. find -unsigned.apk
	// if sign is set true. find the .apk without -unsigned and -unaligned
	buildDir, err := os.Open("./bin")
	if err != nil {
		return err
	}
	fileInfos, err := buildDir.Readdir(0)
	if err != nil {
		return err
	}

	var targetApkPath string
	for i := 0; i < len(fileInfos); i++ {
		if fileInfos[i].IsDir() == true {
			continue
		}
		filename := fileInfos[i].Name()
		if strings.HasSuffix(filename, ".apk") == false || strings.HasSuffix(filename, "-unaligned.apk") == true {
			continue
		}
		if sign == strings.HasSuffix(filename, "-unsigned.apk") {
			continue
		} else {
			var wd string
			wd, err = os.Getwd()
			if err != nil {
				return
			}
			targetApkPath = wd + "/bin/" + filename
			break
		}
	}

	if targetApkPath == "" {
		err = errors.New("no apk found")
	}
	logger.Debug("Find " + targetApkPath)
	// targetApkPath records the absolute path of target apk.
	// change the working dirctory last time and copy the apk file

	logger.Debug("Enter" + workdir)
	err = os.Chdir(workdir) //recover the work directory caused by fetchFromRemote
	if err != nil {
		return
	}
	logger.Debug("copy " + targetApkPath + " to " + outfile)
	cmd.SyncCmd("cp", []string{"-R", targetApkPath, outfile})

	defer func() {
		file.Close()
		buildDir.Close()
	}()
	return
}
Example #6
0
func compileXcode(config *conf.XcodeConfig, outfile string) (err error) {
	// find the *.xcodeproj file under the working directory
	// if multiple xcodeproj file exists, it picks one of them.
	err = changeProjectPath(config.ProjectPath)
	if err != nil {
		return
	}
	var wdnow string
	wdnow, err = os.Getwd()
	if err != nil {
		return
	}
	wdf, err := os.Open(wdnow)
	defer wdf.Close()
	if err != nil {
		return
	}
	logger.Debug("Read Directory " + wdnow)
	fileInfos, err := wdf.Readdir(0)

	if err != nil {
		return
	}
	var prjName string //project name without *.xcodeproj suffix
	for i := 0; i < len(fileInfos); i++ {
		if fileInfos[i].IsDir() == false { // .xcodeproj file is a directory
			continue
		}
		if strings.HasSuffix(fileInfos[i].Name(), ".xcodeproj") == true {
			bytes := []byte(fileInfos[i].Name())
			prjName = string(bytes[:len(bytes)-10])
			break
		}
	}
	if prjName == "" {
		err = errors.New("cannot find the *.xcodeproj file")
		return
	}
	logger.Debug("Found target " + prjName)

	// clean the project
	err = cmd.SyncCmd("xcodebuild", []string{"-sdk", "iphoneos", "-target", prjName, "-configuration", "Release", "clean"})
	if err != nil {
		return
	}

	// build the project. If config.Sign is set, use the Sign.
	if config.Sign == nil {
		err = cmd.SyncCmd("xcodebuild", []string{"-sdk", "iphoneos", "-target", prjName, "-configuration", "Release", "CODE_SIGN_IDENTITY=", "CODE_SIGNING_REQUIRED=NO"})
	} else {
		err = cmd.SyncCmd("xcodebuild", []string{"-sdk", "iphoneos", "-target", prjName, "-configuration", "Release", "CODE_SIGN_IDENTITY=\"" + *config.Sign + "\""})
	}
	if err != nil {
		logger.Debug("xcodebuild failed")
		return
	}
	// find the .app file,mostly in ./build or ./build/Release-iphoneos
	var appPath string
	buildDir, err := os.Open("./build")
	if err != nil {
		return
	}
	defer buildDir.Close()
	fileInfos, err = buildDir.Readdir(0)
	if err != nil {
		return
	}
	buildwd, err := os.Getwd()
	if err != nil {
		return
	}
	for i := 0; i < len(fileInfos); i++ {
		// .app file is a dir
		if fileInfos[i].IsDir() == false {
			continue
		}
		if strings.HasSuffix(fileInfos[i].Name(), ".app") == true {
			appPath = buildwd + "/build/" + fileInfos[i].Name()
			break
		}
	}
	if appPath == "" { //Not found in ./build,try to find it in ./build/Release-iphoneos
		var releaseDir *os.File
		releaseDir, err = os.Open("./build/Release-iphoneos")
		defer releaseDir.Close()
		if err == nil {
			fileInfos, err = releaseDir.Readdir(0)
			if err != nil {
				return
			}
			for i := 0; i < len(fileInfos); i++ {
				if fileInfos[i].IsDir() == false {
					continue
				}
				if strings.HasSuffix(fileInfos[i].Name(), ".app") == true {
					appPath = buildwd + "/build/Release-iphoneos/" + fileInfos[i].Name()
					break
				}
			}
		}
	}
	if appPath == "" {
		err = errors.New(".app file not found")
		return
	}
	logger.Debug("Find .app file at " + appPath)
	// pack the .app into .ipa
	// change the working directory before run xcrun
	// appPath is a absolute path and will not be affected by chdir
	// outfile here must be a absolute path.
	logger.Debug("Enter " + workdir)
	os.Chdir(workdir)
	if strings.HasPrefix(outfile, "/") == false {
		outfile = workdir + "/" + outfile
	}
	if config.Provision == nil {
		logger.Debug("Provision not found!")
		logger.Debug("Make ipa at " + outfile)
		err = cmd.SyncCmd("xcrun", []string{"-sdk", "iphoneos", "PackageApplication", appPath, "-o", outfile})
	} else {
		err = cmd.SyncCmd("xcrun", []string{"-sdk", "iphoneos", "PackageApplication", appPath, "-o", outfile, "--embed", *config.Provision})
	}
	return
}