{"action":"created","comment":{"url":"https://api.github.com/repos/appc/goaci/pulls/comments/26389499","id":26389499,"diff_hunk":"@@ -47,189 +27,401 @@ func (v *StringVector) Set(str string) error {\n \treturn nil\n }\n \n-func main() {\n-\tvar (\n-\t\texecOpts            StringVector\n-\t\tgoDefaultBinaryDesc string\n-\t\tgoBinaryOpt         string\n-\t\tgoPathOpt           string\n-\t)\n-\n-\t// Find the go binary\n-\tgocmd, err := exec.LookPath(\"go\")\n+type options struct {\n+\texec      StringVector\n+\tgoBinary  string\n+\tgoPath    string\n+\tuseBinary string\n+\tassets    StringVector\n+\tkeepTmp   bool\n+\tproject   string\n+}\n \n-\tflag.Var(&execOpts, \"exec\", \"Parameters passed to app, can be used multiple times\")\n+func getOptions() (*options, error) {\n+\topts := &options{}\n+\n+\t// --go-binary\n+\tgoDefaultBinaryDesc := \"Go binary to use\"\n+\tgocmd, err := exec.LookPath(\"go\")\n \tif err != nil {\n-\t\tgoDefaultBinaryDesc = \"Go binary to use (default: none found in $PATH, so it must be provided)\"\n+\t\tgoDefaultBinaryDesc += \" (default: none found in $PATH, so it must be provided)\"\n \t} else {\n-\t\tgoDefaultBinaryDesc = \"Go binary to use (default: whatever go in $PATH)\"\n+\t\tgoDefaultBinaryDesc += \" (default: whatever go in $PATH)\"\n \t}\n-\tflag.StringVar(&goBinaryOpt, \"go-binary\", gocmd, goDefaultBinaryDesc)\n-\tflag.StringVar(&goPathOpt, \"go-path\", \"\", \"Custom GOPATH (default: a temporary directory)\")\n+\tflag.StringVar(&opts.goBinary, \"go-binary\", gocmd, goDefaultBinaryDesc)\n+\n+\t// --exec\n+\tflag.Var(&opts.exec, \"exec\", \"Parameters passed to app, can be used multiple times\")\n+\n+\t// --go-path\n+\tflag.StringVar(&opts.goPath, \"go-path\", \"\", \"Custom GOPATH (default: a temporary directory)\")\n+\n+\t// --use-binary\n+\tflag.StringVar(&opts.useBinary, \"use-binary\", \"\", \"Which executable to put in ACI image\")\n+\n+\t// --asset\n+\tflag.Var(&opts.assets, \"asset\", \"Additional assets, can be used multiple times; format: <path in ACI>\"+ListSeparator()+\"<local path>; placeholders like <GOPATH> and <PROJPATH> can be used there as well\")\n+\n+\t// --keep-tmp\n+\tflag.BoolVar(&opts.keepTmp, \"keep-tmp\", false, \"Do not delete temporary directory used for creating ACI\")\n \tflag.Parse()\n+\n+\targs := flag.Args()\n+\tif len(args) != 1 {\n+\t\treturn nil, fmt.Errorf(\"Expected exactly one project to build, got %d\", len(args))\n+\t}\n+\topts.project = args[0]\n+\tif opts.goBinary == \"\" {\n+\t\treturn nil, fmt.Errorf(\"Go binary not found\")\n+\t}\n+\n+\treturn opts, nil\n+}\n+\n+type pathsAndNames struct {\n+\ttmpDirPath  string\n+\tgoPath      string\n+\tgoRootPath  string\n+\tprojectPath string\n+\tfakeGoPath  string\n+\tgoBinPath   string\n+\taciDirPath  string\n+\trootFSPath  string\n+\tgoExecPath  string\n+\n+\timageFileName string\n+\timageACName   string\n+}\n+\n+// getGoPath returns go path and fake go path. The former is either in\n+// /tmp (which is a default) or some other path as specified by\n+// --go-path parameter. The latter is always in /tmp.\n+func getGoPath(opts *options, tmpDir string) (string, string) {\n+\tfakeGoPath := filepath.Join(tmpDir, \"gopath\")\n+\tif opts.goPath == \"\" {\n+\t\treturn fakeGoPath, fakeGoPath\n+\t}\n+\treturn opts.goPath, fakeGoPath\n+}\n+\n+// getNamesFromProject returns project name, image ACName and ACI\n+// filename. Names depend on whether project has several binaries. For\n+// project with single binary (github.com/appc/goaci) returned values\n+// would be: github.com/appc/goaci, github.com/appc/goaci and\n+// goaci.aci. For project with multiple binaries\n+// (github.com/appc/spec/...) returned values would be (assuming ace\n+// as selected binary): github.com/appc/spec, github.com/appc/spec-ace\n+// and spec-ace.aci.\n+func getNamesFromProject(opts *options) (string, string, string) {\n+\timageACName := opts.project\n+\tprojectName := imageACName\n+\tbase := filepath.Base(imageACName)\n+\tthreeDotsBase := base == \"...\"\n+\tif threeDotsBase {\n+\t\timageACName = filepath.Dir(imageACName)\n+\t\tprojectName = imageACName\n+\t\tbase = filepath.Base(imageACName)\n+\t\tif opts.useBinary != \"\" {\n+\t\t\tsuffix := \"-\" + opts.useBinary\n+\t\t\tbase += suffix\n+\t\t\timageACName += suffix\n+\t\t}\n+\t}\n+\n+\treturn projectName, imageACName, base + schema.ACIExtension\n+}\n+\n+func getPathsAndNames(opts *options) (*pathsAndNames, error) {\n+\ttmpDir, err := ioutil.TempDir(\"\", \"goaci\")\n+\tif err != nil {\n+\t\treturn nil, fmt.Errorf(\"error setting up temporary directory: %v\", err)\n+\t}\n+\n+\tgoPath, fakeGoPath := getGoPath(opts, tmpDir)\n+\tprojectName, imageACName, imageFileName := getNamesFromProject(opts)\n+\n \tif os.Getenv(\"GOPATH\") != \"\" {\n-\t\twarn(\"GOPATH env var is ignored, use --go-path=\\\"$GOPATH\\\" option instead\")\n+\t\tWarn(\"GOPATH env var is ignored, use --go-path=\\\"$GOPATH\\\" option instead\")\n \t}\n \tgoRoot := os.Getenv(\"GOROOT\")\n \tif goRoot != \"\" {\n-\t\twarn(\"Overriding GOROOT env var to %s\", goRoot)\n-\t}\n-\tif os.Getenv(\"GOACI_DEBUG\") != \"\" {\n-\t\tDebug = true\n+\t\tWarn(\"Overriding GOROOT env var to \", goRoot)\n \t}\n \n-\tif goBinaryOpt == \"\" {\n-\t\tdie(\"go binary not found\")\n+\taciDir := filepath.Join(tmpDir, \"aci\")\n+\t// Project name is path-like string with slashes, but slash is\n+\t// not a file separator on every OS.\n+\tprojectPath := filepath.Join(goPath, \"src\", filepath.Join(strings.Split(projectName, \"/\")...))\n+\n+\treturn &pathsAndNames{\n+\t\ttmpDirPath:  tmpDir, // /tmp/XXX\n+\t\tgoPath:      goPath,\n+\t\tgoRootPath:  goRoot,\n+\t\tprojectPath: projectPath,\n+\t\tfakeGoPath:  fakeGoPath,                       // /tmp/XXX/gopath\n+\t\tgoBinPath:   filepath.Join(fakeGoPath, \"bin\"), // /tmp/XXX/gopath/bin\n+\t\taciDirPath:  aciDir,                           // /tmp/XXX/aci\n+\t\trootFSPath:  filepath.Join(aciDir, \"rootfs\"),  // /tmp/XXX/aci/rootfs\n+\t\tgoExecPath:  opts.goBinary,\n+\n+\t\timageFileName: imageFileName,\n+\t\timageACName:   imageACName,\n+\t}, nil\n+}\n+\n+func makeDirectories(pathsNames *pathsAndNames) error {\n+\t// /tmp/XXX already exists, not creating it here\n+\n+\t// /tmp/XXX/gopath\n+\tif err := os.Mkdir(pathsNames.fakeGoPath, 0755); err != nil {\n+\t\treturn err\n \t}\n \n-\t// Set up a temporary directory for everything (gopath and builds)\n-\ttmpdir, err := ioutil.TempDir(\"\", \"goaci\")\n-\tif err != nil {\n-\t\tdie(\"error setting up temporary directory: %v\", err)\n+\t// /tmp/XXX/gopath/bin\n+\tif err := os.Mkdir(pathsNames.goBinPath, 0755); err != nil {\n+\t\treturn err\n \t}\n-\tdefer os.RemoveAll(tmpdir)\n-\tif goPathOpt == \"\" {\n-\t\tgoPathOpt = tmpdir\n+\n+\t// /tmp/XXX/aci\n+\tif err := os.Mkdir(pathsNames.aciDirPath, 0755); err != nil {\n+\t\treturn err\n \t}\n \n-\t// Scratch build dir for aci\n-\tacidir := filepath.Join(tmpdir, \"aci\")\n+\t// /tmp/XXX/aci/rootfs\n+\tif err := os.Mkdir(pathsNames.rootFSPath, 0755); err != nil {\n+\t\treturn err\n+\t}\n \n-\t// Let's put final binary in tmpdir\n-\tgobin := filepath.Join(tmpdir, \"bin\")\n+\treturn nil\n+}\n \n+func runGoGet(opts *options, pathsNames *pathsAndNames) error {\n \t// Construct args for a go get that does a static build\n \targs := []string{\n-\t\tgoBinaryOpt,\n+\t\tpathsNames.goExecPath,\n \t\t\"get\",\n \t\t\"-a\",\n \t\t\"-tags\", \"netgo\",\n \t\t\"-ldflags\", \"'-w'\",\n-\t\t// 1.4\n-\t\t\"-installsuffix\", \"cgo\",\n-\t}\n-\n-\t// Extract the package name (which is the last arg).\n-\tvar ns string\n-\tfor _, arg := range os.Args[1:] {\n-\t\t// TODO(jonboulle): try to pass the other args on to go get?\n-\t\t//\t\targs = append(args, arg)\n-\t\tns = arg\n-\t}\n-\n-\tname, err := types.NewACName(ns)\n-\t// TODO(jonboulle): could this ever actually happen?\n-\tif err != nil {\n-\t\tdie(\"bad app name: %v\", err)\n-\t}\n-\targs = append(args, ns)\n-\n-\t// Use the last component, e.g. example.com/my/app --> app\n-\tofn := filepath.Base(ns) + \".aci\"\n-\tmode := os.O_CREATE | os.O_WRONLY | os.O_TRUNC\n-\tof, err := os.OpenFile(ofn, mode, 0644)\n-\tif err != nil {\n-\t\tdie(\"error opening output file: %v\", err)\n+\t\t\"-installsuffix\", \"nocgo\", // for 1.4\n+\t\topts.project,\n \t}\n \n \tenv := []string{\n-\t\t\"GOPATH=\" + goPathOpt,\n-\t\t\"GOBIN=\" + gobin,\n+\t\t\"GOPATH=\" + pathsNames.goPath,\n+\t\t\"GOBIN=\" + pathsNames.goBinPath,\n \t\t\"CGO_ENABLED=0\",\n \t\t\"PATH=\" + os.Getenv(\"PATH\"),\n \t}\n-\tif goRoot != \"\" {\n-\t\tenv = append(env, \"GOROOT=\"+goRoot)\n+\tif pathsNames.goRootPath != \"\" {\n+\t\tenv = append(env, \"GOROOT=\"+pathsNames.goRootPath)\n \t}\n+\n \tcmd := exec.Cmd{\n \t\tEnv:    env,\n-\t\tPath:   goBinaryOpt,\n+\t\tPath:   pathsNames.goExecPath,\n \t\tArgs:   args,\n \t\tStderr: os.Stderr,\n \t\tStdout: os.Stdout,\n \t}\n-\tdebug(\"env:\", cmd.Env)\n-\tdebug(\"running command:\", strings.Join(cmd.Args, \" \"))\n+\tDebug(\"env: \", cmd.Env)\n+\tDebug(\"running command: \", strings.Join(cmd.Args, \" \"))\n \tif err := cmd.Run(); err != nil {\n-\t\tdie(\"error running go: %v\", err)\n+\t\treturn err\n \t}\n+\treturn nil\n+}\n \n-\t// Check that we got 1 binary from the go get command\n-\tfi, err := ioutil.ReadDir(gobin)\n+// getBinaryName get a binary name built by go get and selected by\n+// --use-binary parameter.\n+func getBinaryName(opts *options, pathsNames *pathsAndNames) (string, error) {\n+\tfi, err := ioutil.ReadDir(pathsNames.goBinPath)\n \tif err != nil {\n-\t\tdie(err.Error())\n+\t\treturn \"\", err\n \t}\n+\n \tswitch {\n \tcase len(fi) < 1:\n-\t\tdie(\"no binaries found in gobin\")\n+\t\treturn \"\", fmt.Errorf(\"No binaries found in gobin.\")\n+\tcase len(fi) == 1:\n+\t\tname := fi[0].Name()\n+\t\tif opts.useBinary != \"\" && name != opts.useBinary {\n+\t\t\treturn \"\", fmt.Errorf(\"No such binary found in gobin: %q. There is only %q\", opts.useBinary, name)\n+\t\t}\n+\t\tDebug(\"found binary: \", name)\n+\t\treturn name, nil\n \tcase len(fi) > 1:\n-\t\tdebug(fmt.Sprint(fi))\n-\t\tdie(\"can't handle multiple binaries\")\n+\t\tnames := []string{}\n+\t\tfor _, v := range fi {\n+\t\t\tnames = append(names, v.Name())\n+\t\t}\n+\t\tif opts.useBinary == \"\" {\n+\t\t\treturn \"\", fmt.Errorf(\"Found multiple binaries in gobin, but --use-binary option is not used. Please specify which binary to put in ACI. Following binaries are available: \\\"%s\\\"\", strings.Join(names, `\", \"`))\n+\t\t}\n+\t\tfor _, v := range names {\n+\t\t\tif v == opts.useBinary {\n+\t\t\t\treturn v, nil\n+\t\t\t}\n+\t\t}\n+\t\treturn \"\", fmt.Errorf(\"No such binary found in gobin: %q. There are following binaries available: \\\"%s\\\"\", opts.useBinary, strings.Join(names, `\", \"`))\n+\t}\n+\treturn \"\", fmt.Errorf(\"Reaching this point shouldn't be possible.\")\n+}\n+\n+func getApp(opts *options, binary string) *types.App {\n+\texec := []string{filepath.Join(\"/\", binary)}\n+\texec = append(exec, opts.exec...)\n+\n+\treturn &types.App{\n+\t\tExec:  exec,\n+\t\tUser:  \"0\",\n+\t\tGroup: \"0\",\n \t}\n-\tfn := fi[0].Name()\n-\tdebug(\"found binary: \", fn)\n+}\n \n-\t// Set up rootfs for ACI layout\n-\trfs := filepath.Join(acidir, \"rootfs\")\n-\terr = os.MkdirAll(rfs, 0755)\n+func getVCSLabel(pathsNames *pathsAndNames) (*types.Label, error) {\n+\tname, value, err := GetVCSInfo(pathsNames.projectPath)\n+\tif err != nil {\n+\t\treturn nil, fmt.Errorf(\"Failed to get VCS info: %v\", err)\n+\t}\n+\tacname, err := types.NewACName(name)\n \tif err != nil {\n-\t\tdie(err.Error())\n+\t\treturn nil, fmt.Errorf(\"Invalid VCS label: %v\", err)\n \t}\n+\treturn &types.Label{\n+\t\tName:  *acname,\n+\t\tValue: value,\n+\t}, nil\n+}\n \n-\t// Move the binary into the rootfs\n-\tep := filepath.Join(rfs, fn)\n-\terr = os.Rename(filepath.Join(gobin, fn), ep)\n+func prepareManifest(opts *options, pathsNames *pathsAndNames, binary string) (*schema.ImageManifest, error) {\n+\tname, err := types.NewACName(pathsNames.imageACName)\n+\t// TODO(jonboulle): could this ever actually happen?\n+\tif err != nil {\n+\t\treturn nil, err\n+\t}\n+\n+\tapp := getApp(opts, binary)\n+\n+\tvcsLabel, err := getVCSLabel(pathsNames)\n \tif err != nil {\n-\t\tdie(err.Error())\n+\t\treturn nil, err\n+\t}\n+\tlabels := types.Labels{\n+\t\t*vcsLabel,\n+\t}\n+\n+\tmanifest := schema.BlankImageManifest()\n+\tmanifest.Name = *name\n+\tmanifest.App = app\n+\tmanifest.Labels = labels\n+\treturn manifest, nil\n+}\n+\n+func copyAssets(opts *options, pathsNames *pathsAndNames) error {\n+\tplaceholderMapping := map[string]string{\n+\t\t\"<PROJPATH>\": pathsNames.projectPath,\n+\t\t\"<GOPATH>\":   pathsNames.goPath,\n+\t}\n+\tif err := PrepareAssets(opts.assets, pathsNames.rootFSPath, placeholderMapping); err != nil {\n+\t\treturn err\n \t}\n-\tdebug(\"moved binary to:\", ep)\n+\treturn nil\n+}\n+\n+func moveBinaryToRootFS(pathsNames *pathsAndNames, binary string) error {\n+\t// Move the binary into the rootfs\n+\tep := filepath.Join(pathsNames.rootFSPath, binary)\n+\tif err := os.Rename(filepath.Join(pathsNames.goBinPath, binary), ep); err != nil {\n+\t\treturn err\n+\t}\n+\tDebug(\"moved binary to: \", ep)\n+\treturn nil\n+}\n \n-\texec := []string{filepath.Join(\"/\", fn)}\n-\texec = append(exec, execOpts...)\n-\t// Build the ACI\n-\tim := schema.ImageManifest{\n-\t\tACKind:    types.ACKind(\"ImageManifest\"),\n-\t\tACVersion: schema.AppContainerVersion,\n-\t\tName:      *name,\n-\t\tApp: &types.App{\n-\t\t\tExec:  exec,\n-\t\t\tUser:  \"0\",\n-\t\t\tGroup: \"0\",\n-\t\t},\n+func writeACI(pathsNames *pathsAndNames, manifest *schema.ImageManifest) error {\n+\tmode := os.O_CREATE | os.O_WRONLY | os.O_TRUNC\n+\tof, err := os.OpenFile(pathsNames.imageFileName, mode, 0644)\n+\tif err != nil {\n+\t\treturn fmt.Errorf(\"Error opening output file: %v\", err)\n \t}\n-\tdebug(im)\n+\tdefer of.Close()\n \n \tgw := gzip.NewWriter(of)\n+\tdefer gw.Close()\n+\n \ttr := tar.NewWriter(gw)\n+\tdefer tr.Close()\n+\n+\t// FIXME: the files in the tar archive are added with the\n+\t// wrong uid/gid. The uid/gid of the aci builder leaks in the\n+\t// tar archive. See: #16\n+\tiw := aci.NewImageWriter(*manifest, tr)\n+\tif err := filepath.Walk(pathsNames.aciDirPath, aci.BuildWalker(pathsNames.aciDirPath, iw)); err != nil {\n+\t\treturn err\n+\t}\n+\tif err := iw.Close(); err != nil {\n+\t\treturn err\n+\t}\n+\tInfo(\"Wrote \", of.Name())\n+\treturn nil\n+}\n+\n+func mainWithError() error {\n+\tInitDebug()\n+\n+\topts, err := getOptions()\n+\tif err != nil {\n+\t\treturn err\n+\t}\n+\n+\tpathsNames, err := getPathsAndNames(opts)\n+\tif err != nil {\n+\t\treturn err\n+\t}\n+\n+\tif opts.keepTmp {\n+\t\tInfo(`Preserving temporary directory \"`, pathsNames.tmpDirPath, `\"`)","path":"goaci.go","position":489,"original_position":489,"commit_id":"f7f50b3fe88d75f793ad68fc751222b4d32059cc","original_commit_id":"f7f50b3fe88d75f793ad68fc751222b4d32059cc","user":{"login":"iaguis","id":507354,"avatar_url":"https://avatars.githubusercontent.com/u/507354?v=3","gravatar_id":"","url":"https://api.github.com/users/iaguis","html_url":"https://github.com/iaguis","followers_url":"https://api.github.com/users/iaguis/followers","following_url":"https://api.github.com/users/iaguis/following{/other_user}","gists_url":"https://api.github.com/users/iaguis/gists{/gist_id}","starred_url":"https://api.github.com/users/iaguis/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/iaguis/subscriptions","organizations_url":"https://api.github.com/users/iaguis/orgs","repos_url":"https://api.github.com/users/iaguis/repos","events_url":"https://api.github.com/users/iaguis/events{/privacy}","received_events_url":"https://api.github.com/users/iaguis/received_events","type":"User","site_admin":false},"body":"It's annoying that Info et al. don't support %q :stuck_out_tongue_closed_eyes: ","created_at":"2015-03-13T14:29:43Z","updated_at":"2015-03-13T14:29:43Z","html_url":"https://github.com/appc/goaci/pull/13#discussion_r26389499","pull_request_url":"https://api.github.com/repos/appc/goaci/pulls/13","_links":{"self":{"href":"https://api.github.com/repos/appc/goaci/pulls/comments/26389499"},"html":{"href":"https://github.com/appc/goaci/pull/13#discussion_r26389499"},"pull_request":{"href":"https://api.github.com/repos/appc/goaci/pulls/13"}}},"pull_request":{"url":"https://api.github.com/repos/appc/goaci/pulls/13","id":30092464,"html_url":"https://github.com/appc/goaci/pull/13","diff_url":"https://github.com/appc/goaci/pull/13.diff","patch_url":"https://github.com/appc/goaci/pull/13.patch","issue_url":"https://api.github.com/repos/appc/goaci/issues/13","number":13,"state":"open","locked":false,"title":"Add assets loading, binary selection and VCS information in manifest","user":{"login":"krnowak","id":96081,"avatar_url":"https://avatars.githubusercontent.com/u/96081?v=3","gravatar_id":"","url":"https://api.github.com/users/krnowak","html_url":"https://github.com/krnowak","followers_url":"https://api.github.com/users/krnowak/followers","following_url":"https://api.github.com/users/krnowak/following{/other_user}","gists_url":"https://api.github.com/users/krnowak/gists{/gist_id}","starred_url":"https://api.github.com/users/krnowak/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/krnowak/subscriptions","organizations_url":"https://api.github.com/users/krnowak/orgs","repos_url":"https://api.github.com/users/krnowak/repos","events_url":"https://api.github.com/users/krnowak/events{/privacy}","received_events_url":"https://api.github.com/users/krnowak/received_events","type":"User","site_admin":false},"body":"This PR fixes #4, #6 and #7. It also refactors a code which might look like a rewrite. Please see the issues mentioned to see how fixes were implemented.","created_at":"2015-02-26T16:27:57Z","updated_at":"2015-03-13T14:29:43Z","closed_at":null,"merged_at":null,"merge_commit_sha":"11168630caad8deb372e38a99d1a7971d49aaa46","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/appc/goaci/pulls/13/commits","review_comments_url":"https://api.github.com/repos/appc/goaci/pulls/13/comments","review_comment_url":"https://api.github.com/repos/appc/goaci/pulls/comments{/number}","comments_url":"https://api.github.com/repos/appc/goaci/issues/13/comments","statuses_url":"https://api.github.com/repos/appc/goaci/statuses/f7f50b3fe88d75f793ad68fc751222b4d32059cc","head":{"label":"endocode:krnowak/work2","ref":"krnowak/work2","sha":"f7f50b3fe88d75f793ad68fc751222b4d32059cc","user":{"login":"endocode","id":4068543,"avatar_url":"https://avatars.githubusercontent.com/u/4068543?v=3","gravatar_id":"","url":"https://api.github.com/users/endocode","html_url":"https://github.com/endocode","followers_url":"https://api.github.com/users/endocode/followers","following_url":"https://api.github.com/users/endocode/following{/other_user}","gists_url":"https://api.github.com/users/endocode/gists{/gist_id}","starred_url":"https://api.github.com/users/endocode/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/endocode/subscriptions","organizations_url":"https://api.github.com/users/endocode/orgs","repos_url":"https://api.github.com/users/endocode/repos","events_url":"https://api.github.com/users/endocode/events{/privacy}","received_events_url":"https://api.github.com/users/endocode/received_events","type":"Organization","site_admin":false},"repo":{"id":30922147,"name":"goaci","full_name":"endocode/goaci","owner":{"login":"endocode","id":4068543,"avatar_url":"https://avatars.githubusercontent.com/u/4068543?v=3","gravatar_id":"","url":"https://api.github.com/users/endocode","html_url":"https://github.com/endocode","followers_url":"https://api.github.com/users/endocode/followers","following_url":"https://api.github.com/users/endocode/following{/other_user}","gists_url":"https://api.github.com/users/endocode/gists{/gist_id}","starred_url":"https://api.github.com/users/endocode/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/endocode/subscriptions","organizations_url":"https://api.github.com/users/endocode/orgs","repos_url":"https://api.github.com/users/endocode/repos","events_url":"https://api.github.com/users/endocode/events{/privacy}","received_events_url":"https://api.github.com/users/endocode/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/endocode/goaci","description":"tool to build go projects into appc containers","fork":true,"url":"https://api.github.com/repos/endocode/goaci","forks_url":"https://api.github.com/repos/endocode/goaci/forks","keys_url":"https://api.github.com/repos/endocode/goaci/keys{/key_id}","collaborators_url":"https://api.github.com/repos/endocode/goaci/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/endocode/goaci/teams","hooks_url":"https://api.github.com/repos/endocode/goaci/hooks","issue_events_url":"https://api.github.com/repos/endocode/goaci/issues/events{/number}","events_url":"https://api.github.com/repos/endocode/goaci/events","assignees_url":"https://api.github.com/repos/endocode/goaci/assignees{/user}","branches_url":"https://api.github.com/repos/endocode/goaci/branches{/branch}","tags_url":"https://api.github.com/repos/endocode/goaci/tags","blobs_url":"https://api.github.com/repos/endocode/goaci/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/endocode/goaci/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/endocode/goaci/git/refs{/sha}","trees_url":"https://api.github.com/repos/endocode/goaci/git/trees{/sha}","statuses_url":"https://api.github.com/repos/endocode/goaci/statuses/{sha}","languages_url":"https://api.github.com/repos/endocode/goaci/languages","stargazers_url":"https://api.github.com/repos/endocode/goaci/stargazers","contributors_url":"https://api.github.com/repos/endocode/goaci/contributors","subscribers_url":"https://api.github.com/repos/endocode/goaci/subscribers","subscription_url":"https://api.github.com/repos/endocode/goaci/subscription","commits_url":"https://api.github.com/repos/endocode/goaci/commits{/sha}","git_commits_url":"https://api.github.com/repos/endocode/goaci/git/commits{/sha}","comments_url":"https://api.github.com/repos/endocode/goaci/comments{/number}","issue_comment_url":"https://api.github.com/repos/endocode/goaci/issues/comments{/number}","contents_url":"https://api.github.com/repos/endocode/goaci/contents/{+path}","compare_url":"https://api.github.com/repos/endocode/goaci/compare/{base}...{head}","merges_url":"https://api.github.com/repos/endocode/goaci/merges","archive_url":"https://api.github.com/repos/endocode/goaci/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/endocode/goaci/downloads","issues_url":"https://api.github.com/repos/endocode/goaci/issues{/number}","pulls_url":"https://api.github.com/repos/endocode/goaci/pulls{/number}","milestones_url":"https://api.github.com/repos/endocode/goaci/milestones{/number}","notifications_url":"https://api.github.com/repos/endocode/goaci/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/endocode/goaci/labels{/name}","releases_url":"https://api.github.com/repos/endocode/goaci/releases{/id}","created_at":"2015-02-17T15:08:24Z","updated_at":"2015-02-17T15:08:25Z","pushed_at":"2015-03-13T14:10:20Z","git_url":"git://github.com/endocode/goaci.git","ssh_url":"git@github.com:endocode/goaci.git","clone_url":"https://github.com/endocode/goaci.git","svn_url":"https://github.com/endocode/goaci","homepage":null,"size":171,"stargazers_count":0,"watchers_count":0,"language":"Go","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"appc:master","ref":"master","sha":"eb7a5690b2b46589fa7fdf4c29fbec3d10220b6b","user":{"login":"appc","id":10080092,"avatar_url":"https://avatars.githubusercontent.com/u/10080092?v=3","gravatar_id":"","url":"https://api.github.com/users/appc","html_url":"https://github.com/appc","followers_url":"https://api.github.com/users/appc/followers","following_url":"https://api.github.com/users/appc/following{/other_user}","gists_url":"https://api.github.com/users/appc/gists{/gist_id}","starred_url":"https://api.github.com/users/appc/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/appc/subscriptions","organizations_url":"https://api.github.com/users/appc/orgs","repos_url":"https://api.github.com/users/appc/repos","events_url":"https://api.github.com/users/appc/events{/privacy}","received_events_url":"https://api.github.com/users/appc/received_events","type":"Organization","site_admin":false},"repo":{"id":30182118,"name":"goaci","full_name":"appc/goaci","owner":{"login":"appc","id":10080092,"avatar_url":"https://avatars.githubusercontent.com/u/10080092?v=3","gravatar_id":"","url":"https://api.github.com/users/appc","html_url":"https://github.com/appc","followers_url":"https://api.github.com/users/appc/followers","following_url":"https://api.github.com/users/appc/following{/other_user}","gists_url":"https://api.github.com/users/appc/gists{/gist_id}","starred_url":"https://api.github.com/users/appc/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/appc/subscriptions","organizations_url":"https://api.github.com/users/appc/orgs","repos_url":"https://api.github.com/users/appc/repos","events_url":"https://api.github.com/users/appc/events{/privacy}","received_events_url":"https://api.github.com/users/appc/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/appc/goaci","description":"tool to build go projects into ACIs","fork":false,"url":"https://api.github.com/repos/appc/goaci","forks_url":"https://api.github.com/repos/appc/goaci/forks","keys_url":"https://api.github.com/repos/appc/goaci/keys{/key_id}","collaborators_url":"https://api.github.com/repos/appc/goaci/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/appc/goaci/teams","hooks_url":"https://api.github.com/repos/appc/goaci/hooks","issue_events_url":"https://api.github.com/repos/appc/goaci/issues/events{/number}","events_url":"https://api.github.com/repos/appc/goaci/events","assignees_url":"https://api.github.com/repos/appc/goaci/assignees{/user}","branches_url":"https://api.github.com/repos/appc/goaci/branches{/branch}","tags_url":"https://api.github.com/repos/appc/goaci/tags","blobs_url":"https://api.github.com/repos/appc/goaci/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/appc/goaci/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/appc/goaci/git/refs{/sha}","trees_url":"https://api.github.com/repos/appc/goaci/git/trees{/sha}","statuses_url":"https://api.github.com/repos/appc/goaci/statuses/{sha}","languages_url":"https://api.github.com/repos/appc/goaci/languages","stargazers_url":"https://api.github.com/repos/appc/goaci/stargazers","contributors_url":"https://api.github.com/repos/appc/goaci/contributors","subscribers_url":"https://api.github.com/repos/appc/goaci/subscribers","subscription_url":"https://api.github.com/repos/appc/goaci/subscription","commits_url":"https://api.github.com/repos/appc/goaci/commits{/sha}","git_commits_url":"https://api.github.com/repos/appc/goaci/git/commits{/sha}","comments_url":"https://api.github.com/repos/appc/goaci/comments{/number}","issue_comment_url":"https://api.github.com/repos/appc/goaci/issues/comments{/number}","contents_url":"https://api.github.com/repos/appc/goaci/contents/{+path}","compare_url":"https://api.github.com/repos/appc/goaci/compare/{base}...{head}","merges_url":"https://api.github.com/repos/appc/goaci/merges","archive_url":"https://api.github.com/repos/appc/goaci/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/appc/goaci/downloads","issues_url":"https://api.github.com/repos/appc/goaci/issues{/number}","pulls_url":"https://api.github.com/repos/appc/goaci/pulls{/number}","milestones_url":"https://api.github.com/repos/appc/goaci/milestones{/number}","notifications_url":"https://api.github.com/repos/appc/goaci/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/appc/goaci/labels{/name}","releases_url":"https://api.github.com/repos/appc/goaci/releases{/id}","created_at":"2015-02-02T10:30:15Z","updated_at":"2015-03-04T20:40:31Z","pushed_at":"2015-02-26T13:48:54Z","git_url":"git://github.com/appc/goaci.git","ssh_url":"git@github.com:appc/goaci.git","clone_url":"https://github.com/appc/goaci.git","svn_url":"https://github.com/appc/goaci","homepage":"","size":229,"stargazers_count":28,"watchers_count":28,"language":"Go","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":4,"mirror_url":null,"open_issues_count":10,"forks":4,"open_issues":10,"watchers":28,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/appc/goaci/pulls/13"},"html":{"href":"https://github.com/appc/goaci/pull/13"},"issue":{"href":"https://api.github.com/repos/appc/goaci/issues/13"},"comments":{"href":"https://api.github.com/repos/appc/goaci/issues/13/comments"},"review_comments":{"href":"https://api.github.com/repos/appc/goaci/pulls/13/comments"},"review_comment":{"href":"https://api.github.com/repos/appc/goaci/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/appc/goaci/pulls/13/commits"},"statuses":{"href":"https://api.github.com/repos/appc/goaci/statuses/f7f50b3fe88d75f793ad68fc751222b4d32059cc"}}}}