machinery-tool 1.16.4 → 1.17.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.git_revision +1 -1
- data/NEWS +10 -0
- data/filters/default_filters.json +21 -20
- data/html/assets/machinery-base.js +4 -0
- data/html/index.html.haml +1 -1
- data/html/partials/changed_managed_files.html.haml +2 -2
- data/html/partials/compare/changed_managed_file_list.html.haml +2 -2
- data/html/partials/compare/changed_managed_files.html.haml +3 -3
- data/html/partials/compare/config_file_list.html.haml +2 -2
- data/html/partials/compare/config_files.html.haml +3 -3
- data/html/partials/compare/packages.html.haml +21 -4
- data/html/partials/compare/repositories.html.haml +10 -7
- data/html/partials/compare/repository_list_apt.html.haml +15 -0
- data/html/partials/compare/repository_list_yum.html.haml +35 -0
- data/html/partials/compare/{repository_list.html.haml → repository_list_zypp.html.haml} +0 -0
- data/html/partials/compare/service_list.html.haml +1 -1
- data/html/partials/compare/services.html.haml +3 -3
- data/html/partials/compare/unmanaged_file_list.html.haml +2 -2
- data/html/partials/compare/unmanaged_files.html.haml +1 -1
- data/html/partials/config_files.html.haml +39 -41
- data/html/partials/repositories.html.haml +1 -23
- data/html/partials/repositories_apt.html.haml +15 -0
- data/html/partials/repositories_yum.html.haml +30 -0
- data/html/partials/repositories_zypp.html.haml +24 -0
- data/html/partials/services.html.haml +2 -2
- data/html/partials/unmanaged_files.html.haml +2 -2
- data/inspect_helpers/dpkg_unmanaged_files.sh +47 -0
- data/inspect_helpers/yum_repositories.py +3 -5
- data/lib/analyze_config_file_diffs_task.rb +11 -1
- data/lib/array.rb +97 -35
- data/lib/autoyast.rb +13 -2
- data/lib/cli.rb +10 -2
- data/lib/config.rb +4 -4
- data/lib/dpkg_database.rb +68 -0
- data/lib/element_filter.rb +2 -0
- data/lib/file_diff.rb +2 -2
- data/lib/file_scope.rb +10 -49
- data/lib/file_validator.rb +10 -4
- data/lib/filter.rb +6 -6
- data/lib/filter_option_parser.rb +1 -1
- data/lib/kiwi_config.rb +13 -10
- data/lib/machinery.rb +2 -0
- data/lib/machinery_helper.rb +1 -1
- data/lib/managed_files_database.rb +200 -0
- data/lib/object.rb +5 -3
- data/lib/remote_system.rb +43 -10
- data/lib/renderer.rb +3 -4
- data/lib/rpm_database.rb +7 -183
- data/lib/scope_file_access_archive.rb +3 -3
- data/lib/scope_file_access_flat.rb +1 -1
- data/lib/server.rb +7 -2
- data/lib/system.rb +50 -22
- data/lib/system_description.rb +3 -3
- data/lib/version.rb +1 -1
- data/lib/workload_mapper.rb +2 -2
- data/machinery-helper/machinery_helper.go +252 -178
- data/machinery-helper/machinery_helper_test.go +121 -121
- data/machinery-helper/mountpoints.go +28 -28
- data/machinery-helper/tar.go +105 -104
- data/machinery-helper/version.go +1 -1
- data/man/generated/machinery.1.gz +0 -0
- data/man/generated/machinery.1.html +19 -8
- data/plugins/changed_managed_files/changed_managed_files_inspector.rb +3 -3
- data/plugins/changed_managed_files/changed_managed_files_model.rb +3 -1
- data/plugins/changed_managed_files/changed_managed_files_renderer.rb +2 -2
- data/plugins/changed_managed_files/schema/system-description-changed-managed-files.schema-v6.json +168 -0
- data/plugins/config_files/config_files_inspector.rb +4 -4
- data/plugins/config_files/config_files_model.rb +3 -1
- data/plugins/config_files/config_files_renderer.rb +2 -2
- data/plugins/config_files/schema/system-description-config-files.schema-v6.json +160 -0
- data/plugins/environment/schema/system-description-environment.schema-v6.json +17 -0
- data/plugins/groups/schema/system-description-groups.schema-v6.json +49 -0
- data/plugins/os/schema/system-description-os.schema-v6.json +21 -0
- data/plugins/packages/packages_inspector.rb +76 -6
- data/plugins/packages/packages_model.rb +31 -12
- data/plugins/packages/packages_renderer.rb +5 -2
- data/plugins/packages/schema/system-description-packages.schema-v6.json +115 -0
- data/plugins/patterns/patterns_inspector.rb +26 -2
- data/plugins/patterns/schema/system-description-patterns.schema-v6.json +58 -0
- data/plugins/repositories/repositories_inspector.rb +41 -14
- data/plugins/repositories/repositories_model.rb +55 -12
- data/plugins/repositories/repositories_renderer.rb +23 -7
- data/plugins/repositories/schema/system-description-repositories.schema-v6.json +165 -0
- data/plugins/services/schema/system-description-services.schema-v6.json +93 -0
- data/plugins/services/services_inspector.rb +88 -22
- data/plugins/services/services_model.rb +9 -15
- data/plugins/services/services_renderer.rb +2 -2
- data/plugins/unmanaged_files/schema/system-description-unmanaged-files.schema-v6.json +162 -0
- data/plugins/unmanaged_files/unmanaged_files_inspector.rb +80 -30
- data/plugins/unmanaged_files/unmanaged_files_model.rb +22 -18
- data/plugins/unmanaged_files/unmanaged_files_renderer.rb +3 -3
- data/plugins/users/schema/system-description-users.schema-v6.json +86 -0
- data/schema/migrations/migrate5to6.rb +101 -0
- data/schema/system-description-global.schema-v6.json +43 -0
- metadata +24 -4
- data/html/assets/landing_page/landing_page.js +0 -10
@@ -18,96 +18,96 @@
|
|
18
18
|
package main
|
19
19
|
|
20
20
|
import (
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
21
|
+
"github.com/nowk/go-fakefileinfo"
|
22
|
+
"os"
|
23
|
+
"reflect"
|
24
|
+
"testing"
|
25
|
+
"time"
|
26
26
|
)
|
27
27
|
|
28
28
|
func doTestParseRpmLine(t *testing.T, line string, expectedFileType string, expectedFileName string, expectedLinkTarget string) {
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
29
|
+
fileType, fileName, linkTarget := parseRpmLine(line)
|
30
|
+
|
31
|
+
if fileType != expectedFileType {
|
32
|
+
t.Errorf("parseRpmLine('%s') file type = '%s', want '%s'", line, fileType, expectedFileType)
|
33
|
+
}
|
34
|
+
if fileName != expectedFileName {
|
35
|
+
t.Errorf("parseRpmLine('%s') file name = '%s', want '%s'", line, fileName, expectedFileName)
|
36
|
+
}
|
37
|
+
if linkTarget != expectedLinkTarget {
|
38
|
+
t.Errorf("parseRpmLine('%s') file type = '%s', want '%s'", line, linkTarget, expectedLinkTarget)
|
39
|
+
}
|
40
40
|
}
|
41
41
|
|
42
42
|
func TestParseRpmLineFile(t *testing.T) {
|
43
|
-
|
43
|
+
line := "-rw-r--r-- 1 root root 18234080 Mar 31 11:40 /usr/lib64/libruby2.0-static.a"
|
44
44
|
|
45
|
-
|
46
|
-
|
47
|
-
|
45
|
+
expectedFileType := "-"
|
46
|
+
expectedFileName := "/usr/lib64/libruby2.0-static.a"
|
47
|
+
expectedLinkTarget := ""
|
48
48
|
|
49
|
-
|
49
|
+
doTestParseRpmLine(t, line, expectedFileType, expectedFileName, expectedLinkTarget)
|
50
50
|
}
|
51
51
|
|
52
52
|
func TestParseRpmLineDir(t *testing.T) {
|
53
|
-
|
53
|
+
line := "drwxr-xr-x 2 root root 0 Mar 31 11:45 /usr/include/ruby-2.0.0/x86_64-linux/ruby"
|
54
54
|
|
55
|
-
|
56
|
-
|
57
|
-
|
55
|
+
expectedFileType := "d"
|
56
|
+
expectedFileName := "/usr/include/ruby-2.0.0/x86_64-linux/ruby"
|
57
|
+
expectedLinkTarget := ""
|
58
58
|
|
59
|
-
|
59
|
+
doTestParseRpmLine(t, line, expectedFileType, expectedFileName, expectedLinkTarget)
|
60
60
|
}
|
61
61
|
|
62
62
|
func TestParseRpmLineLink(t *testing.T) {
|
63
|
-
|
63
|
+
line := "lrwxrwxrwx 1 root root 19 Mar 31 11:45 /usr/lib64/libruby2.0.so -> libruby2.0.so.2.0.0"
|
64
64
|
|
65
|
-
|
66
|
-
|
67
|
-
|
65
|
+
expectedFileType := "l"
|
66
|
+
expectedFileName := "/usr/lib64/libruby2.0.so"
|
67
|
+
expectedLinkTarget := "libruby2.0.so.2.0.0"
|
68
68
|
|
69
|
-
|
69
|
+
doTestParseRpmLine(t, line, expectedFileType, expectedFileName, expectedLinkTarget)
|
70
70
|
}
|
71
71
|
|
72
72
|
func TestParseRpmLineFileSpaces(t *testing.T) {
|
73
|
-
|
73
|
+
line := "-rw-r--r-- 1 root root 61749 Jun 26 01:56 /usr/share/kde4/templates/kipiplugins_photolayoutseditor/data/templates/a4/h/Flipping Tux Black.ple"
|
74
74
|
|
75
|
-
|
76
|
-
|
77
|
-
|
75
|
+
expectedFileType := "-"
|
76
|
+
expectedFileName := "/usr/share/kde4/templates/kipiplugins_photolayoutseditor/data/templates/a4/h/Flipping Tux Black.ple"
|
77
|
+
expectedLinkTarget := ""
|
78
78
|
|
79
|
-
|
79
|
+
doTestParseRpmLine(t, line, expectedFileType, expectedFileName, expectedLinkTarget)
|
80
80
|
}
|
81
81
|
|
82
82
|
func TestAddImplicitlyManagedDirs(t *testing.T) {
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
83
|
+
filesOriginal := map[string]string{
|
84
|
+
"/abc/def/ghf/somefile": "",
|
85
|
+
"/zzz": "/abc/def",
|
86
|
+
}
|
87
|
+
dirsOriginal := map[string]bool{
|
88
|
+
"/abc/def": true,
|
89
|
+
}
|
90
|
+
dirsExpected := map[string]bool{
|
91
|
+
"/abc": false,
|
92
|
+
"/abc/def": true,
|
93
|
+
"/abc/def/ghf": false,
|
94
|
+
"/zzz": false,
|
95
|
+
}
|
96
|
+
|
97
|
+
dirs := dirsOriginal
|
98
|
+
|
99
|
+
addImplicitlyManagedDirs(dirs, filesOriginal)
|
100
|
+
|
101
|
+
if !reflect.DeepEqual(dirs, dirsExpected) {
|
102
|
+
t.Errorf("addImplicitlyManagedDirs('%v') = '%v', want '%v'", dirsOriginal, dirs, dirsExpected)
|
103
|
+
}
|
104
104
|
}
|
105
105
|
|
106
106
|
func TestAssembleJSON(t *testing.T) {
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
107
|
+
unmanagedFilesMap := map[string]string{
|
108
|
+
"name": "/usr/share/go_rulez", "type": "file",
|
109
|
+
}
|
110
|
+
want := `{
|
111
111
|
"extracted": false,
|
112
112
|
"files": {
|
113
113
|
"name": "/usr/share/go_rulez",
|
@@ -115,78 +115,78 @@ func TestAssembleJSON(t *testing.T) {
|
|
115
115
|
}
|
116
116
|
}`
|
117
117
|
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
118
|
+
json := assembleJSON(unmanagedFilesMap)
|
119
|
+
if !reflect.DeepEqual(json, want) {
|
120
|
+
t.Errorf("assembleJSON() = '%v', want '%v'", json, want)
|
121
|
+
}
|
122
122
|
}
|
123
123
|
|
124
124
|
func TestRespectManagedDirsInUnmanagedDirs(t *testing.T) {
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
125
|
+
unmanagedFiles := make(map[string]string)
|
126
|
+
wantUnmanagedFiles := make(map[string]string)
|
127
|
+
|
128
|
+
/*
|
129
|
+
We mock the readDir method and return following directory structure:
|
130
|
+
/
|
131
|
+
/managed_dir/
|
132
|
+
/managed_dir/unmanaged_dir/
|
133
|
+
/managed_dir/unmanaged_dir/managed_dir/
|
134
|
+
*/
|
135
|
+
readDir = func(dir string) ([]os.FileInfo, error) {
|
136
|
+
dirs := make([]os.FileInfo, 0, 1)
|
137
|
+
var fi os.FileInfo
|
138
|
+
switch dir {
|
139
|
+
case "/":
|
140
|
+
fi = fakefileinfo.New("managed_dir", int64(123), os.ModeType, time.Now(), true, nil)
|
141
|
+
case "/managed_dir/":
|
142
|
+
fi = fakefileinfo.New("unmanaged_dir", int64(123), os.ModeType, time.Now(), true, nil)
|
143
|
+
case "/managed_dir/unmanaged_dir/":
|
144
|
+
fi = fakefileinfo.New("managed_dir", int64(123), os.ModeType, time.Now(), true, nil)
|
145
|
+
}
|
146
|
+
dirs = append(dirs, fi)
|
147
|
+
return dirs, nil
|
148
|
+
}
|
149
|
+
|
150
|
+
rpmFiles := make(map[string]string)
|
151
|
+
ignoreList := make(map[string]bool)
|
152
|
+
|
153
|
+
rpmDirs := map[string]bool{
|
154
|
+
"/managed_dir": true,
|
155
|
+
"/managed_dir/unmanaged_dir/managed_dir": true,
|
156
|
+
}
|
157
|
+
|
158
|
+
findUnmanagedFiles("/", rpmFiles, rpmDirs, unmanagedFiles, ignoreList)
|
159
|
+
|
160
|
+
if !reflect.DeepEqual(unmanagedFiles, wantUnmanagedFiles) {
|
161
|
+
t.Errorf("findUnmanagedFiles() = '%v', want '%v'", unmanagedFiles, wantUnmanagedFiles)
|
162
|
+
}
|
163
163
|
}
|
164
164
|
|
165
165
|
func TestHasManagedDirs(t *testing.T) {
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
166
|
+
rpmDirs := map[string]bool{
|
167
|
+
"/managed_dir": true,
|
168
|
+
"/managed_dir/unmanaged_dir/sub_dir/managed_dir": true,
|
169
|
+
}
|
170
170
|
|
171
|
-
|
172
|
-
|
171
|
+
hasDirs := hasManagedDirs("/managed_dir/unmanaged_dir", rpmDirs)
|
172
|
+
want := true
|
173
173
|
|
174
|
-
|
175
|
-
|
176
|
-
|
174
|
+
if hasDirs != want {
|
175
|
+
t.Errorf("hasManagedDirs() = '%v', want '%v'", hasDirs, want)
|
176
|
+
}
|
177
177
|
|
178
178
|
}
|
179
179
|
|
180
180
|
func TestSubdirIsNotAccidentallyConsideredManaged(t *testing.T) {
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
181
|
+
rpmDirs := map[string]bool{
|
182
|
+
"/usr": true,
|
183
|
+
"/usr/foobar": true,
|
184
|
+
}
|
185
185
|
|
186
|
-
|
187
|
-
|
186
|
+
hasDirs := hasManagedDirs("/usr/foo", rpmDirs)
|
187
|
+
want := false
|
188
188
|
|
189
|
-
|
190
|
-
|
191
|
-
|
189
|
+
if hasDirs != want {
|
190
|
+
t.Errorf("hasManagedDirs() = '%v', want '%v'", hasDirs, want)
|
191
|
+
}
|
192
192
|
}
|
@@ -18,9 +18,9 @@
|
|
18
18
|
package main
|
19
19
|
|
20
20
|
import (
|
21
|
-
|
22
|
-
|
23
|
-
|
21
|
+
"io/ioutil"
|
22
|
+
"sort"
|
23
|
+
"strings"
|
24
24
|
)
|
25
25
|
|
26
26
|
// this specifies the path of the process mounts. This needs to be
|
@@ -29,53 +29,53 @@ var ProcMountsPath = "/proc/mounts"
|
|
29
29
|
|
30
30
|
var remoteFileSystems = []string{"autofs", "cifs", "nfs", "nfs4"}
|
31
31
|
var specialFileSystems = []string{"proc", "sysfs", "devtmpfs", "tmpfs", "rpc_pipefs", "fuse.gvfs-fuse-daemon"}
|
32
|
-
var localFileSystems
|
32
|
+
var localFileSystems = []string{"ext2", "ext3", "ext4", "reiserfs", "btrfs", "vfat", "xfs", "jfs"}
|
33
33
|
|
34
34
|
func parseMounts() map[string]string {
|
35
|
-
|
36
|
-
|
35
|
+
mount, _ := ioutil.ReadFile(ProcMountsPath)
|
36
|
+
mounts := make(map[string]string)
|
37
37
|
|
38
|
-
|
38
|
+
lines := strings.Split(string(mount), "\n")
|
39
39
|
|
40
|
-
|
41
|
-
|
40
|
+
for _, line := range lines {
|
41
|
+
elements := strings.Split(line, " ")
|
42
42
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
43
|
+
if len(elements) >= 3 {
|
44
|
+
mounts[elements[1]] = elements[2]
|
45
|
+
}
|
46
|
+
}
|
47
47
|
|
48
|
-
|
48
|
+
return mounts
|
49
49
|
}
|
50
50
|
|
51
|
-
func selectFileSystems(allMounts map[string]string, fileSystems[]string) []string {
|
52
|
-
|
51
|
+
func selectFileSystems(allMounts map[string]string, fileSystems []string) []string {
|
52
|
+
mounts := []string{}
|
53
53
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
54
|
+
for path, fs := range allMounts {
|
55
|
+
for _, specialFs := range fileSystems {
|
56
|
+
if specialFs == fs {
|
57
|
+
mounts = append(mounts, path)
|
58
|
+
}
|
59
|
+
}
|
60
|
+
}
|
61
|
+
sort.Strings(mounts)
|
62
62
|
|
63
|
-
|
63
|
+
return mounts
|
64
64
|
}
|
65
65
|
|
66
66
|
// SpecialMounts returns an array of all special mount paths like
|
67
67
|
// proc or sysfs
|
68
68
|
func SpecialMounts() []string {
|
69
|
-
|
69
|
+
return selectFileSystems(parseMounts(), specialFileSystems)
|
70
70
|
}
|
71
71
|
|
72
72
|
// LocalMounts returns an array of all local mount paths
|
73
73
|
func LocalMounts() []string {
|
74
|
-
|
74
|
+
return selectFileSystems(parseMounts(), localFileSystems)
|
75
75
|
}
|
76
76
|
|
77
77
|
// RemoteMounts returns an array of all remote mount paths
|
78
78
|
// (for example NFS mount points)
|
79
79
|
func RemoteMounts() []string {
|
80
|
-
|
80
|
+
return selectFileSystems(parseMounts(), remoteFileSystems)
|
81
81
|
}
|
data/machinery-helper/tar.go
CHANGED
@@ -18,27 +18,28 @@
|
|
18
18
|
package main
|
19
19
|
|
20
20
|
import (
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
21
|
+
"archive/tar"
|
22
|
+
"bufio"
|
23
|
+
"compress/gzip"
|
24
|
+
"flag"
|
25
|
+
"fmt"
|
26
|
+
"io"
|
27
|
+
"os"
|
28
|
+
"os/exec"
|
29
|
+
"os/user"
|
30
|
+
"path/filepath"
|
31
|
+
"strconv"
|
32
|
+
"strings"
|
33
33
|
)
|
34
34
|
|
35
35
|
type stringArrayFlag []string
|
36
|
+
|
36
37
|
func (i *stringArrayFlag) String() string {
|
37
|
-
|
38
|
+
return "exclude"
|
38
39
|
}
|
39
40
|
func (i *stringArrayFlag) Set(value string) error {
|
40
|
-
|
41
|
-
|
41
|
+
*i = append(*i, value)
|
42
|
+
return nil
|
42
43
|
}
|
43
44
|
|
44
45
|
var excludeList = make(map[string]bool)
|
@@ -46,97 +47,97 @@ var gzipWriter = gzip.NewWriter(os.Stdout)
|
|
46
47
|
var tarWriter = tar.NewWriter(gzipWriter)
|
47
48
|
|
48
49
|
func addPath(path string, info os.FileInfo, err error) error {
|
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
|
-
|
50
|
+
if err != nil {
|
51
|
+
return err
|
52
|
+
}
|
53
|
+
|
54
|
+
if stat, err := os.Lstat(path); err == nil {
|
55
|
+
if _, ok := excludeList[strings.TrimRight(path, "/")]; ok {
|
56
|
+
return nil
|
57
|
+
}
|
58
|
+
|
59
|
+
linkTarget := ""
|
60
|
+
if stat.Mode()&os.ModeSymlink != 0 {
|
61
|
+
if linkTarget, err = os.Readlink(path); err != nil {
|
62
|
+
return err
|
63
|
+
}
|
64
|
+
}
|
65
|
+
header, err := tar.FileInfoHeader(stat, linkTarget)
|
66
|
+
header.Name = strings.TrimLeft(path, "/")
|
67
|
+
if err != nil {
|
68
|
+
return err
|
69
|
+
}
|
70
|
+
|
71
|
+
username, err := user.LookupId(strconv.Itoa(header.Uid))
|
72
|
+
if err != nil {
|
73
|
+
return err
|
74
|
+
}
|
75
|
+
header.Uname = username.Username
|
76
|
+
|
77
|
+
groupname, err := exec.Command("bash", "-c",
|
78
|
+
fmt.Sprintf("getent group %d | cut -d: -f1", header.Gid)).Output()
|
79
|
+
if err != nil {
|
80
|
+
return err
|
81
|
+
}
|
82
|
+
header.Gname = strings.TrimSpace(string(groupname))
|
83
|
+
|
84
|
+
if err := tarWriter.WriteHeader(header); err != nil {
|
85
|
+
return err
|
86
|
+
}
|
87
|
+
|
88
|
+
if stat.Mode().IsRegular() {
|
89
|
+
file, err := os.Open(path)
|
90
|
+
if err != nil {
|
91
|
+
return err
|
92
|
+
}
|
93
|
+
defer file.Close()
|
94
|
+
|
95
|
+
if _, err := io.Copy(tarWriter, file); err != nil {
|
96
|
+
return err
|
97
|
+
}
|
98
|
+
}
|
99
|
+
}
|
100
|
+
return nil
|
100
101
|
}
|
101
102
|
|
102
103
|
// Tar represents the "tar" command for the machinery-helper
|
103
104
|
func Tar(args []string) {
|
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
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
105
|
+
var files []string
|
106
|
+
tarCommand := flag.NewFlagSet("tar", flag.ExitOnError)
|
107
|
+
tarCommand.Bool("create", true, "Create an tar archive")
|
108
|
+
tarCommand.Bool("gzip", true, "Compress archive using GZip")
|
109
|
+
tarCommand.Bool("null", true, "Read null-terminated names")
|
110
|
+
filesFromFlag := tarCommand.String("files-from", "", "Where to take the file list from")
|
111
|
+
|
112
|
+
var excludeFlag stringArrayFlag
|
113
|
+
tarCommand.Var(&excludeFlag, "exclude", "Read null-terminated names")
|
114
|
+
|
115
|
+
tarCommand.Parse(args)
|
116
|
+
for _, path := range excludeFlag {
|
117
|
+
excludeList[path] = true
|
118
|
+
}
|
119
|
+
|
120
|
+
if *filesFromFlag == "-" {
|
121
|
+
reader := bufio.NewReader(os.Stdin)
|
122
|
+
|
123
|
+
for {
|
124
|
+
s, err := reader.ReadString('\x00')
|
125
|
+
|
126
|
+
files = append(files, strings.TrimRight(strings.TrimSpace(s), "\x00"))
|
127
|
+
|
128
|
+
if err == io.EOF {
|
129
|
+
break
|
130
|
+
}
|
131
|
+
}
|
132
|
+
} else {
|
133
|
+
files = tarCommand.Args()
|
134
|
+
}
|
135
|
+
|
136
|
+
for i := range files {
|
137
|
+
if err := filepath.Walk(files[i], addPath); err != nil {
|
138
|
+
fmt.Fprintln(os.Stderr, "Error:", err)
|
139
|
+
}
|
140
|
+
}
|
141
|
+
defer gzipWriter.Close()
|
142
|
+
defer tarWriter.Close()
|
142
143
|
}
|