Add tijo-cat command
Dependencies
- [2]
7D7CMNN3Handle Edit hunks - [3]
DF5RFSLHRead directory entries - [4]
EYPCPIP7Apply changes and build a graph - [*]
AYLFNM5CAdd the ability to output the contents of a file.
Change contents
- edit in pristine.go at line 4
"errors" - replacement in pristine.go at line 55
return blocks[i].Start >= posreturn blocks[i].Start == pos || blocks[i].End > pos - replacement in pristine.go at line 63
// TODO: split blocksreturn nilif blocks[i].Start > pos {return nil}return g.splitBlock(blocks[i], pos) - edit in pristine.go at line 246
}// RootDirectory returns the "inode" block corresponding to the root directory// of the repository.func (g *Graph) RootDirectory() (*Block, error) {b := g.Rootfor i := 0; i < 2; i++ {var next *Blockfor _, e := range b.Edges {if e.Flag&EdgeFlagsDeleted != 0 {continue}if e.Flag&EdgeFlagsFolder == 0 {return nil, errors.New("non-folder edge found while looking for root directory")}next = e.Tobreak}if next == nil {return nil, errors.New("no root directory found")}b = next}return b, nil - edit in output.go at line 7[6.72][6.72]
"path""strings" - edit in output.go at line 215
}func FollowPath(g *Graph, p string) (DirEntry, error) {p = path.Clean(p)names := strings.Split(p, "/")dir, err := g.RootDirectory()if err != nil {return DirEntry{}, err}for level, name := range names {entries, err := ReadDir(dir)if err != nil {return DirEntry{}, err}var entry DirEntryfor _, e := range entries {if e.Name == name {entry = ebreak}}if entry == (DirEntry{}) {return DirEntry{}, fmt.Errorf("not found: %s", path.Join(names[:level+1]...))}if level == len(names)-1 {return entry, nil}if !entry.IsDirectory {return DirEntry{}, fmt.Errorf("not a directory: %s", path.Join(names[:level+1]...))}dir = entry.Inode}panic("unreachable") - file addition: tijo-cat[4.12919]
- file addition: main.go[0.1484]
// The tijo-cat command prints the content of the specified file or files to// standard output.package mainimport ("fmt""os""os/exec""strings""pijul-go")func printErrorAndExit(description string, err error) {msg := err.Error()if err, ok := err.(*exec.ExitError); ok && len(err.Stderr) > 0 {msg = string(err.Stderr)}fmt.Fprintln(os.Stderr, description, msg)os.Exit(2)}func main() {hashLog, err := exec.Command("pijul", "log", "--hash-only").Output()if err != nil {printErrorAndExit("error listing changes:", err)}hashes := strings.Fields(string(hashLog))parsedHashes := make([]pijul.Hash, 0, len(hashes))for i := len(hashes) - 1; i >= 0; i-- {h, err := pijul.HashFromBase32(hashes[i])if err != nil {printErrorAndExit("", fmt.Errorf("error parsing hash %q: %v", hashes[i], err))}parsedHashes = append(parsedHashes, h)}pristine, err := loadChanges(parsedHashes)if err != nil {printErrorAndExit("error loading changes:", err)}for _, filename := range os.Args[1:] {dirEntry, err := pijul.FollowPath(pristine, filename)if err != nil {printErrorAndExit("error finding file:", err)}pijul.OutputFile(os.Stdout, dirEntry.Inode)}}func loadChanges(hashes []pijul.Hash) (*pijul.Graph, error) {pristine := pijul.NewGraph()for _, h := range hashes {hs := h.String()data, err := os.ReadFile(fmt.Sprintf(".pijul/changes/%s/%s.change", hs[:2], hs[2:]))if err != nil {return nil, fmt.Errorf("error reading change %s: %w", hs, err)}c, err := pijul.DeserializeChange(data)if err != nil {return nil, fmt.Errorf("error deserializing change %s: %w", hs, err)}err = pristine.ApplyChange(h, c)if err != nil {return nil, fmt.Errorf("error applying change %s: %w", hs, err)}}return pristine, nil}