6
6
"os"
7
7
"path/filepath"
8
8
"runtime"
9
+ "strings"
9
10
11
+ "github.com/shirou/gopsutil/v3/disk"
10
12
"golang.org/x/xerrors"
11
13
12
14
"github.com/coder/coder/v2/coderd/httpapi"
@@ -26,11 +28,11 @@ func (*agent) HandleLS(rw http.ResponseWriter, r *http.Request) {
26
28
switch {
27
29
case errors .Is (err , os .ErrNotExist ):
28
30
httpapi .Write (ctx , rw , http .StatusNotFound , codersdk.Response {
29
- Message : "Directory does not exist" ,
31
+ Message : err . Error () ,
30
32
})
31
33
case errors .Is (err , os .ErrPermission ):
32
34
httpapi .Write (ctx , rw , http .StatusForbidden , codersdk.Response {
33
- Message : "Permission denied" ,
35
+ Message : err . Error () ,
34
36
})
35
37
default :
36
38
httpapi .Write (ctx , rw , http .StatusInternalServerError , codersdk.Response {
@@ -44,28 +46,27 @@ func (*agent) HandleLS(rw http.ResponseWriter, r *http.Request) {
44
46
}
45
47
46
48
func listFiles (query LSQuery ) (LSResponse , error ) {
47
- var base string
49
+ var fullPath [] string
48
50
switch query .Relativity {
49
51
case LSRelativityHome :
50
52
home , err := os .UserHomeDir ()
51
53
if err != nil {
52
54
return LSResponse {}, xerrors .Errorf ("failed to get user home directory: %w" , err )
53
55
}
54
- base = home
56
+ fullPath = [] string { home }
55
57
case LSRelativityRoot :
56
58
if runtime .GOOS == "windows" {
57
- // TODO: Eventually, we could have a empty path with a root base
58
- // return all drives.
59
- // C drive should be good enough for now.
60
- base = "C:\\ "
59
+ if len (query .Path ) == 0 {
60
+ return listDrives ()
61
+ }
61
62
} else {
62
- base = "/"
63
+ fullPath = [] string { "/" }
63
64
}
64
65
default :
65
66
return LSResponse {}, xerrors .Errorf ("unsupported relativity type %q" , query .Relativity )
66
67
}
67
68
68
- fullPath : = append ([] string { base } , query .Path ... )
69
+ fullPath = append (fullPath , query .Path ... )
69
70
absolutePathString , err := filepath .Abs (filepath .Join (fullPath ... ))
70
71
if err != nil {
71
72
return LSResponse {}, xerrors .Errorf ("failed to get absolute path: %w" , err )
@@ -97,12 +98,48 @@ func listFiles(query LSQuery) (LSResponse, error) {
97
98
})
98
99
}
99
100
101
+ absolutePath := pathToArray (absolutePathString )
102
+
100
103
return LSResponse {
104
+ AbsolutePath : absolutePath ,
101
105
AbsolutePathString : absolutePathString ,
102
106
Contents : respContents ,
103
107
}, nil
104
108
}
105
109
110
+ func listDrives () (LSResponse , error ) {
111
+ aa , err := disk .Partitions (true )
112
+ if err != nil {
113
+ return LSResponse {}, xerrors .Errorf ("failed to get partitions: %w" , err )
114
+ }
115
+ contents := make ([]LSFile , 0 , len (aa ))
116
+ for _ , a := range aa {
117
+ name := a .Mountpoint + string (os .PathSeparator )
118
+ contents = append (contents , LSFile {
119
+ Name : name ,
120
+ AbsolutePathString : name ,
121
+ IsDir : true ,
122
+ })
123
+ }
124
+
125
+ return LSResponse {
126
+ AbsolutePath : []string {},
127
+ AbsolutePathString : "" ,
128
+ Contents : contents ,
129
+ }, nil
130
+ }
131
+
132
+ func pathToArray (path string ) []string {
133
+ out := strings .FieldsFunc (path , func (r rune ) bool {
134
+ return r == os .PathSeparator
135
+ })
136
+ // Drive letters on Windows should have a trailing separator.
137
+ if runtime .GOOS == "windows" && len (out ) > 0 {
138
+ out [0 ] += string (os .PathSeparator )
139
+ }
140
+ return out
141
+ }
142
+
106
143
type LSQuery struct {
107
144
// e.g. [], ["repos", "coder"],
108
145
Path []string `json:"path"`
@@ -112,6 +149,7 @@ type LSQuery struct {
112
149
}
113
150
114
151
type LSResponse struct {
152
+ AbsolutePath []string `json:"absolute_path"`
115
153
// Returned so clients can display the full path to the user, and
116
154
// copy it to configure file sync
117
155
// e.g. Windows: "C:\\Users\\coder"
0 commit comments