github.com/titpetric/pendulum@v0.1.180207-1512.0.20180514135826-1f399445df57/cmd/pendulum/api.go (about)

     1  package main
     2  
     3  import (
     4  	"fmt"
     5  	"os"
     6  	"path"
     7  	"sort"
     8  	"time"
     9  
    10  	"encoding/json"
    11  	"io/ioutil"
    12  	"net/http"
    13  )
    14  
    15  type Location struct {
    16  	Type         string `json:"type"`
    17  	Path         string `json:"path"`
    18  	Name         string `json:"name"`
    19  	Dir          string `json:"dir"`
    20  	LastModified string `json:"last_modified"`
    21  }
    22  
    23  type ListResponse struct {
    24  	Folder string     `json:"folder"`
    25  	Files  []Location `json:"files"`
    26  }
    27  
    28  type ByFolderAndName []Location
    29  
    30  func (a ByFolderAndName) Len() int {
    31  	return len(a)
    32  }
    33  
    34  func (a ByFolderAndName) Swap(i, j int) {
    35  	a[i], a[j] = a[j], a[i]
    36  }
    37  
    38  func (a ByFolderAndName) Less(i, j int) bool {
    39  	if a[i].Type != a[j].Type {
    40  		if a[i].Type == "dir" {
    41  			return true
    42  		}
    43  		return false
    44  	}
    45  	return a[i].Name < a[j].Name
    46  }
    47  
    48  type ReadResponse struct {
    49  	Location
    50  	Contents string `json:"contents"`
    51  }
    52  
    53  type StoreResponse struct {
    54  	Status string `json:"status"`
    55  	Log    string `json:"log"`
    56  }
    57  
    58  type API struct {
    59  	Path     string
    60  	Assets   http.HandlerFunc
    61  	Contents http.HandlerFunc
    62  }
    63  
    64  func (api *API) List(locationPath string) ([]Location, error) {
    65  	response := []Location{}
    66  	fullPath := path.Join(api.Path, locationPath)
    67  	info, err := os.Stat(fullPath)
    68  	if err != nil {
    69  		return response, err
    70  	}
    71  	if !info.IsDir() {
    72  		return response, fmt.Errorf("Path doesn't exist: %s", locationPath)
    73  	}
    74  	files, _ := ioutil.ReadDir(fullPath)
    75  	for _, f := range files {
    76  		name := f.Name()
    77  		if name[0:1] == "." {
    78  			continue
    79  		}
    80  		location := Location{
    81  			Type:         "file",
    82  			Path:         path.Join(locationPath, name),
    83  			Name:         name,
    84  			Dir:          locationPath,
    85  			LastModified: f.ModTime().Format(time.UnixDate),
    86  		}
    87  		if !f.Mode().IsRegular() {
    88  			location.Type = "dir"
    89  			location.Path += "/"
    90  		}
    91  		response = append(response, location)
    92  	}
    93  	sort.Sort(ByFolderAndName(response))
    94  	return response, nil
    95  }
    96  
    97  func (api *API) Read(filePath string) (ReadResponse, error) {
    98  	response := ReadResponse{
    99  		Location: Location{
   100  			Type:         "file",
   101  			Path:         filePath,
   102  			Name:         path.Base(filePath),
   103  			Dir:          path.Dir(filePath),
   104  			LastModified: time.Now().Format(time.UnixDate),
   105  		},
   106  	}
   107  	fullPath := path.Join(api.Path, filePath)
   108  	info, err := os.Stat(fullPath)
   109  	if err != nil {
   110  		if os.IsNotExist(err) {
   111  			return response, nil
   112  		}
   113  		return response, err
   114  	}
   115  	if !info.Mode().IsRegular() {
   116  		return response, fmt.Errorf("Path is not a file: %s", filePath)
   117  	}
   118  	file, err := ioutil.ReadFile(fullPath)
   119  	if err != nil {
   120  		return response, err
   121  	}
   122  	response.LastModified = info.ModTime().Format(time.UnixDate)
   123  	response.Contents = string(file)
   124  	return response, nil
   125  }
   126  
   127  func (api *API) Store(filePath, contents string) (StoreResponse, error) {
   128  	response := StoreResponse{
   129  		Status: "OK",
   130  	}
   131  	fullPath := path.Join(api.Path, filePath)
   132  	err := ioutil.WriteFile(fullPath, []byte(contents), 0644)
   133  	if err != nil {
   134  		return response, err
   135  	}
   136  	git := Git{
   137  		Filename: fullPath,
   138  	}
   139  	response.Log, err = git.Commit()
   140  	return response, err
   141  }
   142  
   143  func (api *API) Error(err error) interface{} {
   144  	response := struct {
   145  		Error struct {
   146  			Message string `json:"message"`
   147  		} `json:"error"`
   148  	}{}
   149  	response.Error.Message = fmt.Sprintf("%s", err)
   150  	return response
   151  }
   152  
   153  func (api *API) ServeJSON(w http.ResponseWriter, r *http.Request, response interface{}) {
   154  	json, err := json.MarshalIndent(response, "", "  ")
   155  	if err != nil {
   156  		http.Error(w, err.Error(), http.StatusInternalServerError)
   157  		return
   158  	}
   159  
   160  	w.Header().Set("Content-Type", "application/json")
   161  	w.Write(json)
   162  }