github.com/hwaf/hwaf@v0.0.0-20140814122253-5465f73b20f1/cmd_pkg_add.go (about)

     1  package main
     2  
     3  import (
     4  	"bufio"
     5  	"fmt"
     6  	"io"
     7  	"os"
     8  	"path/filepath"
     9  	"strings"
    10  	"sync"
    11  
    12  	"github.com/gonuts/commander"
    13  	"github.com/gonuts/flag"
    14  	"github.com/hwaf/hwaf/vcs"
    15  	//gocfg "github.com/gonuts/config"
    16  )
    17  
    18  func hwaf_make_cmd_pkg_add() *commander.Command {
    19  	cmd := &commander.Command{
    20  		Run:       hwaf_run_cmd_pkg_add,
    21  		UsageLine: "co [options] <pkg-uri> [<local-pkg-name>]",
    22  		Short:     "add a package to the current workarea",
    23  		Long: `
    24  co adds a package to the current workarea.
    25  
    26  ex:
    27   $ hwaf pkg co /foo/pkg
    28   $ hwaf pkg co Control/AthenaKernel
    29   $ hwaf pkg co git://github.com/mana-fwk/mana-core-athenakernel
    30   $ hwaf pkg co git://github.com/mana-fwk/mana-core-athenakernel Control/AthenaKernel
    31   $ hwaf pkg co -b=rel/mana git://github.com/mana-fwk/mana-core-athenakernel Control/AthenaKernel
    32   $ hwaf pkg co -b=AthenaKernel-00-00-01 svn+ssh://svn.cern.ch/reps/atlasoff/Control/AthenaKernel Control/AthenaKernel
    33   $ hwaf pkg co -f=list.of.pkgs.txt
    34  `,
    35  		Flag: *flag.NewFlagSet("hwaf-pkg-co", flag.ExitOnError),
    36  	}
    37  	cmd.Flag.Bool("v", false, "enable verbose output")
    38  	cmd.Flag.String("b", "", "branch to checkout (default=master)")
    39  	cmd.Flag.String("f", "", "path to a file holding a list of packages to retrieve")
    40  
    41  	return cmd
    42  }
    43  
    44  func hwaf_run_cmd_pkg_add(cmd *commander.Command, args []string) error {
    45  	var err error
    46  	n := "hwaf-pkg-" + cmd.Name()
    47  
    48  	verbose := cmd.Flag.Lookup("v").Value.Get().(bool)
    49  	bname := cmd.Flag.Lookup("b").Value.Get().(string)
    50  
    51  	type Request struct {
    52  		pkguri  string
    53  		pkgname string
    54  		pkgtag  string
    55  	}
    56  
    57  	reqs := make([]Request, 0, 2)
    58  
    59  	switch len(args) {
    60  	default:
    61  		return fmt.Errorf("%s: expects 0, 1 or 2 arguments (got %d: %v)", n, len(args), args)
    62  	case 2:
    63  		pkguri := args[0]
    64  		pkgname := args[1]
    65  		reqs = append(reqs,
    66  			Request{
    67  				pkguri:  pkguri,
    68  				pkgname: pkgname,
    69  				pkgtag:  bname,
    70  			},
    71  		)
    72  	case 1:
    73  		pkguri := args[0]
    74  		pkgname := ""
    75  		reqs = append(reqs,
    76  			Request{
    77  				pkguri:  pkguri,
    78  				pkgname: pkgname,
    79  				pkgtag:  bname,
    80  			},
    81  		)
    82  	case 0:
    83  		fname := cmd.Flag.Lookup("f").Value.Get().(string)
    84  		if fname == "" {
    85  			err = fmt.Errorf("%s: you need to give a package URL", n)
    86  			if err != nil {
    87  				return err
    88  			}
    89  		}
    90  		f, err := os.Open(fname)
    91  		if err != nil {
    92  			if err != nil {
    93  				return err
    94  			}
    95  		}
    96  		pkgs := [][]string{}
    97  		scnr := bufio.NewScanner(f)
    98  		for scnr.Scan() {
    99  			line := strings.Trim(scnr.Text(), " \n")
   100  			if strings.HasPrefix(line, "#") {
   101  				continue
   102  			}
   103  			tokens := strings.Split(line, " ")
   104  			pkg := []string{}
   105  			for _, tok := range tokens {
   106  				tok = strings.Trim(tok, " \t")
   107  				if tok != "" {
   108  					pkg = append(pkg, tok)
   109  				}
   110  			}
   111  			if len(pkg) > 0 {
   112  				pkgs = append(pkgs, pkg)
   113  			}
   114  		}
   115  		err = scnr.Err()
   116  		if err != nil && err != io.EOF {
   117  			return err
   118  		}
   119  		for _, pkg := range pkgs {
   120  			switch len(pkg) {
   121  			case 1:
   122  				reqs = append(reqs, Request{
   123  					pkguri:  pkg[0],
   124  					pkgname: "",
   125  					pkgtag:  "",
   126  				})
   127  			case 2:
   128  				reqs = append(reqs, Request{
   129  					pkguri:  pkg[0],
   130  					pkgname: "",
   131  					pkgtag:  pkg[1],
   132  				})
   133  			case 3:
   134  				reqs = append(reqs, Request{
   135  					pkguri:  pkg[0],
   136  					pkgname: pkg[2],
   137  					pkgtag:  pkg[1],
   138  				})
   139  			default:
   140  				return fmt.Errorf("%s: invalid number of pkg-co arguments (expected [1-3], got=%d) args=%v", n, len(pkg), pkg)
   141  			}
   142  		}
   143  	}
   144  
   145  	cfg, err := g_ctx.LocalCfg()
   146  	if err != nil {
   147  		return err
   148  	}
   149  
   150  	pkgdir := "src"
   151  	if cfg.HasOption("hwaf-cfg", "pkgdir") {
   152  		pkgdir, err = cfg.String("hwaf-cfg", "pkgdir")
   153  		if err != nil {
   154  			return err
   155  		}
   156  	}
   157  
   158  	throttle := make(chan struct{}, 1)
   159  	errch := make(chan error)
   160  
   161  	var dblock sync.RWMutex
   162  	var colock sync.RWMutex
   163  
   164  	do_checkout := func(req Request) {
   165  		pkguri := req.pkguri
   166  		pkgname := req.pkgname
   167  		bname := req.pkgtag
   168  
   169  		throttle <- struct{}{}
   170  		defer func() { <-throttle }()
   171  
   172  		if verbose {
   173  			fmt.Printf("%s: checkout package [%s]...\n", n, pkguri)
   174  		}
   175  
   176  		// fmt.Printf(">>> helper(pkguri=%q, pkgname=%q, pkgid=%q, pkgdir=%q)...\n", pkguri, pkgname, bname, pkgdir)
   177  		helper, err := vcs.NewHelper(pkguri, pkgname, bname, pkgdir)
   178  		if err != nil {
   179  			errch <- err
   180  			return
   181  		}
   182  		defer helper.Delete()
   183  
   184  		dir := filepath.Join(helper.RepoDir, helper.PkgName)
   185  		// fmt.Printf(">>> dir=%q\n", dir)
   186  		// fmt.Printf(">>> helper=%#v\n", helper)
   187  
   188  		dblock.RLock()
   189  		if g_ctx.PkgDb.HasPkg(dir) {
   190  			err = fmt.Errorf("%s: package [%s] already in db.\ndid you forget to run 'hwaf pkg rm %s' ?", n, dir, dir)
   191  			errch <- err
   192  			dblock.RUnlock()
   193  			fmt.Printf("%s: checkout package [%s]... [err]\n", n, pkguri)
   194  			return
   195  		}
   196  		dblock.RUnlock()
   197  
   198  		//fmt.Printf(">>> pkgname=%q\n", helper.PkgName)
   199  		if helper.Type == "git" {
   200  			colock.Lock()
   201  		}
   202  		err = helper.Checkout()
   203  		if err != nil {
   204  			errch <- err
   205  			if helper.Type == "git" {
   206  				colock.Unlock()
   207  			}
   208  			fmt.Printf("%s: checkout package [%s]... [err]\n", n, pkguri)
   209  			return
   210  		}
   211  		if helper.Type == "git" {
   212  			colock.Unlock()
   213  		}
   214  
   215  		dblock.Lock()
   216  		err = g_ctx.PkgDb.Add(helper.Type, helper.Repo, helper.RepoDir, dir)
   217  		if err != nil {
   218  			errch <- err
   219  			dblock.Unlock()
   220  			fmt.Printf("%s: checkout package [%s]... [err]\n", n, pkguri)
   221  			return
   222  		}
   223  		dblock.Unlock()
   224  
   225  		err = helper.Delete()
   226  		if err != nil {
   227  			errch <- err
   228  			fmt.Printf("%s: checkout package [%s]... [err]\n", n, pkguri)
   229  			return
   230  		}
   231  
   232  		if verbose {
   233  			fmt.Printf("%s: checkout package [%s]... [ok]\n", n, pkguri)
   234  		}
   235  		errch <- nil
   236  	}
   237  
   238  	for _, req := range reqs {
   239  		go do_checkout(req)
   240  	}
   241  
   242  	errs := make([]error, 0, len(reqs))
   243  	for _ = range reqs {
   244  		err := <-errch
   245  		if err != nil {
   246  			errs = append(errs, err)
   247  		}
   248  	}
   249  
   250  	for _, err := range errs {
   251  		fmt.Fprintf(os.Stderr, "**error** %v\n", err)
   252  	}
   253  
   254  	if len(errs) != 0 {
   255  		return errs[0] // TODO(sbinet) create an ErrorStack type and return that
   256  	}
   257  
   258  	return nil
   259  }
   260  
   261  // EOF