github.com/sashka/siva@v1.6.0/cmd/siva/pack.go (about) 1 package main 2 3 import ( 4 "fmt" 5 "io" 6 "io/ioutil" 7 "os" 8 "path/filepath" 9 10 "gopkg.in/src-d/go-siva.v1" 11 ) 12 13 type CmdPack struct { 14 cmd 15 Append bool `long:"append" description:"If append, the files are added to an existing siva file"` 16 Delete bool `long:"delete" description:"If delete, the files are deleted to an existing siva file"` 17 Input struct { 18 Files []string `positional-arg-name:"input" description:"files or directories to be add to the archive."` 19 } `positional-args:"yes"` 20 } 21 22 func (c *CmdPack) Execute(args []string) error { 23 if err := c.validate(); err != nil { 24 return err 25 } 26 27 if err := c.do(); err != nil { 28 if err := os.Remove(c.Args.File); err != nil { 29 return err 30 } 31 32 return err 33 } 34 35 return nil 36 } 37 38 func (c *CmdPack) do() error { 39 if err := c.buildWriter(c.Append); err != nil { 40 return err 41 } 42 43 if err := c.pack(); err != nil { 44 _ = c.close() 45 return err 46 } 47 48 return c.close() 49 } 50 51 func (c *CmdPack) validate() error { 52 if err := c.cmd.validate(); err != nil { 53 return err 54 } 55 56 if len(c.Input.Files) == 0 { 57 return fmt.Errorf("Invalid input count, please add one or more input files/dirs") 58 } 59 60 return nil 61 } 62 63 func (c *CmdPack) pack() error { 64 for _, file := range c.Input.Files { 65 fi, err := os.Stat(file) 66 if err != nil { 67 return fmt.Errorf("Invalid input file/dir %q, no such file", file) 68 } 69 70 if err := c.packPath(file, fi); err != nil { 71 return err 72 } 73 } 74 75 return nil 76 } 77 78 func (c *CmdPack) packPath(fullpath string, fi os.FileInfo) error { 79 if fi.Mode().IsDir() { 80 return c.packDir(fullpath) 81 } 82 83 if !fi.Mode().IsRegular() { 84 return nil 85 } 86 87 return c.packFile(fullpath, fi) 88 } 89 90 func (c *CmdPack) packDir(fullpath string) error { 91 fis, err := ioutil.ReadDir(fullpath) 92 if err != nil { 93 return err 94 } 95 96 for _, fi := range fis { 97 p := filepath.Join(fullpath, fi.Name()) 98 err := c.packPath(p, fi) 99 if err != nil { 100 return err 101 } 102 } 103 104 return nil 105 } 106 107 func (c *CmdPack) packFile(fullpath string, fi os.FileInfo) error { 108 if os.SameFile(c.fi, fi) { 109 fmt.Fprintf(os.Stderr, 110 "skipping %q, cannot archive the target file\n", fullpath) 111 return nil 112 } 113 114 c.println(fullpath) 115 if err := c.writeFileHeader(fullpath, fi); err != nil { 116 return nil 117 } 118 119 return c.writeFile(fullpath, fi) 120 } 121 122 func (c *CmdPack) writeFileHeader(fullpath string, fi os.FileInfo) error { 123 h := &siva.Header{ 124 Name: siva.ToSafePath(fullpath), 125 Mode: fi.Mode(), 126 ModTime: fi.ModTime(), 127 } 128 129 if c.Delete { 130 h.Flags = siva.FlagDeleted 131 } 132 133 if err := c.w.WriteHeader(h); err != nil { 134 return err 135 } 136 137 return nil 138 } 139 140 func (c *CmdPack) writeFile(fullpath string, fi os.FileInfo) error { 141 f, err := os.Open(fullpath) 142 if err != nil { 143 return err 144 } 145 146 defer f.Close() 147 n, err := io.Copy(c.w, f) 148 if err != nil { 149 return err 150 } 151 152 if n != fi.Size() { 153 return fmt.Errorf("unexpected bytes written") 154 } 155 156 return c.w.Flush() 157 }