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  }