Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Doc: golint-ify path package. #4689

Merged
merged 1 commit into from
Feb 13, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 25 additions & 4 deletions path/path.go
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// Package path contains utilities to work with ipfs paths.
package path

import (
Expand All @@ -11,20 +12,29 @@ import (
// ErrBadPath is returned when a given path is incorrectly formatted
var ErrBadPath = errors.New("invalid 'ipfs ref' path")

// A Path represents an ipfs content path:
// * /<cid>/path/to/file
// * /ipfs/<cid>
// * /ipns/<cid>/path/to/folder
// * etc
type Path string

// ^^^
// TODO: debate making this a private struct wrapped in a public interface
// would allow us to control creation, and cache segments.
type Path string

// FromString safely converts a string type to a Path type
// FromString safely converts a string type to a Path type.
func FromString(s string) Path {
return Path(s)
}

// FromCid safely converts a cid.Cid type to a Path type
// FromCid safely converts a cid.Cid type to a Path type.
func FromCid(c *cid.Cid) Path {
return Path("/ipfs/" + c.String())
}

// Segments returns the different elements of a path
// (elements are delimited by a /).
func (p Path) Segments() []string {
cleaned := path.Clean(string(p))
segments := strings.Split(cleaned, "/")
Expand All @@ -37,6 +47,7 @@ func (p Path) Segments() []string {
return segments
}

// String converts a path to string.
func (p Path) String() string {
return string(p)
}
Expand Down Expand Up @@ -65,10 +76,16 @@ func (p Path) PopLastSegment() (Path, string, error) {
return newPath, segs[len(segs)-1], nil
}

// FromSegments returns a path given its different segments.
func FromSegments(prefix string, seg ...string) (Path, error) {
return ParsePath(prefix + strings.Join(seg, "/"))
}

// ParsePath returns a well-formed ipfs Path.
// The returned path will always be prefixed with /ipfs/ or /ipns/.
// The prefix will be added if not present in the given string.
// This function will return an error when the given string is
// not a valid ipfs path.
func ParsePath(txt string) (Path, error) {
parts := strings.Split(txt, "/")
if len(parts) == 1 {
Expand All @@ -78,7 +95,7 @@ func ParsePath(txt string) (Path, error) {
}
}

// if the path doesnt being with a '/'
// if the path doesnt begin with a '/'
// we expect this to start with a hash, and be an 'ipfs' path
if parts[0] != "" {
if _, err := ParseCidToPath(parts[0]); err != nil {
Expand All @@ -103,6 +120,7 @@ func ParsePath(txt string) (Path, error) {
return Path(txt), nil
}

// ParseCidToPath takes a CID in string form and returns a valid ipfs Path.
func ParseCidToPath(txt string) (Path, error) {
if txt == "" {
return "", ErrNoComponents
Expand All @@ -116,15 +134,18 @@ func ParseCidToPath(txt string) (Path, error) {
return FromCid(c), nil
}

// IsValid checks if a path is a valid ipfs Path.
func (p *Path) IsValid() error {
_, err := ParsePath(p.String())
return err
}

// Join joins strings slices using /
func Join(pths []string) string {
return strings.Join(pths, "/")
}

// SplitList splits strings usings /
func SplitList(pth string) []string {
return strings.Split(pth, "/")
}
23 changes: 14 additions & 9 deletions path/resolver.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ import (

var log = logging.Logger("path")

// Paths after a protocol must contain at least one component
// ErrNoComponents is used when Paths after a protocol
// do not contain at least one component
var ErrNoComponents = errors.New(
"path must contain at least one component")

Expand All @@ -26,6 +27,8 @@ type ErrNoLink struct {
Node *cid.Cid
}

// Error implements the Error interface for ErrNoLink with a useful
// human readable message.
func (e ErrNoLink) Error() string {
return fmt.Sprintf("no link named %q under %s", e.Name, e.Node.String())
}
Expand Down Expand Up @@ -74,6 +77,8 @@ func SplitAbsPath(fpath Path) (*cid.Cid, []string, error) {
return c, parts[1:], nil
}

// ResolveToLastNode walks the given path and returns the ipld.Node
// referenced by the last element in it.
func (r *Resolver) ResolveToLastNode(ctx context.Context, fpath Path) (ipld.Node, []string, error) {
c, p, err := SplitAbsPath(fpath)
if err != nil {
Expand Down Expand Up @@ -109,13 +114,13 @@ func (r *Resolver) ResolveToLastNode(ctx context.Context, fpath Path) (ipld.Node

// ResolvePath fetches the node for given path. It returns the last item
// returned by ResolvePathComponents.
func (s *Resolver) ResolvePath(ctx context.Context, fpath Path) (ipld.Node, error) {
func (r *Resolver) ResolvePath(ctx context.Context, fpath Path) (ipld.Node, error) {
// validate path
if err := fpath.IsValid(); err != nil {
return nil, err
}

nodes, err := s.ResolvePathComponents(ctx, fpath)
nodes, err := r.ResolvePathComponents(ctx, fpath)
if err != nil || nodes == nil {
return nil, err
}
Expand All @@ -131,7 +136,7 @@ func ResolveSingle(ctx context.Context, ds ipld.NodeGetter, nd ipld.Node, names
// ResolvePathComponents fetches the nodes for each segment of the given path.
// It uses the first path component as a hash (key) of the first node, then
// resolves all other components walking the links, with ResolveLinks.
func (s *Resolver) ResolvePathComponents(ctx context.Context, fpath Path) ([]ipld.Node, error) {
func (r *Resolver) ResolvePathComponents(ctx context.Context, fpath Path) ([]ipld.Node, error) {
evt := log.EventBegin(ctx, "resolvePathComponents", logging.LoggableMap{"fpath": fpath})
defer evt.Done()

Expand All @@ -142,13 +147,13 @@ func (s *Resolver) ResolvePathComponents(ctx context.Context, fpath Path) ([]ipl
}

log.Debug("resolve dag get")
nd, err := s.DAG.Get(ctx, h)
nd, err := r.DAG.Get(ctx, h)
if err != nil {
evt.Append(logging.LoggableMap{"error": err.Error()})
return nil, err
}

return s.ResolveLinks(ctx, nd, parts)
return r.ResolveLinks(ctx, nd, parts)
}

// ResolveLinks iteratively resolves names by walking the link hierarchy.
Expand All @@ -158,7 +163,7 @@ func (s *Resolver) ResolvePathComponents(ctx context.Context, fpath Path) ([]ipl
//
// ResolveLinks(nd, []string{"foo", "bar", "baz"})
// would retrieve "baz" in ("bar" in ("foo" in nd.Links).Links).Links
func (s *Resolver) ResolveLinks(ctx context.Context, ndd ipld.Node, names []string) ([]ipld.Node, error) {
func (r *Resolver) ResolveLinks(ctx context.Context, ndd ipld.Node, names []string) ([]ipld.Node, error) {

evt := log.EventBegin(ctx, "resolveLinks", logging.LoggableMap{"names": names})
defer evt.Done()
Expand All @@ -172,7 +177,7 @@ func (s *Resolver) ResolveLinks(ctx context.Context, ndd ipld.Node, names []stri
ctx, cancel = context.WithTimeout(ctx, time.Minute)
defer cancel()

lnk, rest, err := s.ResolveOnce(ctx, s.DAG, nd, names)
lnk, rest, err := r.ResolveOnce(ctx, r.DAG, nd, names)
if err == dag.ErrLinkNotFound {
evt.Append(logging.LoggableMap{"error": err.Error()})
return result, ErrNoLink{Name: names[0], Node: nd.Cid()}
Expand All @@ -181,7 +186,7 @@ func (s *Resolver) ResolveLinks(ctx context.Context, ndd ipld.Node, names []stri
return result, err
}

nextnode, err := lnk.GetNode(ctx, s.DAG)
nextnode, err := lnk.GetNode(ctx, r.DAG)
if err != nil {
evt.Append(logging.LoggableMap{"error": err.Error()})
return result, err
Expand Down