Skip to content
This repository was archived by the owner on Apr 28, 2020. It is now read-only.

Allow repos as filepaths in sail run #198

Merged
merged 1 commit into from
Jul 1, 2019
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
78 changes: 75 additions & 3 deletions globalflags.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,15 @@ package main

import (
"flag"
"net/url"
"os"
"os/exec"
"os/user"
"path/filepath"
"strings"

"github.com/fatih/color"
"golang.org/x/xerrors"

"go.coder.com/flog"
)
Expand Down Expand Up @@ -39,18 +45,84 @@ func (gf *globalFlags) ensureDockerDaemon() {
}

func requireRepo(conf config, prefs schemaPrefs, fl *flag.FlagSet) repo {
repoURI := fl.Arg(0)
var (
repoURI = strings.Join(fl.Args(), "/")
r repo
err error
)

if repoURI == "" {
flog.Fatal("Argument <repo> must be provided.")
}

r, err := parseRepo(defaultSchema(conf, prefs), conf.DefaultHost, conf.DefaultOrganization, repoURI)
// if this returns a non-empty string know it's pointing to a valid project on disk
// an error indicates an existing path outside of the project dir
repoName, err := pathIsRunnable(conf, repoURI)
if err != nil {
flog.Fatal("failed to parse repo %q: %v", repoURI, err)
flog.Fatal(err.Error())
}

if repoName != "" {
// we only need the path since the repo exists on disk.
// there's not currently way for us to figure out the host anyways
r = repo{URL: &url.URL{Path: repoName}}
} else {
r, err = parseRepo(defaultSchema(conf, prefs), conf.DefaultHost, conf.DefaultOrganization, repoURI)
if err != nil {
flog.Fatal("failed to parse repo %q: %v", repoURI, err)
}
}

// check if path is pointing to a subdirectory
if sp := strings.Split(r.Path, "/"); len(sp) > 2 {
r.Path = strings.Join(sp[:2], "/")
r.subdir = strings.Join(sp[2:], "/")
}

return r
}

// pathIsRunnable returns the container name if the given path exists and is
// in the projects directory, else an empty string. An error is returned if
// and only if the path exists but it isn't in the user's project directory.
func pathIsRunnable(conf config, path string) (cnt string, _ error) {
fp, err := filepath.Abs(path)
if err != nil {
return
}

s, err := os.Stat(fp)
if err != nil {
return
}

if !s.IsDir() {
return
}

pre := expandRoot(conf.ProjectRoot)
if pre[len(pre)-1] != '/' {
pre = pre + "/"
}

// path exists but doesn't belong to projects directory, return error
if !strings.HasPrefix(fp, pre[:len(pre)-1]) {
return "", xerrors.Errorf("directory %s exists but isn't in projects directory", fp)
}

split := strings.Split(fp, "/")
if len(split) < 2 {
return
}

return strings.TrimPrefix(fp, pre), nil
}

func expandRoot(path string) string {
u, _ := user.Current()
return strings.Replace(path, "~/", u.HomeDir+"/", 1)
}

func defaultSchema(conf config, prefs schemaPrefs) string {
switch {
case prefs.ssh:
Expand Down
11 changes: 5 additions & 6 deletions repo.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (

type repo struct {
*url.URL
subdir string
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't seem to open code-server to the subdirectory, are we planning to handle that in a separate PR?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah see #72 (comment). Right now it just always defaults to the base directory of the project

}

func (r repo) CloneURI() string {
Expand All @@ -27,9 +28,7 @@ func (r repo) CloneURI() string {
}

func (r repo) DockerName() string {
return toDockerName(
r.trimPath(),
)
return toDockerName(r.trimPath())
}

func (r repo) trimPath() string {
Expand All @@ -50,7 +49,7 @@ func parseRepo(defaultSchema, defaultHost, defaultOrganization, name string) (re
return repo{}, xerrors.Errorf("failed to parse repo path: %w", err)
}

r := repo{u}
r := repo{URL: u}

if r.Scheme == "" {
r.Scheme = defaultSchema
Expand Down Expand Up @@ -79,8 +78,8 @@ func parseRepo(defaultSchema, defaultHost, defaultOrganization, name string) (re
// make sure the path doesn't have a trailing .git
r.Path = strings.TrimSuffix(r.Path, ".git")

// non-existent or invalid path
if r.Path == "" || len(strings.Split(r.Path, "/")) != 2 {
// non-existent
if r.Path == "" {
return repo{}, xerrors.Errorf("invalid repo: %s", r.Path)
}

Expand Down