dati

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

file.go (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 }