machinery-tool 1.10.0 → 1.11.0

Sign up to get free protection for your applications and to get access to all the features.
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