github.com/pengwynn/gh@v1.0.1-0.20140118055701-14327ca3942e/gh_task.go (about) 1 // +build gotask 2 3 package main 4 5 import ( 6 "fmt" 7 "github.com/jingweno/gotask/tasking" 8 "io" 9 "io/ioutil" 10 "os" 11 "path/filepath" 12 "runtime" 13 ) 14 15 // NAME 16 // install-deps - install dependencies with go get 17 // 18 // DESCRIPTION 19 // Install dependencies with go get. 20 func TaskInstallDeps(t *tasking.T) { 21 deps := []string{ 22 "github.com/laher/goxc", 23 } 24 25 for _, dep := range deps { 26 t.Logf("Installing %s\n", dep) 27 err := t.Exec("go get", dep) 28 if err != nil { 29 t.Fatalf("Can't download dependency %s", err) 30 } 31 } 32 } 33 34 // NAME 35 // package - cross compile gh and package it 36 // 37 // DESCRIPTION 38 // Cross compile gh and package it into PWD/target 39 func TaskPackage(t *tasking.T) { 40 gopath, err := ioutil.TempDir("", "gh-build") 41 os.Setenv("GOPATH", gopath) 42 t.Logf("GOPATH=%s\n", gopath) 43 44 path := fmt.Sprintf("%s%c%s", filepath.Join(gopath, "bin"), os.PathListSeparator, os.Getenv("PATH")) 45 os.Setenv("PATH", path) 46 t.Logf("PATH=%s\n", path) 47 48 t.Logf("Packaging for %s...\n", runtime.GOOS) 49 50 t.Log("Installing dependencies...") 51 TaskInstallDeps(t) 52 53 pwd, err := os.Getwd() 54 if err != nil { 55 t.Fatal(err) 56 } 57 58 ghPath := filepath.Join(gopath, "src", "github.com", "jingweno", "gh") 59 t.Logf("Copying source from %s to %s\n", pwd, ghPath) 60 err = copyDir(pwd, ghPath) 61 if err != nil { 62 t.Fatal(err) 63 } 64 err = os.Chdir(ghPath) 65 if err != nil { 66 t.Fatal(err) 67 } 68 69 t.Log("Cross-compiling...") 70 godepPath := filepath.Join(ghPath, "Godeps", "_workspace") 71 gopath = fmt.Sprintf("%s%c%s", gopath, os.PathListSeparator, godepPath) 72 os.Setenv("GOPATH", gopath) 73 TaskCrossCompile(t) 74 75 source := filepath.Join(ghPath, "target") 76 target := filepath.Join(pwd, "target") 77 t.Logf("Copying build artifacts from %s to %s...\n", source, target) 78 err = mkdirAll(target) 79 if err != nil { 80 t.Fatal(err) 81 } 82 83 err = copyBuildArtifacts(source, target) 84 if err != nil { 85 t.Fatal(err) 86 } 87 } 88 89 // NAME 90 // bottle - build homebrew bottle for gh 91 // 92 // DESCRIPTION 93 // Build homebrew bottle for gh into PWD/target. 94 func TaskBottle(t *tasking.T) { 95 pwd, err := os.Getwd() 96 if err != nil { 97 t.Fatal(err) 98 } 99 100 target := filepath.Join(pwd, "target") 101 err = mkdirAll(target) 102 if err != nil { 103 t.Fatal(err) 104 } 105 106 err = t.Exec("brew", "list", "gh") 107 if err == nil { 108 err := t.Exec("brew", "uninstall", "gh") 109 if err != nil { 110 t.Fatal(err) 111 } 112 } 113 114 err = t.Exec("brew", "install", "--build-from-source", "--build-bottle", "gh") 115 if err != nil { 116 t.Fatal(err) 117 } 118 119 err = os.Chdir(target) 120 if err != nil { 121 t.Fatal(err) 122 } 123 124 err = t.Exec("brew", "bottle", "gh") 125 if err != nil { 126 t.Fatal(err) 127 } 128 } 129 130 // NAME 131 // cross-compile - cross-compiles gh for current platform. 132 // 133 // DESCRIPTION 134 // Cross-compiles gh for current platform. Build artifacts will be in target/VERSION 135 func TaskCrossCompile(t *tasking.T) { 136 t.Logf("Cross-compiling gh for %s...\n", runtime.GOOS) 137 t.Logf("GOPATH=%s\n", os.Getenv("GOPATH")) 138 err := t.Exec("goxc", "-wd=.", "-os="+runtime.GOOS, "-c="+runtime.GOOS) 139 if err != nil { 140 t.Fatalf("Can't cross-compile gh: %s\n", err) 141 } 142 } 143 144 func copyBuildArtifacts(srcDir, destDir string) error { 145 artifacts := findBuildArtifacts(srcDir) 146 for _, artifact := range artifacts { 147 target := filepath.Join(destDir, filepath.Base(artifact)) 148 fmt.Printf("Copying %s to %s\n", artifact, target) 149 err := copyFile(artifact, target) 150 if err != nil { 151 return err 152 } 153 } 154 155 return nil 156 } 157 158 func copyFile(source, dest string) error { 159 sf, err := os.Open(source) 160 if err != nil { 161 return err 162 } 163 defer sf.Close() 164 165 df, err := os.Create(dest) 166 if err != nil { 167 return err 168 } 169 defer df.Close() 170 171 _, err = io.Copy(df, sf) 172 173 if err == nil { 174 si, err := os.Stat(source) 175 if err != nil { 176 err = os.Chmod(dest, si.Mode()) 177 } 178 } 179 180 return err 181 } 182 183 func copyDir(source, dest string) (err error) { 184 fi, err := os.Stat(source) 185 if err != nil { 186 return err 187 } 188 189 if !fi.IsDir() { 190 return fmt.Errorf("Source is not a directory") 191 } 192 193 _, err = os.Open(dest) 194 if !os.IsNotExist(err) { 195 return fmt.Errorf("Destination already exists") 196 } 197 198 err = os.MkdirAll(dest, fi.Mode()) 199 if err != nil { 200 return err 201 } 202 203 entries, err := ioutil.ReadDir(source) 204 for _, entry := range entries { 205 sfp := filepath.Join(source, entry.Name()) 206 dfp := filepath.Join(dest, entry.Name()) 207 if entry.IsDir() { 208 err = copyDir(sfp, dfp) 209 if err != nil { 210 return err 211 } 212 } else { 213 err = copyFile(sfp, dfp) 214 if err != nil { 215 return err 216 } 217 } 218 } 219 220 return 221 } 222 223 func findBuildArtifacts(root string) (artifacts []string) { 224 filepath.Walk(root, func(path string, info os.FileInfo, err error) error { 225 ext := filepath.Ext(path) 226 if ext == ".deb" || ext == ".zip" || ext == ".gz" { 227 artifacts = append(artifacts, path) 228 } 229 230 return nil 231 }) 232 233 return 234 } 235 236 func mkdirAll(dir string) error { 237 return os.MkdirAll(dir, 0777) 238 }