-
Notifications
You must be signed in to change notification settings - Fork 0
/
template.go
123 lines (108 loc) · 3.23 KB
/
template.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
////////////////////////////////////////////////////////////////////////////
// Program: fsimilar
// Purpose: find/file similar template handling
// Authors: Tong Sun (c) 2017, All rights reserved
////////////////////////////////////////////////////////////////////////////
package main
import (
"fmt"
"os"
"path/filepath"
"strings"
"text/template"
)
////////////////////////////////////////////////////////////////////////////
// Constant and data type/structure definitions
const (
fTmplShellLn = "shell_ln.tmpl"
fTmplShellGlob = "/shell_*.tmpl"
sTmplShellCap = `#!/bin/bash
# -*- bash -*-
# If env var FSIM_MIN is not set, exit
[ -z "$FSIM_MIN" ] && {
echo Env var FSIM_MIN is not set, exiting
exit 0
}
`
)
////////////////////////////////////////////////////////////////////////////
// Global variables definitions
var funcMap = template.FuncMap{
"Quote": Quote,
"ToRel": ToRel,
"Ext": Ext,
}
////////////////////////////////////////////////////////////////////////////
// Function definitions
func outputFinal(files Files) {
if !Opts.Final {
return
}
templateP := filepath.Dir(locateTemplate(fTmplShellLn))
filesG, err := filepath.Glob(templateP + fTmplShellGlob)
abortOn("Glob template", err)
for _, f := range filesG {
verbose(3, "F: '%s' = '%s' / '%s'", f, filepath.Dir(f), filepath.Base(f))
outputSimilars(f, files, false)
}
}
func outputSimilars(tmplFile string, files Files, stdout bool) {
templateV := struct {
Similars Files
Opts OptsT
}{files, Opts}
templateF := locateTemplate(tmplFile)
templateB := filepath.Base(tmplFile)
verbose(3, " Similar items (%s) --\n %#v.", templateF, files)
tmpl, err := template.New(templateB).Funcs(funcMap).
ParseFiles(templateF)
abortOn("Parse template", err)
if stdout {
err = tmpl.Execute(os.Stdout, templateV)
} else {
fo, e := os.OpenFile(Opts.TmpFileP+templateB+".sh",
os.O_CREATE|os.O_APPEND|os.O_RDWR, 0640)
abortOn("Create shell output", e)
defer fo.Close()
err = tmpl.Execute(fo, templateV)
}
warnOn("Executing template", err)
}
func locateTemplate(tmplFile string) string {
var templateF string
if IsExist(tmplFile) {
templateF = tmplFile
} else if tf := Opts.ExecPath + "/" + tmplFile; IsExist(tf) {
templateF = tf
} else if tf := Opts.CfgPath + "/" + tmplFile; IsExist(tf) {
templateF = tf
} else if tf := "/etc/fsimilar/" + tmplFile; IsExist(tf) {
templateF = tf
} else {
abortOn("Locate template",
fmt.Errorf("Template file '%s' not found", tmplFile))
}
return templateF
}
// Quote will quote the file name so as to be savely used in shell.
// It uses single quote to quote the file, thus only need to escape single quote
// by Paul Borman https://play.golang.org/p/VYJ907b8w2
func Quote(s string) string {
return "'" + strings.Join(strings.Split(s, "'"), `'\''`) + "'"
}
// ToRel will convert `p` to relative path to `base`
func ToRel(base, p string) (string, error) {
return filepath.Rel(base, p)
}
// Ext returns the file name extension used by path.
// The extension is the suffix beginning at the final dot
// in the final element of path; it is empty if there is
// no dot.
func Ext(path string) string {
for i := len(path) - 1; i >= 0 && !os.IsPathSeparator(path[i]); i-- {
if path[i] == '.' {
return path[i:]
}
}
return ""
}