depot3 0.0.0a1 → 3.0.7

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.
Files changed (112) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +55 -1
  3. data/bin/d3 +323 -0
  4. data/bin/d3admin +1011 -0
  5. data/bin/d3helper +354 -0
  6. data/bin/puppytime +334 -0
  7. data/data/d3/com.pixar.d3.RepoMan.plist +23 -0
  8. data/data/d3/d3.conf.example +507 -0
  9. data/data/d3/d3RepoMan.app/Contents/Frameworks/libswiftAppKit.dylib +0 -0
  10. data/data/d3/d3RepoMan.app/Contents/Frameworks/libswiftCore.dylib +0 -0
  11. data/data/d3/d3RepoMan.app/Contents/Frameworks/libswiftCoreData.dylib +0 -0
  12. data/data/d3/d3RepoMan.app/Contents/Frameworks/libswiftCoreGraphics.dylib +0 -0
  13. data/data/d3/d3RepoMan.app/Contents/Frameworks/libswiftCoreImage.dylib +0 -0
  14. data/data/d3/d3RepoMan.app/Contents/Frameworks/libswiftDarwin.dylib +0 -0
  15. data/data/d3/d3RepoMan.app/Contents/Frameworks/libswiftDispatch.dylib +0 -0
  16. data/data/d3/d3RepoMan.app/Contents/Frameworks/libswiftFoundation.dylib +0 -0
  17. data/data/d3/d3RepoMan.app/Contents/Frameworks/libswiftObjectiveC.dylib +0 -0
  18. data/data/d3/d3RepoMan.app/Contents/Info.plist +56 -0
  19. data/data/d3/d3RepoMan.app/Contents/MacOS/d3RepoMan +0 -0
  20. data/data/d3/d3RepoMan.app/Contents/PkgInfo +1 -0
  21. data/data/d3/d3RepoMan.app/Contents/Resources/Base.lproj/MainMenu.nib +0 -0
  22. data/data/d3/d3RepoMan.app/Contents/Resources/last-foreground-times-template.plist +5 -0
  23. data/data/d3/d3RepoMan.app/Contents/_CodeSignature/CodeResources +214 -0
  24. data/data/d3/puppytime/ImageLicenses.txt +165 -0
  25. data/data/d3/puppytime/notification_image +1 -0
  26. data/data/d3/puppytime/opt_out_image +1 -0
  27. data/data/d3/puppytime/slideshow/2008-07-11_White_German_Shepherd_pup_chilling_at_the_Coker_Arboretum.jpg +0 -0
  28. data/data/d3/puppytime/slideshow/2009-04-21_APBT_pup_on_deck.jpg +0 -0
  29. data/data/d3/puppytime/slideshow/A_puppy_Yorkie.jpg +0 -0
  30. data/data/d3/puppytime/slideshow/Alert_Pug_Puppy.jpg +0 -0
  31. data/data/d3/puppytime/slideshow/Australian_Cattle_Dog_puppies_04.JPG +0 -0
  32. data/data/d3/puppytime/slideshow/Beagle_puppy_Cadet.jpg +0 -0
  33. data/data/d3/puppytime/slideshow/Bernese_Mountain_Dog.jpg +0 -0
  34. data/data/d3/puppytime/slideshow/Bloodhound_Puppy.jpg +0 -0
  35. data/data/d3/puppytime/slideshow/Boston_terrier_with_toy.jpg +0 -0
  36. data/data/d3/puppytime/slideshow/Boxer_puppy_fawn_portrai.jpg +0 -0
  37. data/data/d3/puppytime/slideshow/Caracal_kitten.jpg +0 -0
  38. data/data/d3/puppytime/slideshow/Chihuahua_&_Doberman_Pup.jpg +0 -0
  39. data/data/d3/puppytime/slideshow/Cuccioli_di_Margot_a_35_gg_Basenjis.jpg +0 -0
  40. data/data/d3/puppytime/slideshow/Dalmatian_puppy_03.jpg +0 -0
  41. data/data/d3/puppytime/slideshow/GoldenRetrieverPuppyDaisyParker.JPG +0 -0
  42. data/data/d3/puppytime/slideshow/Green_eyed_beige_Chihuahua.jpg +0 -0
  43. data/data/d3/puppytime/slideshow/Let_Sleeping_Dogs_Lie.jpg +0 -0
  44. data/data/d3/puppytime/slideshow/Meatball_-_French_Bulldog_Puppy.jpg +0 -0
  45. data/data/d3/puppytime/slideshow/Oola_-_9_weeks.jpg +0 -0
  46. data/data/d3/puppytime/slideshow/Pancho0008.JPG +0 -0
  47. data/data/d3/puppytime/slideshow/Pomeranian_orange-sable_Coco.jpg +0 -0
  48. data/data/d3/puppytime/slideshow/Pug_puppy_001.jpg +0 -0
  49. data/data/d3/puppytime/slideshow/Puggle_puppy_6_weeks.JPG +0 -0
  50. data/data/d3/puppytime/slideshow/Puli_kan.jpg +0 -0
  51. data/data/d3/puppytime/slideshow/Puppy_French_Bulldog.jpg +0 -0
  52. data/data/d3/puppytime/slideshow/Rocco_the_Bulldog.jpg +0 -0
  53. data/data/d3/puppytime/slideshow/Rottweiler_Face.jpg +0 -0
  54. data/data/d3/puppytime/slideshow/Saint_Bernard_puppy.jpg +0 -0
  55. data/data/d3/puppytime/slideshow/Scottish_froment.jpg +0 -0
  56. data/data/d3/puppytime/slideshow/Shar_pei_puppy_(age_2_months).jpg +0 -0
  57. data/data/d3/puppytime/slideshow/Shiba-Inu_beim_Spielen_im_Schnee.JPG +0 -0
  58. data/data/d3/puppytime/slideshow/Smooth-coat_Border_Collie_puppy..jpg +0 -0
  59. data/data/d3/puppytime/slideshow/Smooth_Dachshund_puppies.jpg +0 -0
  60. data/data/d3/puppytime/slideshow/Snow_dog.jpg +0 -0
  61. data/data/d3/puppytime/slideshow/Taylor_the_Pembroke_Welsh_Corgi.png +0 -0
  62. data/data/d3/puppytime/slideshow/Weim_Pups_001.jpg +0 -0
  63. data/data/d3/puppytime/slideshow/Westie_pups.jpg +0 -0
  64. data/data/d3/puppytime/slideshow/Yellow_Labrador_puppies_(4165737325).jpg +0 -0
  65. data/lib/d3/admin/add.rb +451 -0
  66. data/lib/d3/admin/auth.rb +470 -0
  67. data/lib/d3/admin/edit.rb +297 -0
  68. data/lib/d3/admin/help.rb +396 -0
  69. data/lib/d3/admin/interactive.rb +972 -0
  70. data/lib/d3/admin/options.rb +454 -0
  71. data/lib/d3/admin/prefs.rb +204 -0
  72. data/lib/d3/admin/report.rb +727 -0
  73. data/lib/d3/admin/state.rb +42 -0
  74. data/lib/d3/admin/validate.rb +413 -0
  75. data/lib/d3/admin.rb +42 -0
  76. data/lib/d3/basename.rb +217 -0
  77. data/lib/d3/client/auth.rb +108 -0
  78. data/lib/d3/client/class_methods.rb +766 -0
  79. data/lib/d3/client/class_variables.rb +47 -0
  80. data/lib/d3/client/cli.rb +187 -0
  81. data/lib/d3/client/environment.rb +134 -0
  82. data/lib/d3/client/help.rb +110 -0
  83. data/lib/d3/client/lists.rb +314 -0
  84. data/lib/d3/client/receipt.rb +1173 -0
  85. data/lib/d3/client.rb +45 -0
  86. data/lib/d3/configuration.rb +319 -0
  87. data/lib/d3/constants.rb +60 -0
  88. data/lib/d3/database.rb +488 -0
  89. data/lib/d3/exceptions.rb +44 -0
  90. data/lib/d3/log.rb +271 -0
  91. data/lib/d3/package/aliases.rb +80 -0
  92. data/lib/d3/package/attributes.rb +97 -0
  93. data/lib/d3/package/class_methods.rb +817 -0
  94. data/lib/d3/package/class_variables.rb +46 -0
  95. data/lib/d3/package/client_actions.rb +293 -0
  96. data/lib/d3/package/constants.rb +58 -0
  97. data/lib/d3/package/constructor.rb +191 -0
  98. data/lib/d3/package/getters.rb +164 -0
  99. data/lib/d3/package/mixins.rb +39 -0
  100. data/lib/d3/package/private_methods.rb +227 -0
  101. data/lib/d3/package/questions.rb +95 -0
  102. data/lib/d3/package/server_actions.rb +683 -0
  103. data/lib/d3/package/setters.rb +326 -0
  104. data/lib/d3/package/validate.rb +448 -0
  105. data/lib/d3/package.rb +51 -0
  106. data/lib/d3/puppytime/pending_puppy.rb +108 -0
  107. data/lib/d3/puppytime/puppy_queue.rb +274 -0
  108. data/lib/d3/puppytime.rb +68 -0
  109. data/lib/d3/state.rb +105 -0
  110. data/lib/d3/utility.rb +325 -0
  111. data/lib/d3/version.rb +1 -1
  112. metadata +162 -9
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d625adcf2d799ef5d29936bc7535bc148d0219a1
4
- data.tar.gz: 733b6a4da9b4ac7ff8c6b75f722fa9f88c88d44d
3
+ metadata.gz: b324775776772e84290c9a70c319cd331ff8b36a
4
+ data.tar.gz: 0497c9fe41fbbb93ec8a64d50bf4715f97a4ffb6
5
5
  SHA512:
6
- metadata.gz: f5ad8cd0f965268ca65bf7883a908af90afe47a0010609bdb16744b6388339629fa86b2adb71798d2e6b390d9f96713651070ef52b27ae07cfb6b570138423cb
7
- data.tar.gz: 2e2db8d11eba42b8b912e39ff5d46a12bc9dfd1375fd19436c4789e0aed49da400cc2cd54f0bbe30e073384d289db5ca465126e9aa2e15fb6f2dae04d08491a1
6
+ metadata.gz: e584088d46f4cbc0982bb0bdd39bdc47145c9f0e32bcfcdee79cb333368fc5c169dc7a11cbf6d3c23e141098a1768ad01a9d54141cd2bb5d0b5e662e315b6d11
7
+ data.tar.gz: b9ae548291035fdd3bb88b51c9091038b8de70bf00a2de5317c08374b80bf123e6b897880f2421b1ac8c38d5b8492dee1df65d671092660388ac2ca5b930122f
data/README.md CHANGED
@@ -1,3 +1,57 @@
1
1
  # d3 - Command line package and patch management for Casper
2
2
 
3
- This is a temporary placeholder. We plan to release d3 in early April, 2016.
3
+ d3 is a package deployment and patch management system for OS X that enhances the
4
+ [Casper Suite](http://www.jamfsoftware.com/products/casper-suite/), an enterprise-level management system for Apple devices from [JAMF Software](http://www.jamfsoftware.com/). It was created by [Pixar Animation Studios](http://www.pixar.com/).
5
+
6
+
7
+
8
+ d3 adds these, capabilities and more, to Casper's package handling:
9
+
10
+ * Automatic software updates on clients when new versions are released on the server
11
+ * Pre-release piloting of new packages
12
+ * Customizable slideshow presented during logout/reboot installs
13
+ * Installs and uninstalls are conditional on the exit status of pre-flight scripts
14
+ * Packages can be expired (auto-uninstalled) after a period of disuse
15
+ * Both the client and admin tools are command-line only and fully scriptable
16
+ * Admin command-line options allow integration with developer workflows and package-retrieval tools
17
+
18
+ d3 is written in Ruby and available as a rubygem called ['depot3'](https://rubygems.org/gems/depot3). It interfaces with Casper mostly via it's REST API using [ruby-jss](https://github.com/PixarAnimationStudios/ruby-jss), a ruby module that provides simple and powerful access to the API. It also uses Casper's backend MySQL database directly to provide enhanced features.
19
+
20
+
21
+ Please see the [wiki](https://github.com/PixarAnimationStudios/depot3/wiki) for full documentation
22
+
23
+ The developer documentation for the D3 ruby module is at [http://www.rubydoc.info/gems/depot3](http://www.rubydoc.info/gems/depot3)
24
+
25
+ Also check out [ruby-jss](https://github.com/PixarAnimationStudios/ruby-jss), which is used by d3, but is useful for working with the Casper REST API in any project.
26
+
27
+
28
+ ## CONTACT
29
+
30
+ [Email the developer](mailto:d3@pixar.com)
31
+
32
+ [Macadmins Slack Channel](https://macadmins.slack.com/messages/#d3/)
33
+
34
+ ## LICENSE
35
+
36
+ Copyright 2016 Pixar
37
+
38
+ Licensed under the Apache License, Version 2.0 (the "Apache License")
39
+ with the following modification; you may not use d3 except in
40
+ compliance with the Apache License and the following modification to it:
41
+
42
+ Section 6. Trademarks. is deleted and replaced with:
43
+
44
+ 6\. Trademarks. This License does not grant permission to use the trade
45
+ names, trademarks, service marks, or product names of the Licensor
46
+ and its affiliates, except as required to comply with Section 4(c) of
47
+ the License and to reproduce the content of the NOTICE file.
48
+
49
+ You may obtain a copy of the Apache License at
50
+
51
+ http://www.apache.org/licenses/LICENSE-2.0
52
+
53
+ Unless required by applicable law or agreed to in writing, software
54
+ distributed under the Apache License with the above modification is
55
+ distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
56
+ KIND, either express or implied. See the Apache License for the specific
57
+ language governing permissions and limitations under the Apache License.
data/bin/d3 ADDED
@@ -0,0 +1,323 @@
1
+ #!/usr/bin/ruby
2
+ ### Copyright 2016 Pixar
3
+ ###
4
+ ### Licensed under the Apache License, Version 2.0 (the "Apache License")
5
+ ### with the following modification; you may not use this file except in
6
+ ### compliance with the Apache License and the following modification to it:
7
+ ### Section 6. Trademarks. is deleted and replaced with:
8
+ ###
9
+ ### 6. Trademarks. This License does not grant permission to use the trade
10
+ ### names, trademarks, service marks, or product names of the Licensor
11
+ ### and its affiliates, except as required to comply with Section 4(c) of
12
+ ### the License and to reproduce the content of the NOTICE file.
13
+ ###
14
+ ### You may obtain a copy of the Apache License at
15
+ ###
16
+ ### http://www.apache.org/licenses/LICENSE-2.0
17
+ ###
18
+ ### Unless required by applicable law or agreed to in writing, software
19
+ ### distributed under the Apache License with the above modification is
20
+ ### distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
21
+ ### KIND, either express or implied. See the Apache License for the specific
22
+ ### language governing permissions and limitations under the Apache License.
23
+ ###
24
+ ###
25
+
26
+
27
+ ######################################
28
+ # d3 - a commandline interface to Casper package maintenance
29
+ # and Patch Management
30
+ #
31
+ # Copyright 2010 Pixar Animation Studios
32
+ #
33
+ # Chris Lasell chrisl@pixar.com 2010-04-22
34
+
35
+
36
+ # TO DO - add commands for:
37
+ ## immediately remove a receipt
38
+ ## set up configuration on a client
39
+
40
+ ############
41
+ # Modules, Libraries, etc
42
+ ############
43
+
44
+ # Load libraries
45
+ require 'd3'
46
+
47
+ #####################################
48
+ # Script Object
49
+ #####################################
50
+
51
+ class App
52
+
53
+ # the following d3 commands all require one or more arguments to work on
54
+ ACTIONS_NEEDING_ARGS = D3::Client::ACTIONS.select{|k,v| v[:arg] }
55
+
56
+ # the following d3 commands need @admin to be set
57
+ ACTIONS_NEEDING_ADMIN = D3::Client::ACTIONS.select{|k,v| v[:needs_admin] }
58
+
59
+ # the following d3 commands need a connection to the server
60
+ ACTIONS_NEEDING_SERVER = D3::Client::ACTIONS.select{|k,v| v[:needs_connection] }
61
+
62
+ ### set up
63
+ ###
64
+ def initialize(args)
65
+
66
+ D3::LOG.progname = File.basename __FILE__
67
+
68
+ # here's where we hold cmdline args &c
69
+ @options = OpenStruct.new
70
+
71
+ # parse the commandline and populate @action, @options and @targets
72
+ parse_cli
73
+
74
+ # action OK?
75
+ D3::Client::ACTIONS.each do |aname,info|
76
+ @action = aname if @action_from_user == aname
77
+ break if @action
78
+ @action = aname if info[:aka] == @action_from_user
79
+ break if @action
80
+ end
81
+ raise ArgumentError,"Unknown d3 action: #{@action_from_user}. Use -H for help" unless @action
82
+
83
+ # d3 must be run as root - even just listing stuff.
84
+ # (because root is needed to retrieve the passwords for automation)
85
+ if JSS.superuser?
86
+ # make sure some dirs exist
87
+ D3::SUPPORT_DIR.mkpath unless D3::SUPPORT_DIR.directory?
88
+ D3::SUPPORT_DIR.chmod 0755
89
+
90
+ # otherwise, yell if we need to be root.
91
+ else
92
+ raise D3::PermissionError, "You must be root to use d3." unless [:help, :version].include? @action
93
+ end #if root
94
+
95
+ # bail if the jamf binary isn't installed
96
+ unless D3::Client::JAMF_BINARY.executable?
97
+ raise JSS::NoSuchItemError, "The jamf binary isn't installed properly."
98
+ end
99
+
100
+
101
+ # Does this command need the name of an admin for recording who's doing it?
102
+ # The admin name cannot be one of D3::DISALLOWED_ADMINS, currently:
103
+ # [nil, "", "root", "unknown", "auto-installed"]
104
+ # The D3.admin method will try to figure out the real non-root admin name.
105
+ #
106
+ # Syncing doesn't require an admin for auto-installs and updates, but
107
+ # any automated scripts that do a d3 command might need to provide an
108
+ # appropriate admin name. E.g. if a policy runs a script that installs
109
+ # a d3 pkg, it should use something like
110
+ # d3 install some-pkg --admin my-policy-script
111
+ # then the receipt for other-pkg will show that it was installed by
112
+ # 'my-policy-script'. Another useful example is a pre- or post-install script that
113
+ # installs another d3 pkg. That script should use the --admin option to
114
+ # indicate that it did the install
115
+ #
116
+ @options.admin ||= D3.admin
117
+ @options.admin = @options.admin.to_s
118
+ if ACTIONS_NEEDING_ADMIN.keys.include? @action and D3::DISALLOWED_ADMINS.include? @options.admin
119
+ raise ArgumentError, "Cannot determine non-root admin name, please use --admin with '#{@action}'."
120
+ end
121
+ D3::Client.set_env :admin, @options_admin
122
+
123
+ # if we're installing or piloting, and have a custom expiration, it must be
124
+ # a positive integer
125
+ if @action == :install and @options.custom_expiration
126
+ unless @options.custom_expiration =~ /^\d+$/ and @options.custom_expiration.to_i >= 0
127
+ raise ArgumentError, "Expiration periods (in days) must be an integer >= 0"
128
+ end
129
+ @options.custom_expiration = @options.custom_expiration.to_i
130
+ end
131
+
132
+ # tell the client if the admin asked for no puppy notification
133
+ if @options.no_logout_notice
134
+ D3::Client.puppy_notification_ok_with_admin = false
135
+ end
136
+
137
+ # If the action needs targets, and there are none, say so
138
+ if ACTIONS_NEEDING_ARGS.keys.include?(@action) and @targets == 0
139
+ arg_type = D3::Client::ACTIONS[@action][:arg]
140
+ raise ArgumentError, "Action '#{@action}' needs one or more #{arg_type} targets."
141
+ end
142
+
143
+ # connect to d3
144
+ D3::Client.connect if ACTIONS_NEEDING_SERVER.keys.include?(@action)
145
+
146
+ end # init
147
+
148
+ ### Parse the command line - fill @options with our options.
149
+ ###
150
+ def parse_cli
151
+
152
+ # when finished, this leaves the d3 command and its arg in ARGV
153
+ opts = GetoptLong.new( *D3::Client::OPTIONS.values.map{|opt| opt[:cli]} )
154
+
155
+ opts.each do |opt, arg|
156
+ case opt
157
+ when '--help'
158
+ @show_help = :show_help
159
+
160
+ when '--version'
161
+ @show_help = :show_version
162
+
163
+ when '--quiet'
164
+ @options.quiet = true
165
+ D3.verbosity = D3.verbosity + 1
166
+
167
+ when '--verbose'
168
+ @options.verbose = true
169
+ D3.verbosity = D3.verbosity - 1
170
+
171
+ when '--no-puppy-notification'
172
+ @options.no_logout_notice = true
173
+
174
+ when '--puppies'
175
+ @options.puppies = true
176
+
177
+ when '--force'
178
+ @options.force = true
179
+ D3::force
180
+
181
+ when '--freeze'
182
+ @options.freeze_on_install = true
183
+
184
+ when '--admin'
185
+ @options.admin = arg
186
+
187
+ when '--expiration'
188
+ @options.custom_expiration = arg
189
+
190
+ when '--debug'
191
+ @options.debug = true
192
+ @options.verbose = true
193
+ D3.verbosity = :debug
194
+ D3::LOG.level = :debug
195
+ D3::Client.set_env :debug
196
+ end # case
197
+ end # opts.each
198
+
199
+ ARGV.unshift "help" if @show_help
200
+
201
+ # gotta have a least an action....
202
+ if ARGV.empty?
203
+ show_usage
204
+ raise ArgumentError, "action required. Use -H for help"
205
+ end
206
+
207
+ # the gsub makes, eg, 'list-installed' into "list_installed"
208
+ # which are the keys of D3::Client::ACTIONS
209
+ @action_from_user = ARGV.shift.gsub('-','_').to_sym
210
+
211
+ #@targets = ARGV
212
+ @targets = ARGV
213
+
214
+ end # parse args
215
+
216
+ ### Do that d3 thing!
217
+ ###
218
+ def run
219
+ # Process the given d3 command
220
+ case @action
221
+
222
+ when :install then
223
+ D3::Client.install @targets, @options
224
+
225
+ when :uninstall then
226
+ D3::Client.uninstall @targets, @options
227
+
228
+ when :dequeue then
229
+ D3::Client.dequeue_puppies @targets
230
+
231
+ when :sync then
232
+ D3::Client.sync @options
233
+
234
+ when :freeze then
235
+ D3::Client.freeze_receipts @targets
236
+
237
+ when :thaw then
238
+ D3::Client.thaw_receipts @targets
239
+
240
+ when :list_available then
241
+ D3::Client.list_available @options.force
242
+
243
+ when :list_installed then
244
+ D3::Client.list_installed
245
+
246
+ when :list_manual then
247
+ D3::Client.list_manual
248
+
249
+ when :list_pilots then
250
+ D3::Client.list_pilots
251
+
252
+ when :list_frozen then
253
+ D3::Client.list_frozen
254
+
255
+ when :list_puppies then
256
+ D3::Client.list_pending_puppies
257
+
258
+ when :list_details then
259
+ D3::Client.list_details @targets
260
+
261
+ when :list_files then
262
+ D3::Client.list_files @targets
263
+
264
+ when :query_file then
265
+ D3::Client.query_files @targets
266
+
267
+ when :help
268
+ @show_help == :show_version ? show_version : show_help
269
+
270
+ else
271
+ show_usage
272
+ end # case
273
+ end #run
274
+
275
+ ### Show the usage line
276
+ def show_usage
277
+ STDERR.puts D3::Client::Help::USAGE
278
+ end # show_usage
279
+
280
+ ### Show the help message
281
+ ###
282
+ ### @return [void]
283
+ ###
284
+ def show_help
285
+ D3.less_text D3::Client::Help.help_text
286
+ end #show help
287
+
288
+ ### Show the current d3 version
289
+ def show_version
290
+ puts <<-ENDVERS
291
+ D3 module version: #{D3::VERSION}
292
+ JSS module version: #{JSS::VERSION}
293
+ ENDVERS
294
+ end
295
+
296
+
297
+ end # class App
298
+
299
+ ############
300
+ # Do it
301
+ ############
302
+ stty_save = `stty -g`.chomp
303
+ trap("SIGINT") { puts "\nCancelled! Woot!" ; system('stty', stty_save); exit 0 }
304
+
305
+ begin
306
+ # if needed, set debugging even before we make the app
307
+ D3::LOG.level = :debug unless (ARGV & ["--debug", "-d"] ).empty?
308
+
309
+ # make and run d3
310
+ app = App.new(ARGV)
311
+ app.run
312
+
313
+ rescue
314
+ # handle exceptions not handled elsewhere
315
+ D3.log "An error occurred: #{$!.class}: #{$!}", :fatal
316
+ D3.log_backtrace
317
+ exit 1
318
+ ensure
319
+ if JSS::API.connected?
320
+ JSS::DistributionPoint.my_distribution_point.unmount if JSS::DistributionPoint.my_distribution_point.mounted?
321
+ D3::Client.disconnect
322
+ end # if
323
+ end