machinery-tool 1.10.0 → 1.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0248c07e10c874fd1b90d77d42b98e27ce2f5aa2
4
- data.tar.gz: cf74177f9c3e73febd1137c9e9c4a028a1dc6676
3
+ metadata.gz: b96848d4a8e199cd5c03e8b7af1dac6b12ddd360
4
+ data.tar.gz: 8efb2f29f2ba6b12ea9a0c5bd428f6fd98ad8bcd
5
5
  SHA512:
6
- metadata.gz: bd8586da9a47fbff50c9b9c4e59ed2fbd6b31e4cd8cdf17c3abc56d2b10a91c0ffa205cae7619255620a27cd852a400e197482707b5189cf1da7e8668f28be3c
7
- data.tar.gz: 94af88fa5b75517220f9a5383d8306da20a729ccc0c93c09b64e28042577806e98b7d839aedc26e261fdb0da10ee085641fef636980f6d8a2f346419d67c317b
6
+ metadata.gz: e357dd4675da951830ec52d8020d8d10aa4b7a08f0747e15209f22c358cd1b2fc35df58d56fd368c4182713c7d826da37872ea0d699d5693c1a55c51fe0f6922
7
+ data.tar.gz: 6c9a0664f73ea4f84ac3fb37abc6dadaa68ac17835e527d6fd9b84ea6e1da82477519231854bee6aff5bd5fed4db7fb9f58709a7fcaf3ed407ea6bf73758a980
data/NEWS CHANGED
@@ -1,6 +1,12 @@
1
1
  # Machinery Release Notes
2
2
 
3
3
 
4
+ ## Version 1.11.0 - Mon Jul 20 13:51:09 CEST 2015 - thardeck@suse.de
5
+
6
+ * Fix comparison output for scopes that were excluded (gh#SUSE/machinery#1029)
7
+ * Fix connection errors caused by reading from stdin (gh#SUSE/machinery#1050)
8
+ * Differences between unmanaged files can be viewed in the HTML comparison
9
+
4
10
  ## Version 1.10.0 - Thu Jul 09 16:26:35 CEST 2015 - thardeck@suse.de
5
11
 
6
12
  * Data which hasn't changed is not shown in the comparison HTML view by default
@@ -4,8 +4,27 @@ angular.module("machinery-compare")
4
4
  .config(function($locationProvider) {
5
5
  $locationProvider.html5Mode({enabled: true, requireBase: false});
6
6
  })
7
- .controller("compareController", function($scope) {
8
- $scope.diff = getDiff();
7
+ .controller("compareController", function($scope, $http, $timeout, $anchorScroll) {
8
+ $http.get("/compare/" + $("body").data("description-a") + "/" + $("body").data("description-b") + ".json").then(function(result) {
9
+ // Scroll to desired scope when rendering is done
10
+ $timeout(function () {
11
+ $anchorScroll();
12
+ }, 0);
13
+ $scope.diff = result.data;
14
+
15
+ // Determine which unmanaged files can be diffed
16
+ if($scope.diff.unmanaged_files !== undefined &&
17
+ $scope.diff.unmanaged_files.only_in1 !== undefined &&
18
+ $scope.diff.unmanaged_files.only_in2 !== undefined) {
19
+ var unmanagedFilesIn1 = $.map($scope.diff.unmanaged_files.only_in1.files, function(file){
20
+ return file.type == 'file' ? file.name : null;
21
+ });
22
+ var unmanagedFilesIn2 = $.map($scope.diff.unmanaged_files.only_in2.files, function(file){
23
+ return file.type == 'file' ? file.name : null;
24
+ });
25
+ $scope.diffableUnmanagedFiles = $(unmanagedFilesIn1).filter(unmanagedFilesIn2);
26
+ }
27
+ });
9
28
  })
10
29
  .directive("onlyInA", function() {
11
30
  return {
@@ -46,33 +65,35 @@ angular.module("machinery-compare")
46
65
  .directive("changedPackages", function() {
47
66
  return {
48
67
  restrict: "E",
49
- scope: {
50
- object: "=object"
51
- },
52
68
  link: function(scope, element, attrs) {
53
- var elements = [];
69
+ scope.$watch("diff", function(){
70
+ if(scope.diff == undefined || scope.diff.packages == undefined) {
71
+ return;
72
+ }
73
+ var elements = [];
54
74
 
55
- angular.forEach(scope.object, function(value) {
56
- var changes = [];
57
- var relevant_attributes = ["version", "vendor", "arch"];
75
+ angular.forEach(scope.diff.packages.changed, function(value) {
76
+ var changes = [];
77
+ var relevant_attributes = ["version", "vendor", "arch"];
58
78
 
59
- if(value[0].version == value[1].version) {
60
- relevant_attributes.push("release");
61
79
  if(value[0].version == value[1].version) {
62
- relevant_attributes.push("checksum");
80
+ relevant_attributes.push("release");
81
+ if(value[0].version == value[1].version) {
82
+ relevant_attributes.push("checksum");
83
+ }
63
84
  }
64
- }
65
85
 
66
- angular.forEach(relevant_attributes, function(attribute) {
67
- if(value[0][attribute] != value[1][attribute]) {
68
- changes.push(attribute + ": " + value[0][attribute] + " ↔ " + value[1][attribute]);
69
- }
86
+ angular.forEach(relevant_attributes, function(attribute) {
87
+ if(value[0][attribute] != value[1][attribute]) {
88
+ changes.push(attribute + ": " + value[0][attribute] + " ↔ " + value[1][attribute]);
89
+ }
90
+ });
91
+
92
+ elements.push(value[0].name + " (" + changes.join(", ") + ")");
70
93
  });
71
94
 
72
- elements.push(value[0].name + " (" + changes.join(", ") + ")");
95
+ scope.changed_elements = elements;
73
96
  });
74
-
75
- scope.changed_elements = elements;
76
97
  },
77
98
  templateUrl: "scope_packages_changed_partial"
78
99
  };
@@ -1,7 +1,4 @@
1
1
  $(document).ready(function () {
2
- // Render the diff
3
- var diff = getDiff();
4
-
5
2
  // Align content below floating menu
6
3
  var header_height = $("#nav-bar").height() + 20;
7
4
  $("#content_container").css("margin-top", header_height);
@@ -31,6 +28,10 @@ $(document).ready(function () {
31
28
  }
32
29
  });
33
30
 
31
+ $(".dismiss").click(function(){
32
+ $(this).closest(".scope").hide();
33
+ });
34
+
34
35
  // Hook up the toggle links
35
36
  $(".toggle").click(function(){
36
37
  $(this).closest(".scope").find(".scope_content").collapse("toggle");
@@ -55,8 +56,11 @@ $(document).ready(function () {
55
56
  $(".show-common-elements").click(function(){
56
57
  $scope = $(this).closest(".scope");
57
58
  $scope.find(".scope_common_content").collapse("show");
58
- $(this).hide();
59
+ $scope.find(".scope_content").find(".show-common-elements").hide();
59
60
  $scope.find(".hide-common-elements").show();
61
+ if ($(this).attr("href")){
62
+ $('html,body').animate({scrollTop: $($(this).attr("href")).offset().top}, 'slow');
63
+ }
60
64
  return false;
61
65
  });
62
66
 
@@ -67,4 +71,34 @@ $(document).ready(function () {
67
71
  $scope.find(".show-common-elements").show();
68
72
  return false;
69
73
  });
74
+
75
+ // Unmanaged files diffs
76
+ $("#diff-unmanaged-files-file").change(function(){
77
+ $("#diff-unmanaged-files-content").hide();
78
+ $("#diff-unmanaged-files-error").hide();
79
+ $("#diff-unmanaged-files-spinner").show();
80
+ });
81
+
82
+ var description1 = $("body").data("description-a");
83
+ var description2 = $("body").data("description-b");
84
+ var url = "/compare/" + description1 + "/" + description2 + "/files/unmanaged_files" + $(this).val();
85
+ $.get(url, function(res) {
86
+ $("#diff-unmanaged-files-spinner").hide();
87
+ if(res.length === 0) {
88
+ $("#diff-unmanaged-files-error").html("Files are equal.").show();
89
+ } else {
90
+ $("#diff-unmanaged-files-diff").html(res);
91
+ $("#diff-unmanaged-files-content").show();
92
+ }
93
+ }, "text").
94
+ error(function(res) {
95
+ $("#diff-unmanaged-files-spinner").hide();
96
+ if(res.readyState == 0) {
97
+ $("#diff-unmanaged-files-error").html("Could not download file content. Is the web server still running?").show();
98
+ } else if(res.status == 406) {
99
+ $("#diff-unmanaged-files-error").html("Can't generate diff, the files are binary.").show();
100
+ } else {
101
+ $("#diff-unmanaged-files-error").html("There was an unknown error downloading the file.").show();
102
+ }
103
+ });
70
104
  });
Binary file
@@ -18,6 +18,10 @@ body {
18
18
  text-decoration: none;
19
19
  }
20
20
 
21
+ .scope{
22
+ border-spacing: 5px;
23
+ }
24
+
21
25
  a.scope_anchor,
22
26
  a.both_anchor {
23
27
  display: block;
@@ -190,3 +194,37 @@ h1 {
190
194
  min-height: 450px;
191
195
  font-family: monospace;
192
196
  }
197
+
198
+ #diff-unmanaged-files.modal .modal-body {
199
+ margin: 0 0.5em;
200
+ font-family: monospace;
201
+ }
202
+
203
+ #diff-unmanaged-files-diff {
204
+ background-color: #EEEEEE;
205
+ }
206
+
207
+ #diff-unmanaged-files-diff .diff ul {
208
+ background-color: #EEEEEE;
209
+ border: 1px solid gray;
210
+ padding: 4px;
211
+ }
212
+
213
+ #diff-unmanaged-files-file {
214
+ margin-bottom: 1em;
215
+ }
216
+
217
+ .well .dismiss{
218
+ margin: -14px;
219
+ }
220
+
221
+ .dismiss {
222
+ float: right;
223
+ width: 24px;
224
+ height: 24px;
225
+ background: url("cross.png");
226
+ cursor: pointer;
227
+ background-color: white;
228
+ border-radius: 50%;
229
+ }
230
+
@@ -1,19 +1,32 @@
1
1
  !!!
2
- - description_a = diff[:meta][:description_a]
3
- - description_b = diff[:meta][:description_b]
4
2
  %html{"ng-app" => "machinery-compare"}
5
3
  %head
6
4
  %title
7
5
  Machinery System Description Comparison
8
6
  %meta{:charset => 'utf-8'}/
9
7
  %meta{:name => "viewport", :content => "width=device-width, initial-scale=1"}
10
- %link{:href => "assets/machinery-base.css", :rel => "stylesheet", :type => "text/css"}/
11
- %link{:href => "assets/machinery.css", :rel => "stylesheet", :type => "text/css"}/
12
- %script{:src => "assets/angular.min.js"}
13
- %script{:src => "assets/compare/machinery-compare.js"}
14
- %script{:src => "assets/jquery-2.1.1.min.js"}
15
- %script{:src => "assets/transition.js"}
16
- %script{:src => "assets/collapse.js"}
8
+ %link{:href => "/assets/machinery-base.css", :rel => "stylesheet", :type => "text/css"}/
9
+ %link{:href => "/assets/machinery.css", :rel => "stylesheet", :type => "text/css"}/
10
+ %script{:src => "/assets/angular.min.js"}
11
+ %script{:src => "/assets/compare/machinery-compare.js"}
12
+ %script{:src => "/assets/jquery-2.1.1.min.js"}
13
+ %script{:src => "/assets/transition.js"}
14
+ %script{:src => "/assets/collapse.js"}
15
+ %script{:src => "/assets/modal.js"}
16
+
17
+ %style
18
+ = Diffy::CSS
19
+
20
+ %script#alert{:type => "text/ng-template"}
21
+ #alert_container.scope{"ng-show" => "diff.meta.uninspected"}
22
+ .row
23
+ .col-xs-10.col-xs-offset-1
24
+ .well
25
+ %span.text-right.dismiss{:title => "Collapse/Expand"}
26
+ %p{"ng-show" => "diff.meta.uninspected[diff.meta.description_a].length"}
27
+ Couldn't compare <strong>'{{diff.meta.uninspected[diff.meta.description_a].join(", ")}}'</strong> because they are not present in description <strong>'{{diff.meta.description_a}}'</strong>
28
+ %p{"ng-show" => "diff.meta.uninspected[diff.meta.description_b].length"}
29
+ Couldn't compare <strong>'{{diff.meta.uninspected[diff.meta.description_b].join(", ")}}'</strong> because they are not present in description <strong>'{{diff.meta.description_b}}'</strong>
17
30
 
18
31
  %script#scope_os_partial{:type => "text/ng-template"}
19
32
  %table.table.table-striped.table-condensed
@@ -33,7 +46,7 @@
33
46
  .row
34
47
  .col-xs-1
35
48
  %a{:href => "#os"}
36
- %img.scope_logo_big{:src => "assets/logo-os.png", :class=>"over", :"data-toggle"=>"popover", :title=>"Operating System", :"data-content"=>"#{scope_help('os')}"}/
49
+ %img.scope_logo_big{:src => "/assets/logo-os.png", :class=>"over", :"data-toggle"=>"popover", :title=>"Operating System", :"data-content"=>"#{scope_help('os')}"}/
37
50
  %span.toggle{:title => "Collapse/Expand"}
38
51
  .col-xs-11
39
52
  %h2
@@ -87,7 +100,7 @@
87
100
  .row
88
101
  .col-xs-1
89
102
  %a{:href => "#packages"}
90
- %img.scope_logo_big{:src => "assets/logo-packages.png", :class=>"over", :"data-toggle"=>"popover", :title=>"Packages", :"data-content"=>"#{scope_help('packages')}"}/
103
+ %img.scope_logo_big{:src => "/assets/logo-packages.png", :class=>"over", :"data-toggle"=>"popover", :title=>"Packages", :"data-content"=>"#{scope_help('packages')}"}/
91
104
  %span.toggle{:title => "Collapse/Expand"}
92
105
  .col-xs-11
93
106
  %h2
@@ -102,7 +115,7 @@
102
115
  Changed
103
116
  = ": {{diff.packages.changed.length}} packages"
104
117
  %span.summary-part{"ng-show" => "diff.packages.common"}
105
- %a{href: "#packages_both"}
118
+ %a{:class=>"show-common-elements", href: "#packages_both"}
106
119
  both
107
120
  = ": {{diff.packages.common.length}} packages"
108
121
  .row.scope_content.collapse.in
@@ -120,7 +133,7 @@
120
133
  .col-xs-1
121
134
  .col-xs-11.table_container
122
135
  %changed
123
- %changed_packages{:object => "diff.packages.changed"}
136
+ %changed_packages
124
137
  %a.both_anchor{id: "packages_both"}
125
138
  .row
126
139
  .col-xs-1
@@ -154,7 +167,7 @@
154
167
  .row
155
168
  .col-xs-1
156
169
  %a{:href => "#patterns"}
157
- %img.scope_logo_big{:src => "assets/logo-patterns.png", :class=>"over", :"data-toggle"=>"popover", :title=>"Patterns", :"data-content"=>"#{scope_help('patterns')}"}/
170
+ %img.scope_logo_big{:src => "/assets/logo-patterns.png", :class=>"over", :"data-toggle"=>"popover", :title=>"Patterns", :"data-content"=>"#{scope_help('patterns')}"}/
158
171
  %span.toggle{:title => "Collapse/Expand"}
159
172
  .col-xs-11
160
173
  %h2
@@ -165,7 +178,7 @@
165
178
  %span.summary-part{"ng-show" => "diff.patterns.only_in2"}
166
179
  {{diff.meta.description_b}}: {{diff.patterns.only_in2.length}} patterns
167
180
  %span.summary-part{"ng-show" => "diff.patterns.common"}
168
- %a{href: "#patterns_both"}
181
+ %a{:class=>"show-common-elements", href: "#patterns_both"}
169
182
  both
170
183
  = ": {{diff.patterns.common.length}} patterns"
171
184
  .row.scope_content.collapse.in
@@ -216,7 +229,7 @@
216
229
  .row
217
230
  .col-xs-1
218
231
  %a{:href => "#users"}
219
- %img.scope_logo_big{:src => "assets/logo-users.png", :class=>"over", :"data-toggle"=>"popover", :title=>"Users", :"data-content"=>"#{scope_help('users')}"}/
232
+ %img.scope_logo_big{:src => "/assets/logo-users.png", :class=>"over", :"data-toggle"=>"popover", :title=>"Users", :"data-content"=>"#{scope_help('users')}"}/
220
233
  %span.toggle{:title => "Collapse/Expand"}
221
234
  .col-xs-11
222
235
  %h2
@@ -227,7 +240,7 @@
227
240
  %span.summary-part{"ng-show" => "diff.users.only_in2"}
228
241
  {{diff.meta.description_b}}: {{diff.users.only_in2.length}} users
229
242
  %span.summary-part{"ng-show" => "diff.users.common"}
230
- %a{href: "#users_both"}
243
+ %a{:class=>"show-common-elements", href: "#users_both"}
231
244
  both
232
245
  = ": {{diff.users.common.length}} users"
233
246
  .row.scope_content.collapse.in
@@ -272,7 +285,7 @@
272
285
  .row
273
286
  .col-xs-1
274
287
  %a{:href => "#unmanaged_files"}
275
- %img.scope_logo_big{:src => "assets/logo-unmanaged-files.png", :class=>"over", :"data-toggle"=>"popover", :title=>"Unmanaged Files", :"data-content"=>"#{scope_help('unmanaged_files')}"}/
288
+ %img.scope_logo_big{:src => "/assets/logo-unmanaged-files.png", :class=>"over", :"data-toggle"=>"popover", :title=>"Unmanaged Files", :"data-content"=>"#{scope_help('unmanaged_files')}"}/
276
289
  %span.toggle{:title => "Collapse/Expand"}
277
290
  .col-xs-11
278
291
  %h2
@@ -283,11 +296,14 @@
283
296
  %span.summary-part{"ng-show" => "diff.unmanaged_files.only_in2"}
284
297
  {{diff.meta.description_b}}: {{diff.unmanaged_files.only_in2.files.length || 0}} files
285
298
  %span.summary-part{"ng-show" => "diff.unmanaged_files.common"}
286
- %a{href: "#unmanaged_files_both"}
299
+ %a{:class=>"show-common-elements", href: "#unmanaged_files_both"}
287
300
  both
288
301
  = ": {{diff.unmanaged_files.common.files.length}} files"
302
+ %span.summary-part{"ng-show" => "diffableUnmanagedFiles.length"}
303
+ %a#diff-unmanaged-files{"data-toggle" => "modal", "data-target" => "#diff-unmanaged-files"}
304
+ Diff files
289
305
  .row.scope_content.collapse.in
290
- .row
306
+ .row{"ng-show" => "diff.unmanaged_files.only_in1 || diff.unmanaged_files.only_in2"}
291
307
  .col-xs-1
292
308
  .col-xs-5
293
309
  %only-in-a
@@ -330,7 +346,7 @@
330
346
  .row
331
347
  .col-xs-1
332
348
  %a{:href => "#groups"}
333
- %img.scope_logo_big{:src => "assets/logo-groups.png", :class=>"over", :"data-toggle"=>"popover", :title=>"Groups", :"data-content"=>"#{scope_help('groups')}"}/
349
+ %img.scope_logo_big{:src => "/assets/logo-groups.png", :class=>"over", :"data-toggle"=>"popover", :title=>"Groups", :"data-content"=>"#{scope_help('groups')}"}/
334
350
  %span.toggle{:title => "Collapse/Expand"}
335
351
  .col-xs-11
336
352
  %h2
@@ -341,7 +357,7 @@
341
357
  %span.summary-part{"ng-show" => "diff.groups.only_in2"}
342
358
  {{diff.meta.description_b}}: {{diff.groups.only_in2.length}} groups
343
359
  %span.summary-part{"ng-show" => "diff.groups.common"}
344
- %a{href: "#groups_both"}
360
+ %a{:class=>"show-common-elements", href: "#groups_both"}
345
361
  both
346
362
  = ": {{diff.groups.common.length}} groups"
347
363
  .row.scope_content.collapse.in
@@ -401,7 +417,7 @@
401
417
  .row
402
418
  .col-xs-1
403
419
  %a{:href => "#repositories"}
404
- %img.scope_logo_big{:src => "assets/logo-repositories.png", :class=>"over", :"data-toggle"=>"popover", :title=>"Repositories", :"data-content"=>"#{scope_help('repositories')}"}/
420
+ %img.scope_logo_big{:src => "/assets/logo-repositories.png", :class=>"over", :"data-toggle"=>"popover", :title=>"Repositories", :"data-content"=>"#{scope_help('repositories')}"}/
405
421
  %span.toggle{:title => "Collapse/Expand"}
406
422
  .col-xs-11
407
423
  %h2
@@ -412,7 +428,7 @@
412
428
  %span.summary-part{"ng-show" => "diff.repositories.only_in2"}
413
429
  {{diff.meta.description_b}}: {{diff.repositories.only_in2.length}} repos
414
430
  %span.summary-part{"ng-show" => "diff.repositories.common"}
415
- %a{href: "#repositories_both"}
431
+ %a{:class=>"show-common-elements", href: "#repositories_both"}
416
432
  both
417
433
  = ": {{diff.repositories.common.length}} repos"
418
434
  .row.scope_content.collapse.in
@@ -468,7 +484,7 @@
468
484
  .row
469
485
  .col-xs-1
470
486
  %a{:href => "#changed_managed_files"}
471
- %img.scope_logo_big{:src => "assets/logo-changed-managed-files.png", :class=>"over", :"data-toggle"=>"popover", :title=>"Changed Managed Files", :"data-content"=>"#{scope_help('changed_managed_files')}"}/
487
+ %img.scope_logo_big{:src => "/assets/logo-changed-managed-files.png", :class=>"over", :"data-toggle"=>"popover", :title=>"Changed Managed Files", :"data-content"=>"#{scope_help('changed_managed_files')}"}/
472
488
  %span.toggle{:title => "Collapse/Expand"}
473
489
  .col-xs-11
474
490
  %h2
@@ -479,7 +495,7 @@
479
495
  %span.summary-part{"ng-show" => "diff.changed_managed_files.only_in2"}
480
496
  {{diff.meta.description_b}}: {{diff.changed_managed_files.only_in2.files.length || 0}} files
481
497
  %span.summary-part{"ng-show" => "diff.changed_managed_files.common"}
482
- %a{href: "#changed_managed_files_both"}
498
+ %a{:class=>"show-common-elements", href: "#changed_managed_files_both"}
483
499
  both
484
500
  = ": {{diff.changed_managed_files.common.files.length}} files"
485
501
  .row.scope_content.collapse.in
@@ -537,7 +553,7 @@
537
553
  .row
538
554
  .col-xs-1
539
555
  %a{:href => "#config_files"}
540
- %img.scope_logo_big{:src => "assets/logo-config-files.png", :class=>"over", :"data-toggle"=>"popover", :title=>"Config Files", :"data-content"=>"#{scope_help('config_files')}"}/
556
+ %img.scope_logo_big{:src => "/assets/logo-config-files.png", :class=>"over", :"data-toggle"=>"popover", :title=>"Config Files", :"data-content"=>"#{scope_help('config_files')}"}/
541
557
  %span.toggle{:title => "Collapse/Expand"}
542
558
  .col-xs-11
543
559
  %h2
@@ -548,7 +564,7 @@
548
564
  %span.summary-part{"ng-show" => "diff.config_files.only_in2"}
549
565
  {{diff.meta.description_b}}: {{diff.config_files.only_in2.files.length || 0}} files
550
566
  %span.summary-part{"ng-show" => "diff.config_files.common"}
551
- %a{href: "#config_files_both"}
567
+ %a{:class=>"show-common-elements", href: "#config_files_both"}
552
568
  both
553
569
  = ": {{diff.config_files.common.files.length}} files"
554
570
  .row.scope_content.collapse.in
@@ -592,7 +608,7 @@
592
608
  .row
593
609
  .col-xs-1
594
610
  %a{:href => "#services"}
595
- %img.scope_logo_big{:src => "assets/logo-services.png", :class=>"over", :"data-toggle"=>"popover", :title=>"Services", :"data-content"=>"#{scope_help('services')}"}/
611
+ %img.scope_logo_big{:src => "/assets/logo-services.png", :class=>"over", :"data-toggle"=>"popover", :title=>"Services", :"data-content"=>"#{scope_help('services')}"}/
596
612
  %span.toggle{:title => "Collapse/Expand"}
597
613
  .col-xs-11
598
614
  %h2
@@ -603,7 +619,7 @@
603
619
  %span.summary-part{"ng-show" => "diff.services.only_in2"}
604
620
  {{diff.meta.description_b}}: {{diff.services.only_in2.services.length || 0}} services ({{diff.services.only_in2.init_system}})
605
621
  %span.summary-part{"ng-show" => "diff.services.common"}
606
- %a{href: "#services_both"}
622
+ %a{:class=>"show-common-elements", href: "#services_both"}
607
623
  both
608
624
  = ": {{diff.services.common.services.length}} services ({{diff.services.common.init_system}})"
609
625
  .row.scope_content.collapse.in
@@ -630,12 +646,34 @@
630
646
  %in-both
631
647
  %render-template{:template => "scope_services_partial", :object => "diff.services.common"}
632
648
 
633
- %script{:src => "assets/diff.js"}
634
- %script{:src => "assets/compare/machinery.js"}
635
- %script{:src => "assets/bootstrap-tooltip.js"}
636
- %script{:src => "assets/bootstrap-popover.js"}
649
+ %script{:src => "/assets/compare/machinery.js"}
650
+ %script{:src => "/assets/bootstrap-tooltip.js"}
651
+ %script{:src => "/assets/bootstrap-popover.js"}
652
+
653
+ %body{"ng-controller" => "compareController", "data-description-a" => description_a, "data-description-b" => description_b}
654
+ #diff-unmanaged-files.modal.fade
655
+ .modal-dialog.modal-lg
656
+ .modal-content
657
+ .modal-header
658
+ %button.close{"type" => "button", "data-dismiss" => "modal"}
659
+ &times;
660
+ %h4
661
+ Diff Unmanaged Files
662
+ .modal-body
663
+ .row
664
+ File
665
+ %select#diff-unmanaged-files-file{"ng-options" => "file for file in diffableUnmanagedFiles track by file",
666
+ "ng-model" => "selected"}
667
+ .row#diff-unmanaged-files-content{"style" => "display: none"}
668
+ Diff ('#{description_a}' -> '#{description_b}')
669
+ #diff-unmanaged-files-diff
670
+ #diff-unmanaged-files-error{"style" => "display: none"}
671
+ #diff-unmanaged-files-spinner{"style" => "display: none"}
672
+ Generating diff. Please wait...
673
+ .modal-footer
674
+ %button.btn.btn-primary{"type" => "button", "data-dismiss" => "modal"}
675
+ Close
637
676
 
638
- %body
639
677
  .container-fluid
640
678
  #nav-bar
641
679
  .row
@@ -645,26 +683,26 @@
645
683
  Comparing '#{description_a}' with '#{description_b}'
646
684
  %span.scope-navigation
647
685
  Scopes:
648
- %a{:href => "#os", :title => "Operating System"}
649
- %img{:src => "assets/logo-os-small.png"}/
650
- %a{:href => "#packages", :title => "Packages"}
651
- %img{:src => "assets/logo-packages-small.png"}/
652
- %a{:href => "#patterns", :title => "Patterns"}
653
- %img{:src => "assets/logo-patterns-small.png"}/
654
- %a{:href => "#users", :title => "Users"}
655
- %img{:src => "assets/logo-users-small.png"}/
656
- %a{:href => "#groups", :title => "Groups"}
657
- %img{:src => "assets/logo-groups-small.png"}/
658
- %a{:href => "#repositories", :title => "Repositories"}
659
- %img{:src => "assets/logo-repositories-small.png"}/
660
- %a{:href => "#unmanaged_files", :title => "Unmanaged Files"}
661
- %img{:src => "assets/logo-unmanaged-files-small.png"}/
662
- %a{:href => "#changed_managed_files", :title => "Changed Managed Files"}
663
- %img{:src => "assets/logo-changed-managed-files-small.png"}/
664
- %a{:href => "#config_files", :title => "Config Files"}
665
- %img{:src => "assets/logo-config-files-small.png"}/
666
- %a{:href => "#services", :title => "Services"}
667
- %img{:src => "assets/logo-services-small.png"}/
686
+ %a{:href => "#os", :title => "Operating System", "ng-show" => "diff.os"}
687
+ %img{:src => "/assets/logo-os-small.png"}/
688
+ %a{:href => "#packages", :title => "Packages", "ng-show" => "diff.packages"}
689
+ %img{:src => "/assets/logo-packages-small.png"}/
690
+ %a{:href => "#patterns", :title => "Patterns", "ng-show" => "diff.patterns"}
691
+ %img{:src => "/assets/logo-patterns-small.png"}/
692
+ %a{:href => "#users", :title => "Users", "ng-show" => "diff.users"}
693
+ %img{:src => "/assets/logo-users-small.png"}/
694
+ %a{:href => "#groups", :title => "Groups", "ng-show" => "diff.groups"}
695
+ %img{:src => "/assets/logo-groups-small.png"}/
696
+ %a{:href => "#repositories", :title => "Repositories", "ng-show" => "diff.repositories"}
697
+ %img{:src => "/assets/logo-repositories-small.png"}/
698
+ %a{:href => "#unmanaged_files", :title => "Unmanaged Files", "ng-show" => "diff.unmanaged_files"}
699
+ %img{:src => "/assets/logo-unmanaged-files-small.png"}/
700
+ %a{:href => "#changed_managed_files", :title => "Changed Managed Files", "ng-show" => "diff.changed_managed_files"}
701
+ %img{:src => "/assets/logo-changed-managed-files-small.png"}/
702
+ %a{:href => "#config_files", :title => "Config Files", "ng-show" => "diff.config_files"}
703
+ %img{:src => "/assets/logo-config-files-small.png"}/
704
+ %a{:href => "#services", :title => "Services", "ng-show" => "diff.services"}
705
+ %img{:src => "/assets/logo-services-small.png"}/
668
706
  .row
669
707
  .col-xs-1
670
708
  %a#expand-all{:href => "#", :style => "display: none"}
@@ -678,14 +716,20 @@
678
716
  %a{:href => "http://machinery-project.org", :target => "_blank"}
679
717
  Machinery
680
718
 
681
- #content_container{"ng-controller" => "compareController"}
682
- %div{"src" => "'scope_os'", "ng-include" => true}
683
- %div{"src" => "'scope_packages'", "ng-include" => true}
684
- %div{"src" => "'scope_patterns'", "ng-include" => true}
685
- %div{"src" => "'scope_users'", "ng-include" => true}
686
- %div{"src" => "'scope_groups'", "ng-include" => true}
687
- %div{"src" => "'scope_repositories'", "ng-include" => true}
688
- %div{"src" => "'scope_unmanaged_files'", "ng-include" => true}
689
- %div{"src" => "'scope_changed_managed_files'", "ng-include" => true}
690
- %div{"src" => "'scope_config_files'", "ng-include" => true}
691
- %div{"src" => "'scope_services'", "ng-include" => true}
719
+ #content_container
720
+ .row{"ng-hide" => "diff"}
721
+ .col-xs-11.col-xs-offset-1
722
+ %p
723
+ Loading comparison results. Please wait...
724
+ %div{"ng-show" => "diff"}
725
+ %div{"src" => "'alert'", "ng-include" => true}
726
+ %div{"src" => "'scope_os'", "ng-include" => true, "ng-show" => "diff.os"}
727
+ %div{"src" => "'scope_packages'", "ng-include" => true, "ng-show" => "diff.packages"}
728
+ %div{"src" => "'scope_patterns'", "ng-include" => true, "ng-show" => "diff.patterns"}
729
+ %div{"src" => "'scope_users'", "ng-include" => true, "ng-show" => "diff.users"}
730
+ %div{"src" => "'scope_groups'", "ng-include" => true, "ng-show" => "diff.groups"}
731
+ %div{"src" => "'scope_repositories'", "ng-include" => true, "ng-show" => "diff.repositories"}
732
+ %div{"src" => "'scope_unmanaged_files'", "ng-include" => true, "ng-show" => "diff.unmanaged_files"}
733
+ %div{"src" => "'scope_changed_managed_files'", "ng-include" => true, "ng-show" => "diff.changed_managed_files"}
734
+ %div{"src" => "'scope_config_files'", "ng-include" => true, "ng-show" => "diff.config_files"}
735
+ %div{"src" => "'scope_services'", "ng-include" => true, "ng-show" => "diff.services"}
data/lib/cli.rb CHANGED
@@ -26,9 +26,6 @@ class Cli
26
26
  switch :version, negatable: false, desc: "Show version"
27
27
  switch :debug, negatable: false, desc: "Enable debug mode"
28
28
  switch [:help, :h], negatable: false, desc: "Show help"
29
- if @config.experimental_features
30
- flag :exclude, negatable: false, desc: "Exclude elements matching the filter criteria"
31
- end
32
29
 
33
30
  sort_help :manually
34
31
  pre do |global_options,command,options,args|
@@ -88,7 +85,7 @@ class Cli
88
85
  case e
89
86
  when GLI::MissingRequiredArgumentsException
90
87
  Machinery::Ui.error("Option --" + e.message)
91
- exit 1
88
+ exit 1
92
89
  when GLI::UnknownCommandArgument, GLI::UnknownGlobalArgument,
93
90
  GLI::UnknownCommand, GLI::BadCommandLine, OptionParser::MissingArgument
94
91
  Machinery::Ui.error e.to_s + "\n\n"
@@ -228,6 +225,12 @@ class Cli
228
225
  Inspector.sort_scopes(scopes.uniq)
229
226
  end
230
227
 
228
+ def self.supports_filtering(command)
229
+ if @config.experimental_features
230
+ command.flag :exclude, negatable: false, desc: "Exclude elements matching the filter criteria"
231
+ end
232
+ end
233
+
231
234
  AVAILABLE_SCOPE_LIST = Machinery::Ui.internal_scope_list_to_string(
232
235
  Inspector.all_scopes
233
236
  )
@@ -317,6 +320,10 @@ class Cli
317
320
  c.switch "show-all", required: false, negatable: false,
318
321
  desc: "Show also common properties"
319
322
  if @config.experimental_features
323
+ c.flag [:port, :p], type: Integer, required: false, default_value: @config.http_server_port,
324
+ desc: "Listen on port PORT", arg_name: "PORT"
325
+ c.flag [:ip, :i], type: String, required: false, default_value: "127.0.0.1",
326
+ desc: "Listen on ip address IP", arg_name: "IP"
320
327
  c.switch "html", required: false, negatable: false,
321
328
  desc: "Open comparison in HTML format in your web browser."
322
329
  end
@@ -336,7 +343,9 @@ class Cli
336
343
  task = CompareTask.new
337
344
  opts = {
338
345
  show_html: options["html"],
339
- show_all: options["show-all"]
346
+ show_all: options["show-all"],
347
+ ip: options["ip"],
348
+ port: options["port"]
340
349
  }
341
350
  task.compare(description1, description2, scope_list, opts)
342
351
  end
@@ -461,6 +470,7 @@ class Cli
461
470
  LONGDESC
462
471
  arg "HOSTNAME"
463
472
  command :inspect do |c|
473
+ supports_filtering(c)
464
474
  c.flag [:name, :n], type: String, required: false, arg_name: "NAME",
465
475
  desc: "Store system description under the specified name"
466
476
  c.flag [:scope, :s], type: String, required: false,
@@ -516,7 +526,7 @@ class Cli
516
526
  end
517
527
  inspect_options[:remote_user] = options["remote-user"]
518
528
 
519
- filter = FilterOptionParser.parse("inspect", options, global_options)
529
+ filter = FilterOptionParser.parse("inspect", options)
520
530
 
521
531
  if options["verbose"] && !filter.empty?
522
532
  Machinery::Ui.puts "\nThe following filters are applied during inspection:"
@@ -611,6 +621,7 @@ class Cli
611
621
  LONGDESC
612
622
  arg "NAME"
613
623
  command :show do |c|
624
+ supports_filtering(c)
614
625
  c.flag [:scope, :s], type: String, required: false,
615
626
  desc: "Show specified scopes", arg_name: "SCOPE_LIST"
616
627
  c.flag ["exclude-scope", :e], type: String, required: false,
@@ -638,7 +649,7 @@ class Cli
638
649
  description = SystemDescription.load(name, system_description_store)
639
650
  scope_list = process_scope_option(options[:scope], options["exclude-scope"])
640
651
 
641
- filter = FilterOptionParser.parse("show", options, global_options)
652
+ filter = FilterOptionParser.parse("show", options)
642
653
 
643
654
  inspected_filters = description.filter_definitions("inspect")
644
655
 
data/lib/compare_task.rb CHANGED
@@ -27,26 +27,25 @@ class CompareTask
27
27
  end
28
28
 
29
29
  def render_html_comparison(description1, description2, scopes, options)
30
- diff = {
31
- meta: {
32
- description_a: description1.name,
33
- description_b: description2.name,
34
- }
35
- }
30
+ LocalSystem.validate_existence_of_package("xdg-utils")
36
31
 
37
- scopes.each do |scope|
38
- if description1[scope] && description2[scope]
39
- comparison = Comparison.compare_scope(description1, description2, scope)
40
- diff[scope] = comparison.as_json
41
- end
42
- end
32
+ url = "http://#{options[:ip]}:#{options[:port]}/compare/" \
33
+ "#{CGI.escape(description1.name)}/#{CGI.escape(description2.name)}"
43
34
 
44
- target = File.join(Machinery::DEFAULT_CONFIG_DIR, "html-comparison")
45
- FileUtils.rm_r(target) if Dir.exists?(target)
46
- FileUtils.mkdir_p(target)
35
+ Machinery::Ui.use_pager = false
36
+ Machinery::Ui.puts <<EOF
37
+ There is a web server running, serving the comparison result on #{url}.
38
+
39
+ The server can be closed with Ctrl+C.
40
+ EOF
41
+
42
+ server = Html.run_server(description1.store, port: options[:port], ip: options[:ip])
43
+
44
+ Html.when_server_ready(options[:ip], options[:port]) do
45
+ LoggedCheetah.run("xdg-open", url)
46
+ end
47
47
 
48
- Html.generate_comparison(diff, target)
49
- LoggedCheetah.run("xdg-open", File.join(target, "index.html"))
48
+ server.join # Wait until the user cancelled the blocking webserver
50
49
  end
51
50
 
52
51
  def render_comparison(description1, description2, scopes, options = {})
data/lib/exceptions.rb CHANGED
@@ -126,6 +126,7 @@ module Machinery
126
126
  class ExportFailed < MachineryError; end
127
127
  class AnalysisFailed < MachineryError; end
128
128
  class UpgradeFailed < MachineryError; end
129
+ class BinaryDiffError < MachineryError; end
129
130
 
130
131
  class SshConnectionFailed < MachineryError; end
131
132
  class RsyncFailed < MachineryError; end
data/lib/file_diff.rb ADDED
@@ -0,0 +1,32 @@
1
+ # Copyright (c) 2013-2015 SUSE LLC
2
+ #
3
+ # This program is free software; you can redistribute it and/or
4
+ # modify it under the terms of version 3 of the GNU General Public License as
5
+ # published by the Free Software Foundation.
6
+ #
7
+ # This program is distributed in the hope that it will be useful,
8
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
9
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
+ # GNU General Public License for more details.
11
+ #
12
+ # You should have received a copy of the GNU General Public License
13
+ # along with this program; if not, contact SUSE LLC.
14
+ #
15
+ # To contact SUSE about this file by physical or electronic mail,
16
+ # you may find current contact information at www.suse.com
17
+
18
+ class FileDiff
19
+ def self.diff(description1, description2, scope, path)
20
+ return nil if !description1.scope_extracted?(scope) || !description2.scope_extracted?(scope)
21
+
22
+ file1 = description1[scope].files.find { |f| f.name == path }
23
+ file2 = description2[scope].files.find { |f| f.name == path }
24
+ return nil if !file1 || !file2
25
+
26
+ if file1.binary? || file2.binary?
27
+ raise Machinery::Errors::BinaryDiffError, "Can't diff binary files"
28
+ end
29
+
30
+ Diffy::Diff.new(file1.content, file2.content, include_plus_and_minus_in_html: true)
31
+ end
32
+ end
@@ -19,11 +19,11 @@
19
19
  # actual Filter objects.
20
20
  class FilterOptionParser
21
21
  class <<self
22
- def parse(command, options, global_options)
22
+ def parse(command, options)
23
23
  filter = Filter.from_default_definition(command)
24
24
 
25
25
  definitions = skip_files_definitions(options.delete("skip-files"))
26
- definitions += exclude_definitions(global_options["exclude"])
26
+ definitions += exclude_definitions(options["exclude"])
27
27
 
28
28
  definitions.map! { |definition| definition.gsub("\\@", "@") } # Unescape escaped @s
29
29
  definitions.each do |definition|
data/lib/html.rb CHANGED
@@ -137,6 +137,58 @@ class Html
137
137
  content
138
138
  end
139
139
 
140
+ get "/compare/:a/:b.json" do
141
+ description_a = SystemDescription.load(params[:a], system_description_store)
142
+ description_b = SystemDescription.load(params[:b], system_description_store)
143
+
144
+ diff = {
145
+ meta: {
146
+ description_a: description_a.name,
147
+ description_b: description_b.name,
148
+ }
149
+ }
150
+
151
+ Inspector.all_scopes.each do |scope|
152
+ if description_a[scope] && description_b[scope]
153
+ comparison = Comparison.compare_scope(description_a, description_b, scope)
154
+ diff[scope] = comparison.as_json
155
+ else
156
+ diff[:meta][:uninspected] ||= Hash.new
157
+
158
+ if !description_a[scope] && description_b[scope]
159
+ diff[:meta][:uninspected][description_a.name] ||= Array.new
160
+ diff[:meta][:uninspected][description_a.name] << scope
161
+ end
162
+ if !description_b[scope] && description_a[scope]
163
+ diff[:meta][:uninspected][description_b.name] ||= Array.new
164
+ diff[:meta][:uninspected][description_b.name] << scope
165
+ end
166
+ end
167
+ end
168
+
169
+ diff.to_json
170
+ end
171
+
172
+ get "/compare/:a/:b" do
173
+ haml File.read(File.join(Machinery::ROOT, "html/comparison.html.haml")),
174
+ locals: { description_a: params[:a], description_b: params[:b] }
175
+ end
176
+
177
+ get "/compare/:a/:b/files/:scope/*" do
178
+ description1 = SystemDescription.load(params[:a], system_description_store)
179
+ description2 = SystemDescription.load(params[:b], system_description_store)
180
+ filename = File.join("/", params["splat"].first)
181
+
182
+ begin
183
+ diff = FileDiff.diff(description1, description2, params[:scope], filename)
184
+ rescue Machinery::Errors::BinaryDiffError
185
+ status 406
186
+ return "binary file"
187
+ end
188
+
189
+ diff.to_s(:html)
190
+ end
191
+
140
192
  get "/:id" do
141
193
  haml File.read(File.join(Machinery::ROOT, "html/index.html.haml")),
142
194
  locals: { description_name: params[:id] }
data/lib/machinery.rb CHANGED
@@ -34,6 +34,7 @@ require "find"
34
34
  require "pathname"
35
35
  require "nokogiri"
36
36
  require "socket"
37
+ require "diffy"
37
38
 
38
39
  require_relative "machinery_logger"
39
40
  require_relative "zypper"
@@ -97,6 +98,7 @@ require_relative "scope_file_access_archive"
97
98
  require_relative "man_task"
98
99
  require_relative "comparison"
99
100
  require_relative "serve_html_task"
101
+ require_relative "file_diff"
100
102
 
101
103
  Dir[File.join(Machinery::ROOT, "plugins", "**", "*.rb")].each { |f| require(f) }
102
104
 
data/lib/remote_system.rb CHANGED
@@ -83,10 +83,10 @@ class RemoteSystem < System
83
83
  end
84
84
  end
85
85
 
86
- # Tries to connect to the remote system as root (without a password or passphrase)
86
+ # Tries to run the noop-command(:) on the remote system as root (without a password or passphrase)
87
87
  # and raises an Machinery::Errors::SshConnectionFailed exception when it's not successful.
88
88
  def connect
89
- LoggedCheetah.run "ssh", "-q", "-o", "BatchMode=yes", "#{remote_user}@#{host}"
89
+ LoggedCheetah.run "ssh", "-q", "-o", "BatchMode=yes", "#{remote_user}@#{host}", ":"
90
90
  rescue Cheetah::ExecutionFailed
91
91
  raise Machinery::Errors::SshConnectionFailed.new(
92
92
  "Could not establish SSH connection to host '#{host}'. Please make sure that " \
data/lib/version.rb CHANGED
@@ -17,6 +17,6 @@
17
17
 
18
18
  module Machinery
19
19
 
20
- VERSION = "1.10.0"
20
+ VERSION = "1.11.0"
21
21
 
22
22
  end
Binary file
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: machinery-tool
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.10.0
4
+ version: 1.11.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - SUSE
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-07-09 00:00:00.000000000 Z
11
+ date: 2015-07-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: cheetah
@@ -164,6 +164,20 @@ dependencies:
164
164
  - - "~>"
165
165
  - !ruby/object:Gem::Version
166
166
  version: 0.3.0
167
+ - !ruby/object:Gem::Dependency
168
+ name: diffy
169
+ requirement: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - "~>"
172
+ - !ruby/object:Gem::Version
173
+ version: 3.0.7
174
+ type: :runtime
175
+ prerelease: false
176
+ version_requirements: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - "~>"
179
+ - !ruby/object:Gem::Version
180
+ version: 3.0.7
167
181
  - !ruby/object:Gem::Dependency
168
182
  name: ronn
169
183
  requirement: !ruby/object:Gem::Requirement
@@ -239,6 +253,7 @@ files:
239
253
  - html/assets/collapse.js
240
254
  - html/assets/compare/machinery-compare.js
241
255
  - html/assets/compare/machinery.js
256
+ - html/assets/cross.png
242
257
  - html/assets/jquery-2.1.1.min.js
243
258
  - html/assets/logo-changed-managed-files-small.png
244
259
  - html/assets/logo-changed-managed-files.png
@@ -289,6 +304,7 @@ files:
289
304
  - lib/exceptions.rb
290
305
  - lib/export_task.rb
291
306
  - lib/exporter.rb
307
+ - lib/file_diff.rb
292
308
  - lib/file_scope.rb
293
309
  - lib/file_validator.rb
294
310
  - lib/filter.rb