@@ -2,9 +2,15 @@ package main
2
2
3
3
import (
4
4
"flag"
5
+ "net/url"
6
+ "os"
5
7
"os/exec"
8
+ "os/user"
9
+ "path/filepath"
10
+ "strings"
6
11
7
12
"github.com/fatih/color"
13
+ "golang.org/x/xerrors"
8
14
9
15
"go.coder.com/flog"
10
16
)
@@ -39,18 +45,84 @@ func (gf *globalFlags) ensureDockerDaemon() {
39
45
}
40
46
41
47
func requireRepo (conf config , prefs schemaPrefs , fl * flag.FlagSet ) repo {
42
- repoURI := fl .Arg (0 )
48
+ var (
49
+ repoURI = strings .Join (fl .Args (), "/" )
50
+ r repo
51
+ err error
52
+ )
53
+
43
54
if repoURI == "" {
44
55
flog .Fatal ("Argument <repo> must be provided." )
45
56
}
46
57
47
- r , err := parseRepo (defaultSchema (conf , prefs ), conf .DefaultHost , conf .DefaultOrganization , repoURI )
58
+ // if this returns a non-empty string know it's pointing to a valid project on disk
59
+ // an error indicates an existing path outside of the project dir
60
+ repoName , err := pathIsRunnable (conf , repoURI )
48
61
if err != nil {
49
- flog .Fatal ("failed to parse repo %q: %v" , repoURI , err )
62
+ flog .Fatal (err .Error ())
63
+ }
64
+
65
+ if repoName != "" {
66
+ // we only need the path since the repo exists on disk.
67
+ // there's not currently way for us to figure out the host anyways
68
+ r = repo {URL : & url.URL {Path : repoName }}
69
+ } else {
70
+ r , err = parseRepo (defaultSchema (conf , prefs ), conf .DefaultHost , conf .DefaultOrganization , repoURI )
71
+ if err != nil {
72
+ flog .Fatal ("failed to parse repo %q: %v" , repoURI , err )
73
+ }
50
74
}
75
+
76
+ // check if path is pointing to a subdirectory
77
+ if sp := strings .Split (r .Path , "/" ); len (sp ) > 2 {
78
+ r .Path = strings .Join (sp [:2 ], "/" )
79
+ r .subdir = strings .Join (sp [2 :], "/" )
80
+ }
81
+
51
82
return r
52
83
}
53
84
85
+ // pathIsRunnable returns the container name if the given path exists and is
86
+ // in the projects directory, else an empty string. An error is returned if
87
+ // and only if the path exists but it isn't in the user's project directory.
88
+ func pathIsRunnable (conf config , path string ) (cnt string , _ error ) {
89
+ fp , err := filepath .Abs (path )
90
+ if err != nil {
91
+ return
92
+ }
93
+
94
+ s , err := os .Stat (fp )
95
+ if err != nil {
96
+ return
97
+ }
98
+
99
+ if ! s .IsDir () {
100
+ return
101
+ }
102
+
103
+ pre := expandRoot (conf .ProjectRoot )
104
+ if pre [len (pre )- 1 ] != '/' {
105
+ pre = pre + "/"
106
+ }
107
+
108
+ // path exists but doesn't belong to projects directory, return error
109
+ if ! strings .HasPrefix (fp , pre [:len (pre )- 1 ]) {
110
+ return "" , xerrors .Errorf ("directory %s exists but isn't in projects directory" , fp )
111
+ }
112
+
113
+ split := strings .Split (fp , "/" )
114
+ if len (split ) < 2 {
115
+ return
116
+ }
117
+
118
+ return strings .TrimPrefix (fp , pre ), nil
119
+ }
120
+
121
+ func expandRoot (path string ) string {
122
+ u , _ := user .Current ()
123
+ return strings .Replace (path , "~/" , u .HomeDir + "/" , 1 )
124
+ }
125
+
54
126
func defaultSchema (conf config , prefs schemaPrefs ) string {
55
127
switch {
56
128
case prefs .ssh :
0 commit comments