Skip to content

Instantly share code, notes, and snippets.

@aclisp
Last active May 29, 2017 09:50
Show Gist options
  • Save aclisp/e2c67622a9bdf6aaabf6d5c99ed1cca5 to your computer and use it in GitHub Desktop.
Save aclisp/e2c67622a9bdf6aaabf6d5c99ed1cca5 to your computer and use it in GitHub Desktop.
A golang app that list svn dirs...
package main
import (
"encoding/json"
"encoding/xml"
"fmt"
"net/http"
"strings"
)
const (
svnServerAddr = "https://svn.xxxxxx.com"
svnUsername = "xxxxxx"
svnPassword = "xxxxxx"
)
var (
client = &http.Client{}
)
// HTMLList is the container of svn returned items.
type HTMLList struct {
Items []string `xml:"body>ul>li>a"`
}
// DirList is the container of items for API
type DirList struct {
Path string
Items []string
}
// FileAttr is the container of file attributes for API
type FileAttr struct {
Path string
Exist bool
}
func getSVNContent(svnURL string) (*HTMLList, error) {
req, err := http.NewRequest("GET", svnURL, nil)
if err != nil {
return nil, fmt.Errorf("Couldn't create new http request: %v", err)
}
req.SetBasicAuth(svnUsername, svnPassword)
resp, err := client.Do(req)
if err != nil {
return nil, fmt.Errorf("Couldn't get svn path: %v", err)
}
defer resp.Body.Close()
// Parse html returned from svn.
decoder := xml.NewDecoder(resp.Body)
items := &HTMLList{}
err = decoder.Decode(items)
if err != nil {
return nil, fmt.Errorf("Couldn't parse svn resp body: %v", err)
}
return items, nil
}
func listDir(svnURL string) (string, error) {
items, err := getSVNContent(svnURL)
if err != nil {
return "", fmt.Errorf("Couldn't get svn content: %v", err)
}
// Filter non-dir items.
dirs := DirList{
Path: svnURL,
}
for _, v := range items.Items {
if len(v) > 0 && v[0] != '.' && v[len(v)-1:] == "/" {
v = v[:len(v)-1] // Remove the last '/'
dirs.Items = append(dirs.Items, v)
}
}
// Encode result.
result, err := json.MarshalIndent(dirs, "", " ")
if err != nil {
return "", fmt.Errorf("Couldn't marshal result: %v", err)
}
return string(result), nil
}
func queryFile(svnURL string) (string, error) {
i := strings.LastIndex(svnURL, "/")
d := svnURL[:i+1]
f := svnURL[i+1:]
items, err := getSVNContent(d)
if err != nil {
return "", fmt.Errorf("Couldn't get svn content: %v", err)
}
attr := FileAttr{
Path: svnURL,
}
for _, v := range items.Items {
if strings.EqualFold(f, v) {
attr.Exist = true
attr.Path = d + v
break
}
}
result, err := json.MarshalIndent(attr, "", " ")
if err != nil {
return "", fmt.Errorf("Couldn't marshal result: %v", err)
}
return string(result), nil
}
func handler(w http.ResponseWriter, r *http.Request) {
// allow cross domain AJAX requests
w.Header().Set("Access-Control-Allow-Origin", "*")
w.Header().Set("Content-Type", "application/json;charset=UTF-8")
svnPath := r.URL.Path
var result string
var err error
if svnPath[len(svnPath)-1:] == "/" {
result, err = listDir(svnServerAddr + svnPath)
} else {
result, err = queryFile(svnServerAddr + svnPath)
}
if err != nil {
http.Error(w, fmt.Sprintf("ERROR: %v", err), http.StatusInternalServerError)
return
}
fmt.Fprintf(w, "%s\n", result)
}
func main() {
http.HandleFunc("/", handler)
http.ListenAndServe(":8070", nil)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment