github.com/Xenoex/gopm@v0.6.5/cmd/bin.go (about)

     1  // Copyright 2013-2014 gopm authors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License"): you may
     4  // not use this file except in compliance with the License. You may obtain
     5  // a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
    11  // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
    12  // License for the specific language governing permissions and limitations
    13  // under the License.
    14  
    15  package cmd
    16  
    17  import (
    18  	"fmt"
    19  	"os"
    20  	"path"
    21  	"path/filepath"
    22  	"runtime"
    23  	"strings"
    24  
    25  	"github.com/Unknwon/com"
    26  	"github.com/codegangsta/cli"
    27  
    28  	"github.com/gpmgo/gopm/doc"
    29  	"github.com/gpmgo/gopm/log"
    30  )
    31  
    32  var CmdBin = cli.Command{
    33  	Name:  "bin",
    34  	Usage: "download and link dependencies and build executable binary",
    35  	Description: `Command bin downloads and links dependencies according to gopmfile,
    36  and build executable binary to work directory
    37  
    38  gopm bin <import path>@[<tag|commit|branch>:<value>]
    39  gopm bin <package name>@[<tag|commit|branch>:<value>]
    40  
    41  Can only specify one each time, and only works for projects that 
    42  contain main package`,
    43  	Action: runBin,
    44  	Flags: []cli.Flag{
    45  		cli.BoolFlag{"dir, d", "build binary to given directory(second argument)"},
    46  		cli.BoolFlag{"update, u", "update pakcage(s) and dependencies if any"},
    47  		cli.BoolFlag{"verbose, v", "show process details"},
    48  	},
    49  }
    50  
    51  func runBin(ctx *cli.Context) {
    52  	setup(ctx)
    53  
    54  	if len(ctx.Args()) == 0 {
    55  		log.Error("bin", "Cannot start command:")
    56  		log.Fatal("", "\tNo package specified")
    57  	}
    58  
    59  	installRepoPath = doc.HomeDir + "/repos"
    60  	log.Log("Local repository path: %s", installRepoPath)
    61  
    62  	// Check arguments.
    63  	num := 1
    64  	if ctx.Bool("dir") {
    65  		num = 2
    66  	}
    67  	if len(ctx.Args()) != num {
    68  		log.Error("bin", "Cannot start command:")
    69  		log.Fatal("", "\tMissing indicated path to build binary")
    70  	}
    71  
    72  	// Check if given directory exists.
    73  	if ctx.Bool("dir") && !com.IsDir(ctx.Args()[1]) {
    74  		log.Error("bin", "Cannot start command:")
    75  		log.Fatal("", "\tIndicated path does not exist or is not a directory")
    76  	}
    77  
    78  	// Parse package version.
    79  	info := ctx.Args()[0]
    80  	pkgPath := info
    81  	node := doc.NewNode(pkgPath, pkgPath, doc.BRANCH, "", true)
    82  	if i := strings.Index(info, "@"); i > -1 {
    83  		pkgPath = info[:i]
    84  		node.Type, node.Value = validPath(info[i+1:])
    85  	}
    86  
    87  	// Check package name.
    88  	if !strings.Contains(pkgPath, "/") {
    89  		pkgPath = doc.GetPkgFullPath(pkgPath)
    90  	}
    91  
    92  	node.ImportPath = pkgPath
    93  	node.DownloadURL = pkgPath
    94  
    95  	// Get code.
    96  	downloadPackages(ctx, []*doc.Node{node})
    97  
    98  	// Check if previous steps were successful.
    99  	repoPath := installRepoPath + "/" + pkgPath + versionSuffix(node.Value)
   100  	if !com.IsDir(repoPath) {
   101  		log.Error("bin", "Cannot continue command:")
   102  		log.Fatal("", "\tPrevious steps weren't successful")
   103  	}
   104  
   105  	wd, err := os.Getwd()
   106  	if err != nil {
   107  		log.Error("bin", "Cannot get work directory:")
   108  		log.Fatal("", "\t"+err.Error())
   109  	}
   110  
   111  	// Change to repository path.
   112  	log.Log("Changing work directory to %s", repoPath)
   113  	if err = os.Chdir(repoPath); err != nil {
   114  		log.Error("bin", "Fail to change work directory:")
   115  		log.Fatal("", "\t"+err.Error())
   116  	}
   117  
   118  	defer os.RemoveAll(path.Join(repoPath, doc.VENDOR))
   119  	// Build application.
   120  	buildBinary(ctx)
   121  
   122  	includes := make([]string, 0, 3)
   123  	// Check if previous steps were successful.
   124  	if com.IsFile(doc.GOPM_FILE_NAME) {
   125  		log.Trace("Loading gopmfile...")
   126  		gf := doc.NewGopmfile(".")
   127  
   128  		var err error
   129  		pkgName, err = gf.GetValue("target", "path")
   130  		if err == nil {
   131  			log.Log("Target name: %s", pkgName)
   132  		}
   133  
   134  		includes = strings.Split(gf.MustValue("res", "include"), "|")
   135  	}
   136  
   137  	if len(pkgName) == 0 {
   138  		_, pkgName = filepath.Split(pkgPath)
   139  	}
   140  
   141  	// Because build command moved binary to root path.
   142  	binName := path.Base(pkgName)
   143  	if runtime.GOOS == "windows" {
   144  		binName += ".exe"
   145  	}
   146  	if !com.IsFile(binName) {
   147  		log.Error("bin", "Binary does not exist:")
   148  		log.Error("", "\t"+binName)
   149  		log.Fatal("", "\tPrevious steps weren't successful or the project does not contain main package")
   150  	}
   151  
   152  	// Move binary to given directory.
   153  	movePath := wd
   154  	if ctx.Bool("dir") {
   155  		movePath = ctx.Args()[1]
   156  	}
   157  
   158  	if com.IsExist(movePath + "/" + binName) {
   159  		if err = os.Remove(movePath + "/" + binName); err != nil {
   160  			log.Warn("Cannot remove binary in work directory:")
   161  			log.Warn("\t %s", err)
   162  		}
   163  	}
   164  
   165  	if err = os.Rename(binName, movePath+"/"+binName); err != nil {
   166  		log.Error("bin", "Fail to move binary:")
   167  		log.Fatal("", "\t"+err.Error())
   168  	}
   169  	os.Chmod(movePath+"/"+binName, os.ModePerm)
   170  
   171  	if len(includes) > 0 {
   172  		log.Log("Copying resources to %s", movePath)
   173  		for _, include := range includes {
   174  			if com.IsDir(include) {
   175  				if err = com.CopyDir(include, filepath.Join(movePath, include)); err != nil {
   176  					log.Error("bin", "Fail to copy following resource:")
   177  					log.Error("", "\t"+include)
   178  				}
   179  			}
   180  		}
   181  	}
   182  
   183  	log.Log("Changing work directory back to %s", wd)
   184  	os.Chdir(wd)
   185  
   186  	log.Success("SUCC", "bin", "Command executed successfully!")
   187  	fmt.Println("Binary has been built into: " + movePath)
   188  }