// archiveData archives a tree fictious data. // Returns (tree of sha1s, name of the node, sha1 of the node entry). // Accept the paths as posix. func archiveData(t testing.TB, cas dumbcaslib.CasTable, nodes dumbcaslib.NodesTable, tree map[string]string) (map[string]string, string, string) { sha1tree, entries := marshalData(t, tree) for k, v := range tree { err := cas.AddEntry(bytes.NewBuffer([]byte(v)), sha1tree[k]) ut.AssertEqualf(t, true, err == nil || err == os.ErrExist, "Unexpected error: %s", err) } entrySha1, err := dumbcaslib.AddBytes(cas, entries) ut.AssertEqual(t, nil, err) // And finally add the node. now := time.Now().UTC() nodeName, err := nodes.AddEntry(&dumbcaslib.Node{entrySha1, "useful comment"}, "fictious") ut.AssertEqual(t, nil, err) ut.AssertEqualf(t, true, strings.HasPrefix(nodeName, now.Format("2006-01")+string(filepath.Separator)), "Invalid node name %s", nodeName) return sha1tree, nodeName, entrySha1 }
// Restores entries and keep going on in case of error. Returns the first seen // error. // Do not overwrite files. A file already present is considered an error. func restoreEntry(l *log.Logger, cas dumbcaslib.CasTable, entry *dumbcaslib.Entry, root string) (count int, out error) { if entry.Sha1 != "" { f, err := cas.Open(entry.Sha1) if err != nil { out = fmt.Errorf("Failed to fetch %s for %s: %s", entry.Sha1, root, err) } else { defer func() { _ = f.Close() }() baseDir := filepath.Dir(root) if err = os.MkdirAll(baseDir, 0755); err != nil && !os.IsExist(err) { out = fmt.Errorf("Failed to create %s: %s", baseDir, err) } else { dst, err := os.OpenFile(root, os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0644) if err != nil { out = fmt.Errorf("Failed to create %s in %s: %s", root, baseDir, err) } else { size, err := io.Copy(dst, f) if err != nil { out = fmt.Errorf("Failed to copy %s: %s", root, err) } else if size != entry.Size { out = fmt.Errorf("Failed to write %s, expected %d, wrote %d", root, entry.Size, size) } else { count++ } } } } if out != nil { l.Printf("%s(%d): %s", root, entry.Size, out) } else { l.Printf("%s(%d)", root, entry.Size) } } for name, child := range entry.Files { c, err := restoreEntry(l, cas, child, filepath.Join(root, name)) if err != nil && out == nil { out = err } count += c } return }
// Archives one item in the CAS table. func (s *stats) archiveItem(item itemToArchive, cas dumbcaslib.CasTable) { f, err := os.Open(item.fullPath) if err != nil { s.errors.Add(1) s.out <- fmt.Sprintf("Failed to archive %s: %s", item.fullPath, err) return } defer func() { _ = f.Close() }() err = cas.AddEntry(f, item.sha1) if os.IsExist(err) { s.nbNotArchived.Add(1) s.bytesNotArchived.Add(item.size) } else if err == nil { s.nbArchived.Add(1) s.bytesArchived.Add(item.size) } else { s.errors.Add(1) s.out <- fmt.Sprintf("Failed to archive %s: %s", item.fullPath, err) } }