dati

A Go library/binary to parse & execute data against template langauges.
git clone git://src.gearsix.net/datidati.zip
Log | Files | Refs | Atom | README | LICENSE

file.go (raw) (3008B)


   1 package dati
   2 
   3 /*
   4 Copyright (C) 2023 gearsix <gearsix@tuta.io>
   5 
   6 This program is free software: you can redistribute it and/or modify
   7 it under the terms of the GNU General Public License as published by
   8 the Free Software Foundation, either version 3 of the License, or
   9 at your option) any later version.
  10 
  11 This program is distributed in the hope that it will be useful,
  12 but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14 GNU General Public License for more details.
  15 
  16 You should have received a copy of the GNU General Public License
  17 along with this program.  If not, see <https://www.gnu.org/licenses/>.
  18 */
  19 
  20 import (
  21 	"fmt"
  22 	"os"
  23 	"path/filepath"
  24 	"sort"
  25 	"time"
  26 )
  27 
  28 // SortFileList sorts `filepath` (a list of filepaths) in `order`. `order`
  29 // can be any of the following values: "filename", "filename-asc",
  30 // "filename-desc", "modified", "modified-asc", "modified-desc"; by default
  31 // "filename" and "modified" are in ascending direction, if specified an
  32 // "-asc" suffix will set the direction to ascending and "-desc" will set the
  33 // direction to descending.
  34 // This was originally intended to be used before calling LoadDataFiles on a
  35 // set of "data" files.
  36 func SortFileList(paths []string, order string) (sorted []string, err error) {
  37 	if order == "filename-desc" {
  38 		sorted = sortFileListByName("desc", paths)
  39 	} else if order == "filename-asc" || order == "filename" {
  40 		sorted = sortFileListByName("asc", paths)
  41 	} else if order == "modified-desc" {
  42 		sorted, err = sortFileListByMod("desc", paths)
  43 	} else if order == "modified-asc" || order == "modified" {
  44 		sorted, err = sortFileListByMod("asc", paths)
  45 	} else {
  46 		err = fmt.Errorf("invalid order '%s'", order)
  47 		sorted = paths
  48 	}
  49 	return
  50 }
  51 
  52 func sortFileListByName(direction string, paths []string) []string {
  53 	if direction == "desc" {
  54 		sort.Slice(paths, func(i, j int) bool {
  55 			return filepath.Base(paths[i]) > filepath.Base(paths[j])
  56 		})
  57 	} else {
  58 		sort.Slice(paths, func(i, j int) bool {
  59 			return filepath.Base(paths[i]) < filepath.Base(paths[j])
  60 		})
  61 	}
  62 	return paths
  63 }
  64 
  65 func sortFileListByMod(direction string, paths []string) ([]string, error) {
  66 	stats := make(map[string]os.FileInfo)
  67 	for _, p := range paths {
  68 		stat, err := os.Stat(p)
  69 		if err != nil {
  70 			return paths, err
  71 		}
  72 		stats[p] = stat
  73 	}
  74 
  75 	modtimes := make([]time.Time, 0, len(paths))
  76 	for _, stat := range stats {
  77 		modtimes = append(modtimes, stat.ModTime())
  78 	}
  79 	if direction == "desc" {
  80 		sort.Slice(modtimes, func(i, j int) bool {
  81 			return modtimes[i].After(modtimes[j])
  82 		})
  83 	} else {
  84 		sort.Slice(modtimes, func(i, j int) bool {
  85 			return modtimes[i].Before(modtimes[j])
  86 		})
  87 	}
  88 
  89 	sorted := make([]string, 0)
  90 	for _, t := range modtimes {
  91 		for path, stat := range stats {
  92 			if t == stat.ModTime() {
  93 				sorted = append(sorted, path)
  94 				delete(stats, path)
  95 				break
  96 			}
  97 		}
  98 	}
  99 	if len(sorted) != len(paths) {
 100 		return nil, fmt.Errorf("sorted length invalid")
 101 	}
 102 
 103 	return sorted, nil
 104 }