devtools/{depotview,hackdoc}: tie both together
Change-Id: I0a1ca3b4fa0e0a074eccbe0f8748839b926db9c1
diff --git a/devtools/hackdoc/source/source_depotview.go b/devtools/hackdoc/source/source_depotview.go
new file mode 100644
index 0000000..6a256be
--- /dev/null
+++ b/devtools/hackdoc/source/source_depotview.go
@@ -0,0 +1,126 @@
+package source
+
+import (
+ "context"
+ "fmt"
+ "strconv"
+ "strings"
+
+ dvpb "code.hackerspace.pl/hscloud/devtools/depotview/proto"
+)
+
+type DepotViewSourceProvider struct {
+ stub dvpb.DepotViewClient
+}
+
+func NewDepotView(stub dvpb.DepotViewClient) SourceProvider {
+ return &DepotViewSourceProvider{
+ stub: stub,
+ }
+}
+
+func changeRef(ref string) int64 {
+ ref = strings.ToLower(ref)
+ if !strings.HasPrefix(ref, "change/") && !strings.HasPrefix(ref, "cr/") {
+ return 0
+ }
+ n, err := strconv.ParseInt(strings.SplitN(ref, "/", 2)[1], 10, 64)
+ if err != nil {
+ return 0
+ }
+
+ return n
+}
+
+func (s *DepotViewSourceProvider) Source(ctx context.Context, ref string) (Source, error) {
+ var hash string
+ n := changeRef(ref)
+ if n != 0 {
+ res, err := s.stub.ResolveGerritChange(ctx, &dvpb.ResolveGerritChangeRequest{Change: n})
+ if err != nil {
+ return nil, err
+ }
+ hash = res.Hash
+ } else {
+ res, err := s.stub.Resolve(ctx, &dvpb.ResolveRequest{Ref: ref})
+ if err != nil {
+ return nil, err
+ }
+ hash = res.Hash
+ }
+
+ if hash == "" {
+ return nil, nil
+ }
+
+ return &depotViewSource{
+ stub: s.stub,
+ hash: hash,
+ change: n,
+ }, nil
+}
+
+type depotViewSource struct {
+ stub dvpb.DepotViewClient
+ hash string
+ change int64
+}
+
+func (s *depotViewSource) IsFile(ctx context.Context, path string) (bool, error) {
+ res, err := s.stub.Stat(ctx, &dvpb.StatRequest{
+ Hash: s.hash,
+ Path: path,
+ })
+ if err != nil {
+ return false, err
+ }
+ return res.Type == dvpb.StatResponse_TYPE_FILE, nil
+}
+
+func (s *depotViewSource) IsDirectory(ctx context.Context, path string) (bool, error) {
+ res, err := s.stub.Stat(ctx, &dvpb.StatRequest{
+ Hash: s.hash,
+ Path: path,
+ })
+ if err != nil {
+ return false, err
+ }
+ return res.Type == dvpb.StatResponse_TYPE_DIRECTORY, nil
+}
+
+func (s *depotViewSource) ReadFile(ctx context.Context, path string) ([]byte, error) {
+ var data []byte
+ srv, err := s.stub.Read(ctx, &dvpb.ReadRequest{
+ Hash: s.hash,
+ Path: path,
+ })
+ if err != nil {
+ return nil, err
+ }
+ for {
+ res, err := srv.Recv()
+ if err != nil {
+ return nil, err
+ }
+ if len(res.Data) == 0 {
+ break
+ }
+ data = append(data, res.Data...)
+ }
+ return data, nil
+}
+
+func (s *depotViewSource) WebLinks(fpath string) []WebLink {
+ gitURL := fmt.Sprintf(FlagGitwebURLPattern, s.hash, fpath)
+ links := []WebLink{
+ WebLink{Kind: "gitweb", LinkLabel: s.hash[:16], LinkURL: gitURL},
+ }
+
+ if s.change != 0 {
+ gerritLabel := fmt.Sprintf("change %d", s.change)
+ gerritLink := fmt.Sprintf("https://gerrit.hackerspace.pl/%d", s.change)
+ links = append(links, WebLink{Kind: "gerrit", LinkLabel: gerritLabel, LinkURL: gerritLink})
+ }
+
+ return links
+}