@@ -35,25 +35,35 @@ func NewTarSum(r io.Reader, dc bool, v Version) (TarSum, error) {
3535 return & tarSum {Reader : r , DisableCompression : dc , tarSumVersion : v }, nil
3636}
3737
38+ // Create a new TarSum, providing a THash to use rather than the DefaultTHash
39+ func NewTarSumHash (r io.Reader , dc bool , v Version , tHash THash ) (TarSum , error ) {
40+ if _ , ok := tarSumVersions [v ]; ! ok {
41+ return nil , ErrVersionNotImplemented
42+ }
43+ return & tarSum {Reader : r , DisableCompression : dc , tarSumVersion : v , tHash : tHash }, nil
44+ }
45+
3846// TarSum is the generic interface for calculating fixed time
3947// checksums of a tar archive
4048type TarSum interface {
4149 io.Reader
4250 GetSums () FileInfoSums
4351 Sum ([]byte ) string
4452 Version () Version
53+ Hash () THash
4554}
4655
4756// tarSum struct is the structure for a Version0 checksum calculation
4857type tarSum struct {
4958 io.Reader
5059 tarR * tar.Reader
5160 tarW * tar.Writer
52- gz writeCloseFlusher
61+ writer writeCloseFlusher
5362 bufTar * bytes.Buffer
54- bufGz * bytes.Buffer
63+ bufWriter * bytes.Buffer
5564 bufData []byte
5665 h hash.Hash
66+ tHash THash
5767 sums FileInfoSums
5868 fileCounter int64
5969 currentFile string
@@ -63,10 +73,36 @@ type tarSum struct {
6373 tarSumVersion Version // this field is not exported so it can not be mutated during use
6474}
6575
76+ func (ts tarSum ) Hash () THash {
77+ return ts .tHash
78+ }
79+
6680func (ts tarSum ) Version () Version {
6781 return ts .tarSumVersion
6882}
6983
84+ // A hash.Hash type generator and its name
85+ type THash interface {
86+ Hash () hash.Hash
87+ Name () string
88+ }
89+
90+ // Convenience method for creating a THash
91+ func NewTHash (name string , h func () hash.Hash ) THash {
92+ return simpleTHash {n : name , h : h }
93+ }
94+
95+ // TarSum default is "sha256"
96+ var DefaultTHash = NewTHash ("sha256" , sha256 .New )
97+
98+ type simpleTHash struct {
99+ n string
100+ h func () hash.Hash
101+ }
102+
103+ func (sth simpleTHash ) Name () string { return sth .n }
104+ func (sth simpleTHash ) Hash () hash.Hash { return sth .h () }
105+
70106func (ts tarSum ) selectHeaders (h * tar.Header , v Version ) (set [][2 ]string ) {
71107 for _ , elem := range [][2 ]string {
72108 {"name" , h .Name },
@@ -113,25 +149,35 @@ func (ts *tarSum) encodeHeader(h *tar.Header) error {
113149 return nil
114150}
115151
152+ func (ts * tarSum ) initTarSum () error {
153+ ts .bufTar = bytes .NewBuffer ([]byte {})
154+ ts .bufWriter = bytes .NewBuffer ([]byte {})
155+ ts .tarR = tar .NewReader (ts .Reader )
156+ ts .tarW = tar .NewWriter (ts .bufTar )
157+ if ! ts .DisableCompression {
158+ ts .writer = gzip .NewWriter (ts .bufWriter )
159+ } else {
160+ ts .writer = & nopCloseFlusher {Writer : ts .bufWriter }
161+ }
162+ if ts .tHash == nil {
163+ ts .tHash = DefaultTHash
164+ }
165+ ts .h = ts .tHash .Hash ()
166+ ts .h .Reset ()
167+ ts .first = true
168+ ts .sums = FileInfoSums {}
169+ return nil
170+ }
171+
116172func (ts * tarSum ) Read (buf []byte ) (int , error ) {
117- if ts .gz == nil {
118- ts .bufTar = bytes .NewBuffer ([]byte {})
119- ts .bufGz = bytes .NewBuffer ([]byte {})
120- ts .tarR = tar .NewReader (ts .Reader )
121- ts .tarW = tar .NewWriter (ts .bufTar )
122- if ! ts .DisableCompression {
123- ts .gz = gzip .NewWriter (ts .bufGz )
124- } else {
125- ts .gz = & nopCloseFlusher {Writer : ts .bufGz }
173+ if ts .writer == nil {
174+ if err := ts .initTarSum (); err != nil {
175+ return 0 , err
126176 }
127- ts .h = sha256 .New ()
128- ts .h .Reset ()
129- ts .first = true
130- ts .sums = FileInfoSums {}
131177 }
132178
133179 if ts .finished {
134- return ts .bufGz .Read (buf )
180+ return ts .bufWriter .Read (buf )
135181 }
136182 if ts .bufData == nil {
137183 switch {
@@ -167,10 +213,10 @@ func (ts *tarSum) Read(buf []byte) (int, error) {
167213 if err := ts .tarW .Close (); err != nil {
168214 return 0 , err
169215 }
170- if _ , err := io .Copy (ts .gz , ts .bufTar ); err != nil {
216+ if _ , err := io .Copy (ts .writer , ts .bufTar ); err != nil {
171217 return 0 , err
172218 }
173- if err := ts .gz .Close (); err != nil {
219+ if err := ts .writer .Close (); err != nil {
174220 return 0 , err
175221 }
176222 ts .finished = true
@@ -189,12 +235,12 @@ func (ts *tarSum) Read(buf []byte) (int, error) {
189235 return 0 , err
190236 }
191237 ts .tarW .Flush ()
192- if _ , err := io .Copy (ts .gz , ts .bufTar ); err != nil {
238+ if _ , err := io .Copy (ts .writer , ts .bufTar ); err != nil {
193239 return 0 , err
194240 }
195- ts .gz .Flush ()
241+ ts .writer .Flush ()
196242
197- return ts .bufGz .Read (buf )
243+ return ts .bufWriter .Read (buf )
198244 }
199245 return n , err
200246 }
@@ -210,26 +256,26 @@ func (ts *tarSum) Read(buf []byte) (int, error) {
210256 }
211257 ts .tarW .Flush ()
212258
213- // Filling the gz writter
214- if _ , err = io .Copy (ts .gz , ts .bufTar ); err != nil {
259+ // Filling the output writer
260+ if _ , err = io .Copy (ts .writer , ts .bufTar ); err != nil {
215261 return 0 , err
216262 }
217- ts .gz .Flush ()
263+ ts .writer .Flush ()
218264
219- return ts .bufGz .Read (buf )
265+ return ts .bufWriter .Read (buf )
220266}
221267
222268func (ts * tarSum ) Sum (extra []byte ) string {
223269 ts .sums .SortBySums ()
224- h := sha256 . New ()
270+ h := ts . tHash . Hash ()
225271 if extra != nil {
226272 h .Write (extra )
227273 }
228274 for _ , fis := range ts .sums {
229275 log .Debugf ("-->%s<--" , fis .Sum ())
230276 h .Write ([]byte (fis .Sum ()))
231277 }
232- checksum := ts .Version ().String () + "+sha256 :" + hex .EncodeToString (h .Sum (nil ))
278+ checksum := ts .Version ().String () + "+" + ts . tHash . Name () + " :" + hex .EncodeToString (h .Sum (nil ))
233279 log .Debugf ("checksum processed: %s" , checksum )
234280 return checksum
235281}
0 commit comments