github.com/hattya/nazuna@v0.7.1-0.20240331055452-55e14c275c1c/util.go (about)

     1  //
     2  // nazuna :: util.go
     3  //
     4  //   Copyright (c) 2013-2022 Akinori Hattori <hattya@gmail.com>
     5  //
     6  //   SPDX-License-Identifier: MIT
     7  //
     8  
     9  package nazuna
    10  
    11  import (
    12  	"encoding/json"
    13  	"fmt"
    14  	"io"
    15  	"net/http"
    16  	"os"
    17  	"path/filepath"
    18  	"reflect"
    19  	"sort"
    20  	"strings"
    21  	"unicode/utf8"
    22  )
    23  
    24  func IsDir(path string) bool {
    25  	fi, err := os.Stat(path)
    26  	return err == nil && fi.IsDir()
    27  }
    28  
    29  func IsEmptyDir(path string) bool {
    30  	f, err := os.Open(path)
    31  	if err != nil {
    32  		return true
    33  	}
    34  	defer f.Close()
    35  	_, err = f.Readdir(1)
    36  	return err == io.EOF
    37  }
    38  
    39  func SplitPath(path string) (string, string) {
    40  	dir, name := filepath.Split(path)
    41  	dir = strings.TrimRightFunc(dir, func(r rune) bool {
    42  		return r < utf8.RuneSelf && os.IsPathSeparator(uint8(r))
    43  	})
    44  	return dir, name
    45  }
    46  
    47  func sortKeys(i interface{}) []string {
    48  	v := reflect.Indirect(reflect.ValueOf(i))
    49  	if v.Kind() != reflect.Map {
    50  		return nil
    51  	}
    52  	keys := v.MapKeys()
    53  	if len(keys) == 0 || keys[0].Kind() != reflect.String {
    54  		return nil
    55  	}
    56  	list := make(sort.StringSlice, len(keys))
    57  	for i, k := range keys {
    58  		list[i] = k.String()
    59  	}
    60  	list.Sort()
    61  	return list
    62  }
    63  
    64  func marshal(repo *Repository, path string, v interface{}) error {
    65  	rel, err := filepath.Rel(repo.root, path)
    66  	if err != nil {
    67  		return err
    68  	}
    69  	data, err := json.MarshalIndent(v, "", "  ")
    70  	if err != nil {
    71  		return fmt.Errorf("%v: %v", rel, err)
    72  	}
    73  	if err := os.WriteFile(path, append(data, '\n'), 0o666); err != nil {
    74  		return fmt.Errorf("cannot write '%v'", rel)
    75  	}
    76  	return nil
    77  }
    78  
    79  func unmarshal(repo *Repository, path string, v interface{}) error {
    80  	rel, err := filepath.Rel(repo.root, path)
    81  	if err != nil {
    82  		return err
    83  	}
    84  	if _, err := os.Stat(path); err == nil {
    85  		data, err := os.ReadFile(path)
    86  		if err != nil {
    87  			return fmt.Errorf("cannot read '%v'", rel)
    88  		}
    89  		if err := json.Unmarshal(data, v); err != nil {
    90  			return fmt.Errorf("%v: %v", rel, err)
    91  		}
    92  	}
    93  	return nil
    94  }
    95  
    96  func httpGet(uri string) ([]byte, error) {
    97  	resp, err := http.Get(uri)
    98  	if err != nil {
    99  		return nil, err
   100  	}
   101  	defer resp.Body.Close()
   102  	if resp.StatusCode != 200 {
   103  		return nil, fmt.Errorf("%v: %v", uri, resp.Status)
   104  	}
   105  	data, err := io.ReadAll(resp.Body)
   106  	if err != nil {
   107  		return nil, err
   108  	}
   109  	return data, nil
   110  }