func runRevlog(cmd *Command, w io.Writer, args []string) { if len(args) == 0 { fatalf("missing argument: revlog index file") } index, err := revlog.Open(storeName(args[0])) if err != nil { fatalf("%s", err) } if *revlogR == -1 { index.Dump(w) return } r, err := revlog.FileRevSpec(*revlogR).Lookup(index) if err != nil { fatalf("%s", err) } if !*revlogBuild { dh := &dataHelper{} d, err := r.GetData(dh) if dh.file != nil { dh.file.Close() } if err != nil { fatalf("%s", err) } if r.IsBase() { w.Write(d) } else { hunks, err := patch.Parse(d) if err != nil { fatalf("%s", err) } for _, h := range hunks { h.Dump(w) } } } else { fb := revlog.NewFileBuilder() err = fb.BuildWrite(w, r) if err != nil { fatalf("%s", err) } } }
func (p *FileBuilder) PreparePatch(r *Rec) (f *FilePatch, err error) { var prevPatch []patch.Hunk rsav := r dc := p.dataCache if dc == nil { dc = noCache{} } if !p.data.keepOpen { defer p.CloseData() } for { d := dc.Get(r.i) if d == nil { d, err = r.GetData(&p.data) if err != nil { err = fmt.Errorf("rev %d: get data: %v", r.i, err) return } dc.Store(r.i, d) } if r.IsBase() { f = new(FilePatch) if rsav.IsStartOfBranch() { if r == rsav { // The normal case, rsav is a base revision, the // complete meta header is at the top of the data f.MetaData = scanMetaData(d) f.MetaSkip = len(f.MetaData) } else if len(prevPatch) > 0 { baseMeta := scanMetaData(d) skipFirst := false prevPatch[0].Adjust(func(begin, end int, data []byte) []byte { if n := len(baseMeta); n > 0 && begin >= 2 && end <= n-2 { // A rare case: There is a meta header at the top of the // data of the base revision (already parsed into tmp), but // there's also the first patch that modifies some content of the // meta header. (For a more robust solution the patches // following the first one would need to be checked too // whether they are located within the original meta header.) // An example is: // hgo revlog $GOROOT/.hg/store/data/test/fixedbugs/bug136.go.i // file revision 1 b := &p.metaBuf b.Reset() b.Write(baseMeta[:begin]) b.Write(data) b.Write(baseMeta[end:]) f.MetaSkip = n f.MetaData = b.Bytes() skipFirst = true return data[:0] } // Another rare case, rsav is an incremental revision, the // meta header is at the top of the first hunk. // Example: hgo revlog -r 1 $PLAN9/.hg/store/data/src/cmd/dd.c.i if begin > 0 { return data } f.MetaData = scanMetaData(data) return data[len(f.MetaData):] }) if skipFirst { prevPatch = prevPatch[1:] } } } f.baseData = d f.patch = prevPatch f.rev = rsav f.fb = p return } hunks, err1 := patch.Parse(d) if err1 != nil { err = err1 return } if prevPatch == nil { prevPatch = hunks } else { prevPatch = p.w.JoinPatches(hunks, prevPatch) p.swap() } r = r.Prev() } panic("not reached") }