-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgithub-tree.go
258 lines (216 loc) · 6.32 KB
/
github-tree.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
package main
import (
"encoding/json"
"flag"
"fmt"
"io"
"net/http"
"os"
"path/filepath"
)
var (
ownerFlag string
repoFlag string
pathFlag string
maxDepthFlag int
)
type File struct {
Name string `json:"name"`
Type string `json:"type"`
}
func init() {
flag.StringVar(&ownerFlag, "O", "", "Repository owner")
flag.StringVar(&ownerFlag, "owner", "", "Repository owner")
flag.StringVar(&repoFlag, "R", "", "Repository name")
flag.StringVar(&repoFlag, "repo", "", "Repository name")
flag.StringVar(&pathFlag, "P", "", "Path within the repository")
flag.StringVar(&pathFlag, "path", "", "Path within the repository")
flag.IntVar(&maxDepthFlag, "M", 1, "Maximum depth for fetching content")
flag.IntVar(&maxDepthFlag, "maxDepth", 1, "Maximum depth for fetching content")
}
func main() {
// Parse command-line flags
flag.Parse()
// Get the absolute path to github-tree-inputs.txt
inputsFilePath := getAbsolutePath("github-tree-inputs.txt")
// Check if github-tree-inputs.txt exists
_, err := os.Stat(inputsFilePath)
if err == nil {
// The file exists, so read existing inputs from the file
currentOwner, currentRepo, currentPath, currentMaxDepth := readInputsFromFile(inputsFilePath)
// Check if the owner and repo fields are empty
if currentOwner == "" || currentRepo == "" {
panic("The 'owner' and 'repo' fields in github-tree-inputs.txt cannot be empty")
}
// Set default value for maxDepth if not available
if currentMaxDepth < 1 {
currentMaxDepth = 1
}
// Update inputs if flags were provided
if ownerFlag != "" {
currentOwner = ownerFlag
}
if repoFlag != "" {
currentRepo = repoFlag
}
if pathFlag != "" {
currentPath = pathFlag
}
currentMaxDepth = maxDepthFlag
// Update the inputs in the file
updateInputsInFile(inputsFilePath, currentOwner, currentRepo, currentPath, currentMaxDepth)
// Retrieve access token from environment
accessToken := os.Getenv("GITHUB_ACCESS_TOKEN")
if accessToken == "" {
panic("GitHub access token not found in environment")
}
// Fetch files and folders using the updated inputs
fetchFilesAndFolders(accessToken, currentOwner, currentRepo, currentPath, "", 1, currentMaxDepth)
} else {
// The "github-tree-inputs.txt" doesn't exist, so create it
// Set default value for maxDepth if not available
if maxDepthFlag == 0 {
maxDepthFlag = 1
}
// Create a new inputs struct
newInputs := struct {
Owner string `json:"owner"`
Repo string `json:"repo"`
Path string `json:"path"`
MaxDepth int `json:"maxDepth"`
}{
Owner: ownerFlag,
Repo: repoFlag,
Path: pathFlag,
MaxDepth: maxDepthFlag,
}
// Convert to JSON
newInputsJSON, err := json.MarshalIndent(newInputs, "", " ")
if err != nil {
panic(fmt.Errorf("failed to marshal new inputs: %w", err))
}
// Write to the file
err = os.WriteFile(inputsFilePath, newInputsJSON, 0644)
if err != nil {
panic(fmt.Errorf("failed to write new inputs to file: %w", err))
}
// Retrieve access token from environment
accessToken := os.Getenv("GITHUB_ACCESS_TOKEN")
if accessToken == "" {
panic("GitHub access token not found in environment")
}
// Fetch files and folders using the new inputs
fetchFilesAndFolders(accessToken, ownerFlag, repoFlag, pathFlag, "", 1, maxDepthFlag)
}
}
func readInputsFromFile(filePath string) (owner, repo, path string, maxDepth int) {
// Read the contents of the file
fileData, err := os.ReadFile(filePath)
if err != nil {
panic(fmt.Errorf("failed to read inputs from file: %w", err))
}
// Unmarshal the JSON data into a struct
var inputs struct {
Owner string `json:"owner"`
Repo string `json:"repo"`
Path string `json:"path"`
MaxDepth int `json:"maxDepth"`
}
err = json.Unmarshal(fileData, &inputs)
if err != nil {
panic(fmt.Errorf("failed to parse inputs from file: %w", err))
}
return inputs.Owner, inputs.Repo, inputs.Path, inputs.MaxDepth
}
func getAbsolutePath(filePath string) string {
currentDir, err := os.Getwd()
if err != nil {
panic(fmt.Errorf("failed to get current directory: %w", err))
}
return filepath.Join(currentDir, filePath)
}
func fetchFilesAndFolders(accessToken, owner, repo, path, indent string, level, maxDepth int) {
// Stop if the maximum depth has been reached
if level > maxDepth {
return
}
// Make the API request
url := fmt.Sprintf("https://api.github.com/repos/%s/%s/contents/%s", owner, repo, path)
req, err := http.NewRequest("GET", url, nil)
if err != nil {
panic(err)
}
req.Header.Set("Authorization", "Bearer "+accessToken)
client := http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
// Read the response body
body, err := io.ReadAll(resp.Body)
if err != nil {
panic(err)
}
// Unmarshal the response into a slice of File structs
var files []File
err = json.Unmarshal(body, &files)
if err != nil {
panic(err)
}
// Iterate over the files and folders
for i, f := range files {
isLast := i == len(files)-1
if f.Type == "file" {
fmt.Printf("%s%s", indent, getFilePrefix(isLast))
fmt.Println(f.Name)
} else if f.Type == "dir" {
fmt.Printf("%s%s", indent, getDirPrefix(isLast))
fmt.Println(f.Name)
// Recursively fetch files and folders for subdirectory
fetchFilesAndFolders(accessToken, owner, repo, path+"/"+f.Name, indent+getIndentPrefix(isLast), level+1, maxDepth)
}
}
}
func getFilePrefix(isLast bool) string {
if isLast {
return "└── "
}
return "├── "
}
func getDirPrefix(isLast bool) string {
if isLast {
return "└── "
}
return "├── "
}
func getIndentPrefix(isLast bool) string {
if isLast {
return " "
}
return "│ "
}
func updateInputsInFile(filePath, owner, repo, path string, maxDepth int) {
// Create the new inputs struct
newInputs := struct {
Owner string `json:"owner"`
Repo string `json:"repo"`
Path string `json:"path"`
MaxDepth int `json:"maxDepth"`
}{
Owner: owner,
Repo: repo,
Path: path,
MaxDepth: maxDepth,
}
// Convert to JSON
newInputsJSON, err := json.MarshalIndent(newInputs, "", " ")
if err != nil {
panic(fmt.Errorf("failed to marshal new inputs: %w", err))
}
// Write to the file
err = os.WriteFile(filePath, newInputsJSON, 0644)
if err != nil {
panic(fmt.Errorf("failed to write updated inputs to file: %w", err))
}
}