Commit aa1d7e12 authored by Kirill Smelkov's avatar Kirill Smelkov

go/zodb/zodbtools: Catobj

`zodb catobj` command to dump content of an object - similarly to `git
cat-file`. Two modes: raw and verbose with `zodb dump` like headers for
the object present.

There is no such command currently in zodbtools/py.
parent 27d02ad5
// Copyright (C) 2017 Nexedi SA and Contributors.
// Kirill Smelkov <kirr@nexedi.com>
//
// This program is free software: you can Use, Study, Modify and Redistribute
// it under the terms of the GNU General Public License version 3, or (at your
// option) any later version, as published by the Free Software Foundation.
//
// You can also Link and Combine this program with other software covered by
// the terms of any of the Free Software licenses or any of the Open Source
// Initiative approved licenses and Convey the resulting work. Corresponding
// source of such a combination shall include the source code for all other
// software used.
//
// This program is distributed WITHOUT ANY WARRANTY; without even the implied
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
//
// See COPYING file for full licensing terms.
// See https://www.nexedi.com/licensing for rationale and options.
package zodbtools
// Catobj - dump content of a database object
import (
"context"
"flag"
"fmt"
"io"
"os"
"lab.nexedi.com/kirr/go123/prog"
"lab.nexedi.com/kirr/neo/go/zodb"
)
// Catobj dumps content of one ZODB object.
//
// The object is printed in raw form without any headers (see Dumpobj)
func Catobj(ctx context.Context, w io.Writer, stor zodb.IStorage, xid zodb.Xid) error {
buf, _, err := stor.Load(ctx, xid)
if err != nil {
return err
}
_, err = w.Write(buf.Data) // NOTE deleted data are returned as err by Load
buf.Release()
if err != nil {
err = fmt.Errorf("%s: catobj %s: %s", stor.URL(), xid, err)
}
return err
}
// Dumpobj dumps content of one ZODB object with zodbdump-like header
func Dumpobj(ctx context.Context, w io.Writer, stor zodb.IStorage, xid zodb.Xid, hashOnly bool) error {
var objInfo zodb.DataInfo
buf, serial, err := stor.Load(ctx, xid)
if err != nil {
return err
}
objInfo.Oid = xid.Oid
objInfo.Tid = serial
objInfo.Data = buf.Data
objInfo.DataTidHint = 0 // no copy detection at catobj - just dump raw content
d := dumper{W: w, HashOnly: hashOnly}
err = d.DumpData(&objInfo)
buf.Release()
return err
}
// ----------------------------------------
const catobjSummary = "dump content of a database object"
func catobjUsage(w io.Writer) {
fmt.Fprintf(w,
`Usage: zodb catobj [OPTIONS] <storage> xid...
Dump content of a ZODB database object.
<storage> is an URL (see 'zodb help zurl') of a ZODB-storage.
xid is object address (see 'zodb help xid').
Options:
-h --help this help text.
-hashonly dump only hashes of objects without content.
-raw dump object data without any headers. Only one object allowed.
`)
}
func catobjMain(argv []string) {
hashOnly := false
raw := false
flags := flag.FlagSet{Usage: func() { catobjUsage(os.Stderr) }}
flags.Init("", flag.ExitOnError)
flags.BoolVar(&hashOnly, "hashonly", hashOnly, "dump only hashes of objects")
flags.BoolVar(&raw, "raw", hashOnly, "dump object data without any headers. Only one object allowed.")
// TODO also -batch to serve objects a-la `git cat-file --batch` ?
flags.Parse(argv[1:])
argv = flags.Args()
if len(argv) < 2 {
flags.Usage()
prog.Exit(2)
}
storUrl := argv[0]
if hashOnly && raw {
prog.Fatal("-hashonly & -raw are incompatible")
}
xidv := []zodb.Xid{}
for _, arg := range argv[1:] {
xid, err := zodb.ParseXid(arg)
if err != nil {
prog.Fatal(err)
}
xidv = append(xidv, xid)
}
if raw && len(xidv) > 1 {
prog.Fatal("only 1 object allowed with -raw")
}
ctx := context.Background()
stor, err := zodb.OpenStorage(ctx, storUrl, &zodb.OpenOptions{ReadOnly: true})
if err != nil {
prog.Fatal(err)
}
// TODO defer stor.Close()
catobj := func(xid zodb.Xid) error {
if raw {
return Catobj(ctx, os.Stdout, stor, xid)
} else {
return Dumpobj(ctx, os.Stdout, stor, xid, hashOnly)
}
}
for _, xid := range xidv {
err = catobj(xid)
if err != nil {
prog.Fatal(err)
}
}
}
......@@ -27,6 +27,7 @@ var commands = prog.CommandRegistry{
// NOTE the order commands are listed here is the order how they will appear in help
{"info", infoSummary, infoUsage, infoMain},
{"dump", dumpSummary, dumpUsage, dumpMain},
{"catobj", catobjSummary, catobjUsage, catobjMain},
}
// main zodbtools driver
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment