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