/
file_replace_token.go
132 lines (118 loc) · 3.19 KB
/
file_replace_token.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
124
125
126
127
128
129
130
131
132
/**
* Copyright 2021 Adobe. All rights reserved.
* This file is licensed to you under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. You may obtain a copy
* of the License at http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under
* the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
* OF ANY KIND, either express or implied. See the License for the specific language
* governing permissions and limitations under the License.
*/
package util
import (
"bufio"
"fmt"
"io"
"io/ioutil"
"os"
"path/filepath"
"strings"
)
func FileReplaceToken(path string, full_line, add, anycase bool, token_values ...string) error {
// Open input file
in_f, err := os.OpenFile(path, os.O_RDONLY, 0o644)
if err != nil {
return err
}
defer in_f.Close()
// Check it's not a dir
if info, err := in_f.Stat(); err == nil && info.IsDir() {
return fmt.Errorf("Util: Unable to replace token in directory")
}
// Open output file
out_f, err := ioutil.TempFile(filepath.Dir(path), "tmp")
if err != nil {
return err
}
defer out_f.Close()
var tokens []string
var values []string
// Walking through the list of tokens to split them into pairs
// 0 - key, 1 - value
for i, tv := range token_values {
if i%2 == 0 {
if anycase {
tokens = append(tokens, strings.ToLower(tv))
} else {
tokens = append(tokens, tv)
}
} else {
values = append(values, tv)
}
}
replaced := make([]bool, len(values))
// Replace while copying
sc := bufio.NewScanner(in_f)
for sc.Scan() {
line := sc.Text()
comp_line := line
if anycase {
comp_line = strings.ToLower(line)
}
for i, value := range values {
if strings.Contains(comp_line, tokens[i]) {
replaced[i] = true
if full_line {
line = value
break // No need to check the other tokens
} else {
if anycase {
// We're not using RE because it's hard to predict the token
// and escape it to compile the proper regular expression
// so instead we using just regular replace by position of the token
idx := strings.Index(comp_line, tokens[i])
for idx != -1 {
// To support unicode use runes
line = string([]rune(line)[0:idx]) + value + string([]rune(line)[idx+len(tokens[i]):len(line)])
comp_line = strings.ToLower(line)
idx = strings.Index(comp_line, tokens[i])
}
} else {
line = strings.ReplaceAll(line, tokens[i], value)
}
}
}
}
// Probably not the best way to assume there was just \n
if _, err := io.WriteString(out_f, line+"\n"); err != nil {
return err
}
}
if sc.Err() != nil {
return err
}
// Add if was not replaced
if add {
for i, value := range values {
if !replaced[i] {
if _, err := io.WriteString(out_f, value+"\n"); err != nil {
return err
}
}
}
}
// Close the out file
if err := out_f.Close(); err != nil {
return err
}
// Close the input file
if err := in_f.Close(); err != nil {
return err
}
// Replace input file with out file
if err := os.Rename(out_f.Name(), path); err != nil {
return err
}
return nil
}