alexandria-book-collection-manager 0.6.9.pre1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (293) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +10 -0
  3. data/.rubocop.yml +68 -0
  4. data/.rubocop_todo.yml +200 -0
  5. data/CHANGELOG.md +23 -0
  6. data/COPYING +339 -0
  7. data/ChangeLog.0 +3598 -0
  8. data/Gemfile +9 -0
  9. data/INSTALL.rdoc +156 -0
  10. data/PACKAGING +36 -0
  11. data/README.md +88 -0
  12. data/RELEASE_CHECKLIST +18 -0
  13. data/Rakefile +264 -0
  14. data/TODO +24 -0
  15. data/alexandria-book-collection-manager.gemspec +35 -0
  16. data/alexandria.desktop.in +10 -0
  17. data/bin/alexandria +82 -0
  18. data/doc/AUTHORS +60 -0
  19. data/doc/BUGS +31 -0
  20. data/doc/FAQ +369 -0
  21. data/doc/HACKING +19 -0
  22. data/doc/NEWS +341 -0
  23. data/doc/alexandria.1 +120 -0
  24. data/doc/cuecat_support.rdoc +67 -0
  25. data/lib/alexandria.rb +85 -0
  26. data/lib/alexandria/about.rb +82 -0
  27. data/lib/alexandria/book_providers.rb +411 -0
  28. data/lib/alexandria/book_providers/adlibris.rb +235 -0
  29. data/lib/alexandria/book_providers/amazon_aws.rb +261 -0
  30. data/lib/alexandria/book_providers/amazon_ecs_util.rb +405 -0
  31. data/lib/alexandria/book_providers/barnes_and_noble.rb +229 -0
  32. data/lib/alexandria/book_providers/bol_it.rb +162 -0
  33. data/lib/alexandria/book_providers/deastore.rb +277 -0
  34. data/lib/alexandria/book_providers/douban.rb +135 -0
  35. data/lib/alexandria/book_providers/ibs_it.rb +149 -0
  36. data/lib/alexandria/book_providers/mcu.rb +177 -0
  37. data/lib/alexandria/book_providers/proxis.rb +205 -0
  38. data/lib/alexandria/book_providers/pseudomarc.rb +185 -0
  39. data/lib/alexandria/book_providers/renaud.rb +142 -0
  40. data/lib/alexandria/book_providers/siciliano.rb +271 -0
  41. data/lib/alexandria/book_providers/thalia.rb +197 -0
  42. data/lib/alexandria/book_providers/web.rb +59 -0
  43. data/lib/alexandria/book_providers/webster_it.rb +173 -0
  44. data/lib/alexandria/book_providers/worldcat.rb +251 -0
  45. data/lib/alexandria/book_providers/z3950.rb +422 -0
  46. data/lib/alexandria/config.rb +8 -0
  47. data/lib/alexandria/console.rb +31 -0
  48. data/lib/alexandria/execution_queue.rb +96 -0
  49. data/lib/alexandria/export_library.rb +536 -0
  50. data/lib/alexandria/import_library.rb +316 -0
  51. data/lib/alexandria/import_library_csv.rb +270 -0
  52. data/lib/alexandria/logging.rb +159 -0
  53. data/lib/alexandria/models/book.rb +72 -0
  54. data/lib/alexandria/models/library.rb +714 -0
  55. data/lib/alexandria/net.rb +53 -0
  56. data/lib/alexandria/preferences.rb +324 -0
  57. data/lib/alexandria/scanners.rb +42 -0
  58. data/lib/alexandria/scanners/cuecat.rb +118 -0
  59. data/lib/alexandria/scanners/keyboard.rb +57 -0
  60. data/lib/alexandria/smart_library.rb +525 -0
  61. data/lib/alexandria/ui.rb +53 -0
  62. data/lib/alexandria/ui/builder_base.rb +43 -0
  63. data/lib/alexandria/ui/callbacks.rb +389 -0
  64. data/lib/alexandria/ui/completion_models.rb +228 -0
  65. data/lib/alexandria/ui/dialogs/about_dialog.rb +59 -0
  66. data/lib/alexandria/ui/dialogs/acquire_dialog.rb +640 -0
  67. data/lib/alexandria/ui/dialogs/alert_dialog.rb +68 -0
  68. data/lib/alexandria/ui/dialogs/bad_isbns_dialog.rb +43 -0
  69. data/lib/alexandria/ui/dialogs/barcode_animation.rb +159 -0
  70. data/lib/alexandria/ui/dialogs/book_properties_dialog.rb +210 -0
  71. data/lib/alexandria/ui/dialogs/book_properties_dialog_base.rb +432 -0
  72. data/lib/alexandria/ui/dialogs/export_dialog.rb +172 -0
  73. data/lib/alexandria/ui/dialogs/import_dialog.rb +205 -0
  74. data/lib/alexandria/ui/dialogs/misc_dialogs.rb +85 -0
  75. data/lib/alexandria/ui/dialogs/new_book_dialog.rb +639 -0
  76. data/lib/alexandria/ui/dialogs/new_book_dialog_manual.rb +153 -0
  77. data/lib/alexandria/ui/dialogs/new_smart_library_dialog.rb +67 -0
  78. data/lib/alexandria/ui/dialogs/preferences_dialog.rb +587 -0
  79. data/lib/alexandria/ui/dialogs/smart_library_properties_dialog.rb +56 -0
  80. data/lib/alexandria/ui/dialogs/smart_library_properties_dialog_base.rb +432 -0
  81. data/lib/alexandria/ui/dndable.rb +81 -0
  82. data/lib/alexandria/ui/gtk_thread_help.rb +88 -0
  83. data/lib/alexandria/ui/icons.rb +100 -0
  84. data/lib/alexandria/ui/iconview.rb +91 -0
  85. data/lib/alexandria/ui/iconview_tooltips.rb +162 -0
  86. data/lib/alexandria/ui/init.rb +93 -0
  87. data/lib/alexandria/ui/libraries_combo.rb +75 -0
  88. data/lib/alexandria/ui/listview.rb +310 -0
  89. data/lib/alexandria/ui/main_app.rb +67 -0
  90. data/lib/alexandria/ui/multi_drag_treeview.rb +150 -0
  91. data/lib/alexandria/ui/sidepane.rb +194 -0
  92. data/lib/alexandria/ui/sound.rb +107 -0
  93. data/lib/alexandria/ui/ui_manager.rb +1308 -0
  94. data/lib/alexandria/undo_manager.rb +78 -0
  95. data/lib/alexandria/utils.rb +30 -0
  96. data/lib/alexandria/version.rb +24 -0
  97. data/lib/alexandria/web_themes.rb +75 -0
  98. data/misc/sounds/README +15 -0
  99. data/misc/sounds/bad_scan.csd +62 -0
  100. data/misc/sounds/good_scan.csd +61 -0
  101. data/misc/sounds/scanning.csd +46 -0
  102. data/po/ChangeLog +488 -0
  103. data/po/Makefile +44 -0
  104. data/po/README +29 -0
  105. data/po/commit-po +72 -0
  106. data/po/cs.po +1437 -0
  107. data/po/cy.po +1521 -0
  108. data/po/de.po +1400 -0
  109. data/po/el.po +1379 -0
  110. data/po/es.po +1376 -0
  111. data/po/fr.po +1420 -0
  112. data/po/ga.po +1359 -0
  113. data/po/gl.po +1397 -0
  114. data/po/it.po +1406 -0
  115. data/po/ja.po +1355 -0
  116. data/po/mk.po +1373 -0
  117. data/po/nb.po +1386 -0
  118. data/po/nl.po +1405 -0
  119. data/po/pl.po +1373 -0
  120. data/po/pt.po +1398 -0
  121. data/po/pt_BR.po +1409 -0
  122. data/po/ru.po +1372 -0
  123. data/po/sk.po +1380 -0
  124. data/po/sv.po +1402 -0
  125. data/po/uk.po +1423 -0
  126. data/po/zh_TW.po +1394 -0
  127. data/schemas/alexandria.schemas +300 -0
  128. data/share/alexandria/glade/acquire_dialog__builder.glade +201 -0
  129. data/share/alexandria/glade/book_properties_dialog__builder.glade +910 -0
  130. data/share/alexandria/glade/main_app__builder.glade +229 -0
  131. data/share/alexandria/glade/new_book_dialog__builder.glade +379 -0
  132. data/share/alexandria/glade/preferences_dialog__builder.glade +733 -0
  133. data/share/alexandria/icons/alexandria.png +0 -0
  134. data/share/alexandria/icons/alexandria_small.png +0 -0
  135. data/share/alexandria/icons/book.png +0 -0
  136. data/share/alexandria/icons/book_icon.png +0 -0
  137. data/share/alexandria/icons/book_small.png +0 -0
  138. data/share/alexandria/icons/cuecat.png +0 -0
  139. data/share/alexandria/icons/cuecat_inactive.png +0 -0
  140. data/share/alexandria/icons/favorite_tag.png +0 -0
  141. data/share/alexandria/icons/less.png +0 -0
  142. data/share/alexandria/icons/library.png +0 -0
  143. data/share/alexandria/icons/library_small.png +0 -0
  144. data/share/alexandria/icons/lookup.png +0 -0
  145. data/share/alexandria/icons/more.png +0 -0
  146. data/share/alexandria/icons/no_cover.png +0 -0
  147. data/share/alexandria/icons/smart_library.png +0 -0
  148. data/share/alexandria/icons/smart_library_small.png +0 -0
  149. data/share/alexandria/icons/star_set.png +0 -0
  150. data/share/alexandria/icons/star_unset.png +0 -0
  151. data/share/alexandria/icons/view_as_icons.png +0 -0
  152. data/share/alexandria/icons/view_as_list.png +0 -0
  153. data/share/alexandria/ui/menus.xml +91 -0
  154. data/share/alexandria/ui/popups.xml +91 -0
  155. data/share/alexandria/web-themes/clean/clean.css +85 -0
  156. data/share/alexandria/web-themes/clean/preview.jpg +0 -0
  157. data/share/alexandria/web-themes/list/list.css +105 -0
  158. data/share/alexandria/web-themes/list/preview.jpg +0 -0
  159. data/share/app-icon/16x16/alexandria.png +0 -0
  160. data/share/app-icon/16x16/alexandria.svg +263 -0
  161. data/share/app-icon/22x22/alexandria.png +0 -0
  162. data/share/app-icon/22x22/alexandria.svg +465 -0
  163. data/share/app-icon/24x24/alexandria.png +0 -0
  164. data/share/app-icon/32x32/alexandria.png +0 -0
  165. data/share/app-icon/32x32/alexandria.svg +813 -0
  166. data/share/app-icon/32x32/alexandria.xpm +241 -0
  167. data/share/app-icon/48x48/alexandria.png +0 -0
  168. data/share/app-icon/scalable/alexandria.svg +700 -0
  169. data/share/gnome/help/alexandria/C/about.xml +44 -0
  170. data/share/gnome/help/alexandria/C/adding-books.xml +339 -0
  171. data/share/gnome/help/alexandria/C/alexandria.xml +185 -0
  172. data/share/gnome/help/alexandria/C/bugs.xml +18 -0
  173. data/share/gnome/help/alexandria/C/editing-book-properties.xml +124 -0
  174. data/share/gnome/help/alexandria/C/exporting.xml +81 -0
  175. data/share/gnome/help/alexandria/C/figures/adding_books_acquire_from_scanner_process.png +0 -0
  176. data/share/gnome/help/alexandria/C/figures/adding_books_add_by_isbn.png +0 -0
  177. data/share/gnome/help/alexandria/C/figures/adding_books_isbn_import.png +0 -0
  178. data/share/gnome/help/alexandria/C/figures/adding_books_manual_details.png +0 -0
  179. data/share/gnome/help/alexandria/C/figures/adding_books_rename_library_after_import.png +0 -0
  180. data/share/gnome/help/alexandria/C/figures/adding_books_search_results.png +0 -0
  181. data/share/gnome/help/alexandria/C/figures/editing_book_properties_info.png +0 -0
  182. data/share/gnome/help/alexandria/C/figures/editing_book_properties_loaning.png +0 -0
  183. data/share/gnome/help/alexandria/C/figures/exporting_information_html.png +0 -0
  184. data/share/gnome/help/alexandria/C/figures/getting_started_first_launched.png +0 -0
  185. data/share/gnome/help/alexandria/C/figures/searching_filtering_views_list_view.png +0 -0
  186. data/share/gnome/help/alexandria/C/figures/searching_filtering_views_list_view_search.png +0 -0
  187. data/share/gnome/help/alexandria/C/figures/settings_providers_new_z3950.png +0 -0
  188. data/share/gnome/help/alexandria/C/figures/smart_libraries_new_smart_library.png +0 -0
  189. data/share/gnome/help/alexandria/C/figures/working_with_libraries_library_pane.png +0 -0
  190. data/share/gnome/help/alexandria/C/getting-started.xml +154 -0
  191. data/share/gnome/help/alexandria/C/gnu-fdl-1.2.xml +543 -0
  192. data/share/gnome/help/alexandria/C/introduction.xml +142 -0
  193. data/share/gnome/help/alexandria/C/searching.xml +90 -0
  194. data/share/gnome/help/alexandria/C/settings.xml +140 -0
  195. data/share/gnome/help/alexandria/C/smart-libraries.xml +160 -0
  196. data/share/gnome/help/alexandria/C/working-with-libraries.xml +76 -0
  197. data/share/gnome/help/alexandria/ChangeLog +99 -0
  198. data/share/gnome/help/alexandria/fr/alexandria.xml +2292 -0
  199. data/share/gnome/help/alexandria/fr/figures/alexandria_add_button.png +0 -0
  200. data/share/gnome/help/alexandria/fr/figures/alexandria_add_by_isbn_1.png +0 -0
  201. data/share/gnome/help/alexandria/fr/figures/alexandria_add_by_search_1.png +0 -0
  202. data/share/gnome/help/alexandria/fr/figures/alexandria_add_manually.png +0 -0
  203. data/share/gnome/help/alexandria/fr/figures/alexandria_add_z3950.png +0 -0
  204. data/share/gnome/help/alexandria/fr/figures/alexandria_close_button.png +0 -0
  205. data/share/gnome/help/alexandria/fr/figures/alexandria_edit_info.png +0 -0
  206. data/share/gnome/help/alexandria/fr/figures/alexandria_export_web_page.png +0 -0
  207. data/share/gnome/help/alexandria/fr/figures/alexandria_importing.png +0 -0
  208. data/share/gnome/help/alexandria/fr/figures/alexandria_library_pane.png +0 -0
  209. data/share/gnome/help/alexandria/fr/figures/alexandria_list_view.png +0 -0
  210. data/share/gnome/help/alexandria/fr/figures/alexandria_list_view_search.png +0 -0
  211. data/share/gnome/help/alexandria/fr/figures/alexandria_loaning.png +0 -0
  212. data/share/gnome/help/alexandria/fr/figures/alexandria_main_window.png +0 -0
  213. data/share/gnome/help/alexandria/fr/figures/alexandria_remove_button.png +0 -0
  214. data/share/gnome/help/alexandria/ja/about.xml +33 -0
  215. data/share/gnome/help/alexandria/ja/adding-books.xml +314 -0
  216. data/share/gnome/help/alexandria/ja/alexandria.xml +172 -0
  217. data/share/gnome/help/alexandria/ja/bugs.xml +11 -0
  218. data/share/gnome/help/alexandria/ja/editing-book-properties.xml +100 -0
  219. data/share/gnome/help/alexandria/ja/exporting.xml +98 -0
  220. data/share/gnome/help/alexandria/ja/figures/adding_books_acquire_from_scanner_process.png +0 -0
  221. data/share/gnome/help/alexandria/ja/figures/adding_books_add_by_isbn.png +0 -0
  222. data/share/gnome/help/alexandria/ja/figures/adding_books_isbn_import.png +0 -0
  223. data/share/gnome/help/alexandria/ja/figures/adding_books_manual_details.png +0 -0
  224. data/share/gnome/help/alexandria/ja/figures/adding_books_rename_library_after_import.png +0 -0
  225. data/share/gnome/help/alexandria/ja/figures/adding_books_search_results.png +0 -0
  226. data/share/gnome/help/alexandria/ja/figures/editing_book_properties_info.png +0 -0
  227. data/share/gnome/help/alexandria/ja/figures/editing_book_properties_loaning.png +0 -0
  228. data/share/gnome/help/alexandria/ja/figures/exporting_information_html.png +0 -0
  229. data/share/gnome/help/alexandria/ja/figures/getting_started_first_launched.png +0 -0
  230. data/share/gnome/help/alexandria/ja/figures/searching_filtering_views_list_view.png +0 -0
  231. data/share/gnome/help/alexandria/ja/figures/searching_filtering_views_list_view_search.png +0 -0
  232. data/share/gnome/help/alexandria/ja/figures/settings_providers_new_z3950.png +0 -0
  233. data/share/gnome/help/alexandria/ja/figures/smart_libraries_new_smart_library.png +0 -0
  234. data/share/gnome/help/alexandria/ja/figures/working_with_libraries_library_pane.png +0 -0
  235. data/share/gnome/help/alexandria/ja/getting-started.xml +144 -0
  236. data/share/gnome/help/alexandria/ja/gnu-fdl-1.2.xml +541 -0
  237. data/share/gnome/help/alexandria/ja/introduction.xml +134 -0
  238. data/share/gnome/help/alexandria/ja/searching.xml +104 -0
  239. data/share/gnome/help/alexandria/ja/settings.xml +129 -0
  240. data/share/gnome/help/alexandria/ja/smart-libraries.xml +140 -0
  241. data/share/gnome/help/alexandria/ja/working-with-libraries.xml +88 -0
  242. data/share/menu/alexandria +7 -0
  243. data/share/omf/alexandria/alexandria-C.omf.in +27 -0
  244. data/share/omf/alexandria/alexandria-fr.omf.in +30 -0
  245. data/share/sounds/alexandria/bad_scan.ogg +0 -0
  246. data/share/sounds/alexandria/bad_scan.wav +0 -0
  247. data/share/sounds/alexandria/good_scan.ogg +0 -0
  248. data/share/sounds/alexandria/good_scan.wav +0 -0
  249. data/share/sounds/alexandria/scanning.ogg +0 -0
  250. data/share/sounds/alexandria/scanning.wav +0 -0
  251. data/spec/alexandria/library_spec.rb +205 -0
  252. data/spec/alexandria/preferences_spec.rb +22 -0
  253. data/spec/alexandria/scanners/cuecat_spec.rb +68 -0
  254. data/spec/alexandria/smart_library_spec.rb +22 -0
  255. data/spec/alexandria/ui/dialogs_spec.rb +90 -0
  256. data/spec/alexandria/ui/iconview_spec.rb +27 -0
  257. data/spec/alexandria/ui/listview_spec.rb +28 -0
  258. data/spec/alexandria/ui/main_app_spec.rb +48 -0
  259. data/spec/alexandria/ui/sidepane_spec.rb +27 -0
  260. data/spec/alexandria/ui/ui_manager_spec.rb +26 -0
  261. data/spec/alexandria/ui/ui_utilities_spec.rb +60 -0
  262. data/spec/alexandria/utilities_spec.rb +50 -0
  263. data/spec/data/libraries/0.6.1-noisbn/My Library/0201398257.yaml +10 -0
  264. data/spec/data/libraries/0.6.1-noisbn/My Library/1565920007.yaml +10 -0
  265. data/spec/data/libraries/0.6.1/My Library/0192812173.yaml +9 -0
  266. data/spec/data/libraries/0.6.1/My Library/0201398257.cover +0 -0
  267. data/spec/data/libraries/0.6.1/My Library/0201398257.yaml +10 -0
  268. data/spec/data/libraries/0.6.1/My Library/1565920007.yaml +10 -0
  269. data/spec/data/libraries/0.6.2/My Library/9780140266146.cover +0 -0
  270. data/spec/data/libraries/0.6.2/My Library/9780140266146.yaml +16 -0
  271. data/spec/data/libraries/0.6.2/My Library/9780140278781.cover +0 -0
  272. data/spec/data/libraries/0.6.2/My Library/9780140278781.yaml +21 -0
  273. data/spec/data/libraries/0.6.2/My Library/9780571147168.cover +0 -0
  274. data/spec/data/libraries/0.6.2/My Library/9780571147168.yaml +20 -0
  275. data/spec/data/libraries/0.6.2/My Library/9780575079038.cover +0 -0
  276. data/spec/data/libraries/0.6.2/My Library/9780575079038.yaml +20 -0
  277. data/spec/data/libraries/0.6.2/My Library/9780755322800.cover +0 -0
  278. data/spec/data/libraries/0.6.2/My Library/9780755322800.yaml +20 -0
  279. data/spec/spec_helper.rb +46 -0
  280. data/tasks/rdoc.rake +6 -0
  281. data/tasks/setup.rb +30 -0
  282. data/tasks/spec.rake +29 -0
  283. data/tasks/test.rake +38 -0
  284. data/test/application_test.rb +39 -0
  285. data/test/book_test.rb +34 -0
  286. data/test/data/isbns.txt +3 -0
  287. data/test/isbn_test.rb +68 -0
  288. data/test/providers_test.rb +254 -0
  289. data/test/test_helper.rb +42 -0
  290. data/util/rake/fileinstall.rb +313 -0
  291. data/util/rake/gettextgenerate.rb +158 -0
  292. data/util/rake/omfgenerate.rb +79 -0
  293. metadata +452 -0
@@ -0,0 +1,42 @@
1
+ #!/usr/bin/env ruby
2
+ # Copyright (C) 2011, 2014 Matijs van Zuijlen
3
+ # Incorporates code Copyright (C) 2007 Joseph Method
4
+ #
5
+ # This file is part of Alexandria, a GNOME book collection manager.
6
+ #
7
+ # Alexandria is free software; you can redistribute it and/or
8
+ # modify it under the terms of the GNU General Public License as
9
+ # published by the Free Software Foundation; either version 2 of the
10
+ # License, or (at your option) any later version.
11
+ #
12
+ # Alexandria is distributed in the hope that it will be useful,
13
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15
+ # General Public License for more details.
16
+ #
17
+ # You should have received a copy of the GNU General Public
18
+ # License along with Alexandria; see the file COPYING. If not,
19
+ # write to the Free Software Foundation, Inc., 51 Franklin Street,
20
+ # Fifth Floor, Boston, MA 02110-1301 USA.
21
+
22
+ require 'minitest/autorun'
23
+
24
+ require 'gettext'
25
+ require 'alexandria'
26
+
27
+ LIBDIR = File.expand_path(File.join(File.dirname(__FILE__), '/data/libraries'))
28
+ TESTDIR = File.join(LIBDIR, 'test')
29
+
30
+ def an_artist_of_the_floating_world
31
+ Alexandria::Book.new('An Artist of the Floating World',
32
+ 'Kazuo Ishiguro',
33
+ '9780571147168',
34
+ 'Faber and Faber', 1999,
35
+ 'Paperback')
36
+ end
37
+
38
+ module Alexandria
39
+ class Library
40
+ DIR.replace TESTDIR
41
+ end
42
+ end
@@ -0,0 +1,313 @@
1
+ # -*- ruby -*-
2
+ #--
3
+ # Copyright (C) 2009 Cathal Mc Ginley
4
+ # Modifications Copyright (C) 2011 Matijs van Zuijlen
5
+ #
6
+ # This file is part of the Alexandria build system.
7
+ #
8
+ # Permission is hereby granted, free of charge, to any person obtaining
9
+ # a copy of this software and associated documentation files (the
10
+ # "Software"), to deal in the Software without restriction, including
11
+ # without limitation the rights to use, copy, modify, merge, publish,
12
+ # distribute, sublicense, and/or sell copies of the Software, and to
13
+ # permit persons to whom the Software is furnished to do so, subject to
14
+ # the following conditions:
15
+ #
16
+ # The above copyright notice and this permission notice shall be
17
+ # included in all copies or substantial portions of the Software.
18
+ #
19
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
22
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
23
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
24
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
25
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26
+ #++
27
+
28
+ require 'fileutils'
29
+ require 'pathname'
30
+ require 'set'
31
+ require 'rake/tasklib'
32
+
33
+ # A file installer task, capable of installing into the system
34
+ # directories, or doing a staged install to a given directory
35
+ # (preparatory to bundling the installed files in a binary package
36
+ # such as deb or rpm).
37
+ class FileInstallTask < Rake::TaskLib
38
+ # The calculated location of the preferred ruby lib installation dir.
39
+ attr_reader :rubylib
40
+
41
+ # Creates an installer task with the given +taskname+. If a
42
+ # +dirname+ is given, the task will perform a staged installation to
43
+ # that directory with a correct sub-tree e.g. 'tmp/usr/bin',
44
+ # 'tmp/usr/share/doc/packagename'.
45
+ #
46
+ # This constructor is called with a block, which is passed the
47
+ # installer task. You should call +install+ or +install_exe+ on that
48
+ # installer as follows:
49
+ #
50
+ # FileInstallTask.new(:install) do |i|
51
+ # i.install('lib', 'lib/**/*.rb', i.rubylib)
52
+ # i.install_exe('bin', 'bin/*', '/usr/bin')
53
+ # end
54
+ #
55
+ # If you set +install_to_rubylibdir+ true, or specify the
56
+ # +RUBYLIBDIR+ environment variable, you can ensure the files are
57
+ # installed in the correct place for staged installation, e.g. on
58
+ # Debian, set +dirname+ to 'debian/packagename' and
59
+ # +install_to_rubylibdir+ to true so that files are stage-installed
60
+ # to 'debian/packagename/usr/lib/ruby/1.8'
61
+ def initialize(taskname, dirname = nil, install_to_rubylibdir = false)
62
+ @taskname = taskname
63
+ @install_to_rubylibdir = install_to_rubylibdir
64
+ calculate_ruby_dir
65
+ @stage_dir = dirname # || @prefix
66
+ @file_groups = []
67
+ @dirs_to_remove_globs = []
68
+ if block_given?
69
+ yield self
70
+ end
71
+ make_tasks
72
+ end
73
+
74
+ protected
75
+
76
+ # Creates the install and uninstall tasks based on the contents
77
+ # of the @file_groups list
78
+ def make_tasks
79
+ tasknames = {}
80
+ tasknames[:install] = "install_#{@taskname}".intern
81
+ tasknames[:uninstall] = "uninstall_#{@taskname}".intern
82
+ tasknames[:uninstall_files] = "uninstall_#{@taskname}_files".intern
83
+ tasknames[:uninstall_dirs] = "uninstall_#{@taskname}_dirs".intern
84
+
85
+ # INSTALL TASK
86
+
87
+ description = 'Install package files'
88
+ if @stage_dir
89
+ description += ' to staging directory'
90
+ end
91
+ desc description
92
+ task tasknames[:install] do
93
+ @file_groups.each { |g| g.install(@stage_dir) }
94
+ end
95
+
96
+ # UNINSTALL TASKS
97
+
98
+ task tasknames[:uninstall_files] do
99
+ @file_groups.each { |g| g.uninstall(@stage_dir) }
100
+ end
101
+
102
+ task tasknames[:uninstall_dirs] => tasknames[:uninstall_files] do
103
+ all_dirs = Set.new
104
+ @file_groups.each { |g| g.get_installation_dirs(@stage_dir, all_dirs) }
105
+
106
+ to_delete = Set.new
107
+ @dirs_to_remove_globs.each do |glob|
108
+ regex = glob2regex(glob)
109
+ all_dirs.each do |dir|
110
+ unless dir =~ /\/$/
111
+ dir += '/'
112
+ end
113
+ if regex =~ dir
114
+ to_delete << Regexp.last_match[1]
115
+ end
116
+ end
117
+ end
118
+ to_delete.each do |dirname|
119
+ dir = dirname
120
+ if @stage_dir
121
+ dir = File.join(@stage_dir, dirname)
122
+ end
123
+ delete_empty(dir)
124
+ end
125
+ end
126
+
127
+ uninstall_description = 'Uninstall package files'
128
+ if @stage_dir
129
+ uninstall_description += ' from staging directory'
130
+ end
131
+ desc uninstall_description
132
+ task tasknames[:uninstall] => [tasknames[:uninstall_files],
133
+ tasknames[:uninstall_dirs]]
134
+ end
135
+
136
+ public
137
+
138
+ # Include the files specified in the +file_glob+ to be installed in
139
+ # +dest_dir+, but noting that the prefix +src_dir+ is to be
140
+ # disregarded in the installation.
141
+ #
142
+ # This means that
143
+ # i.install('data', 'data/gnome/**', '/usr/share')
144
+ # would install files in the 'data/gnome/help' directory to
145
+ # '/usr/share/gnome/help'
146
+ def install(src_dir, file_glob, dest_dir)
147
+ @file_groups << FileGroup.new(src_dir, file_glob, dest_dir)
148
+ end
149
+
150
+ # Install files the same way as +install+, but setting the mode of
151
+ # the installed file to be executable.
152
+ def install_exe(src_dir, file_glob, dest_dir)
153
+ @file_groups << FileGroup.new(src_dir, file_glob, dest_dir, 0755)
154
+ end
155
+
156
+ # Install icon files. This method splits up the source file name and
157
+ # determines where they should be put in the destination hierarchy.
158
+ def install_icons(file_globs, dest_dir, theme = 'hicolor', icon_type = 'apps')
159
+ file_globs.each do |fg|
160
+ files = FileList.new(fg)
161
+ files.each do |f|
162
+ icon_file = Pathname.new(f)
163
+ icon_dir = icon_file.dirname
164
+ icon_size = Pathname.new(icon_dir).basename
165
+ icon_dest_dir = "#{dest_dir}/#{theme}/#{icon_size}/#{icon_type}"
166
+ group = FileGroup.new(icon_dir, f, icon_dest_dir)
167
+ group.description = 'icons'
168
+ @file_groups << group
169
+ end
170
+ end
171
+ end
172
+
173
+ # Specify which directories should be deleted by the uninstall task
174
+ # if they are empty (or only contain more empty directories).
175
+ def uninstall_empty_dirs(dir_globs)
176
+ @dirs_to_remove_globs = dir_globs
177
+ end
178
+
179
+ private
180
+
181
+ def calculate_ruby_dir
182
+ ruby_prefix = RbConfig::CONFIG['prefix']
183
+
184
+ if @install_to_rubylibdir
185
+ ruby_libdir = RbConfig::CONFIG['rubylibdir']
186
+ else
187
+ ruby_libdir = RbConfig::CONFIG['sitelibdir']
188
+ end
189
+ if ENV.key?('RUBYLIBDIR')
190
+ ruby_libdir = ENV['RUBYLIBDIR']
191
+ end
192
+
193
+ @prefix = ENV['PREFIX'] || ruby_prefix
194
+ if @prefix == ruby_prefix
195
+ @rubylib = ruby_libdir
196
+ elsif ruby_libdir.index(ruby_prefix) == 0
197
+ libpart = ruby_libdir[ruby_prefix.size..-1]
198
+ @rubylib = File.join(@prefix, libpart)
199
+ else
200
+ @rubylib = ruby_libdir
201
+ end
202
+ end
203
+
204
+ def glob2regex(pathglob)
205
+ if pathglob =~ /\*\*$/
206
+ pathglob += '/'
207
+ end
208
+ real_parts = pathglob.split('**/')
209
+ real_parts.each do |part|
210
+ part.gsub!('.', '\\.')
211
+ part.gsub!('*', '[^\\/]*')
212
+ part.gsub!('?', '[^\\/]')
213
+ end
214
+ pattern = real_parts.join("([^\/]+\/)*")
215
+ /(#{pattern})/
216
+ end
217
+
218
+ # For each of the directories named in the list +dirs+, delete the
219
+ # tree if is empty except for further empty directories.
220
+ def delete_empty(dirs)
221
+ dirs.each do |d|
222
+ p = Pathname.new(d)
223
+ if p.exist?
224
+ delete_if_empty(p.realpath)
225
+ end
226
+ end
227
+ end
228
+
229
+ # Delete the directory at the given Pathname +p+ if all its children
230
+ # can be similarly deleted, and if it is then empty.
231
+ def delete_if_empty(p)
232
+ unless p.directory?
233
+ return false
234
+ end
235
+ p.children.each do |c|
236
+ delete_if_empty(c)
237
+ end
238
+ if p.children.empty?
239
+ p.delete # TODO optional verbose output here
240
+ true
241
+ else
242
+ false
243
+ end
244
+ end
245
+
246
+ class FileGroup
247
+ attr_reader :mode
248
+ attr_accessor :description
249
+ def initialize(src_dir, file_glob, dest_dir, mode = 0644)
250
+ @src_dir = src_dir
251
+ @file_glob = file_glob
252
+ @dest_dir = dest_dir
253
+ @mode = mode
254
+ @description = 'files'
255
+ end
256
+
257
+ def to_s
258
+ "FileGroup[#{@src_dir}] => #{@dest_dir}"
259
+ end
260
+
261
+ def dest_dir(file, staging_dir = nil)
262
+ source_basedir = Pathname.new(@src_dir)
263
+ source_file = Pathname.new(file)
264
+
265
+ if staging_dir
266
+ stage_dest = File.join(staging_dir, @dest_dir)
267
+ dest_basedir = Pathname.new(stage_dest)
268
+ else
269
+ dest_basedir = Pathname.new(@dest_dir)
270
+ end
271
+ if source_file.file?
272
+ source_path = source_file.dirname.relative_path_from(source_basedir)
273
+ end
274
+ dest = source_path ? dest_basedir + source_path : dest_basedir
275
+ dest.to_s
276
+ end
277
+
278
+ def files
279
+ FileList.new(@file_glob)
280
+ end
281
+
282
+ def install(base_dir)
283
+ puts "Installing #{@description} to #{base_dir}#{@dest_dir}"
284
+ files.each do |f|
285
+ dest = dest_dir(f, base_dir)
286
+ FileUtils.mkdir_p(dest) unless test('d', dest)
287
+ if test('f', f)
288
+ FileUtils.install(f, dest, mode: mode)
289
+ end
290
+ end
291
+ end
292
+
293
+ def uninstall(base_dir)
294
+ files.each do |f|
295
+ dest = dest_dir(f, base_dir)
296
+ filename = File.basename(f)
297
+ file = File.join(dest, filename)
298
+ if test('f', file)
299
+ FileUtils::Verbose.rm_f(file) # , :noop => true)
300
+ end
301
+ end
302
+ end
303
+
304
+ def get_installation_dirs(base_dir, all_dirs_set)
305
+ files.each do |f|
306
+ dest = dest_dir(f, base_dir)
307
+ filename = File.basename(f)
308
+ file = File.join(dest, filename)
309
+ all_dirs_set << File.dirname(file)
310
+ end
311
+ end
312
+ end # class FileGroup
313
+ end # class FileInstallTask
@@ -0,0 +1,158 @@
1
+ # -*- ruby -*-
2
+ #--
3
+ # Copyright (C) 2009 Cathal Mc Ginley
4
+ #
5
+ # This file is part of the Alexandria build system.
6
+ #
7
+ # Permission is hereby granted, free of charge, to any person obtaining
8
+ # a copy of this software and associated documentation files (the
9
+ # "Software"), to deal in the Software without restriction, including
10
+ # without limitation the rights to use, copy, modify, merge, publish,
11
+ # distribute, sublicense, and/or sell copies of the Software, and to
12
+ # permit persons to whom the Software is furnished to do so, subject to
13
+ # the following conditions:
14
+ #
15
+ # The above copyright notice and this permission notice shall be
16
+ # included in all copies or substantial portions of the Software.
17
+ #
18
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
22
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
24
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25
+ #++
26
+
27
+ require 'fileutils'
28
+ require 'pathname'
29
+ require 'rake/tasklib'
30
+
31
+ class GettextGenerateTask < Rake::TaskLib
32
+ def initialize(projectname)
33
+ @projectname = projectname
34
+ @generated_files = []
35
+ if block_given?
36
+ yield self
37
+ end
38
+ make_task
39
+ end
40
+
41
+ def make_task
42
+ desc 'Generate gettext localization files'
43
+ task gettext: @generated_files
44
+
45
+ if CLOBBER
46
+ @generated_files.each { |gen| CLOBBER << gen }
47
+ end
48
+ end
49
+
50
+ def generate_po_files(po_dir, file_glob, dest_dir)
51
+ @po_dir = po_dir
52
+ @po_files_glob = file_glob
53
+ @mo_dir = dest_dir
54
+ @mo_files_regex = /.*\/(.+)\/LC_MESSAGES\/.+\.mo/
55
+
56
+ # create MO files
57
+ rule(/\.mo$/ => [->(dest) { source_file(dest) }]) do |t|
58
+ dest_dir = File.dirname(t.name)
59
+ FileUtils.makedirs(dest_dir) unless FileTest.exists?(dest_dir)
60
+ puts "Generating #{t.name}"
61
+ system("msgfmt #{t.source} -o #{t.name}")
62
+ raise "msgfmt failed for #{t.source}" if $CHILD_STATUS != 0
63
+ end
64
+ mo_files.each { |mo| @generated_files << mo }
65
+ end
66
+
67
+ def po_files
68
+ FileList[@po_files_glob]
69
+ end
70
+
71
+ def generate_desktop(infile, outfile)
72
+ @generated_files << outfile
73
+ file outfile => [infile, *po_files] do |_f|
74
+ unless `intltool-merge --version`
75
+ raise Exception, 'Need to install intltool'
76
+ end
77
+ system("intltool-merge -d #{@po_dir} #{infile} #{outfile}")
78
+ end
79
+ end
80
+
81
+ def locales
82
+ po_files.map { |po| File.basename(po).split('.')[0] }
83
+ end
84
+
85
+ def mo_files
86
+ locales.map { |loc| mo_file_for(loc) }
87
+ end
88
+
89
+ def po_file_for(locale)
90
+ "#{@po_dir}/#{locale}.po"
91
+ end
92
+
93
+ def mo_file_for(locale)
94
+ "#{@mo_dir}/#{locale}/LC_MESSAGES/#{@projectname}.mo"
95
+ end
96
+
97
+ def source_file(dest_file)
98
+ dest_file =~ @mo_files_regex
99
+ po_file_for(Regexp.last_match[1])
100
+ end
101
+ end
102
+
103
+ # class GettextConfig < BuildConfig
104
+ # attr_accessor :po_dir, :po_files_glob
105
+ # attr_accessor :mo_dir, :mo_files_regex
106
+ # def initialize(build)
107
+ # super(build)
108
+ # @po_dir = 'po'
109
+ # @po_files_glob = "#{@po_dir}/*.po"
110
+ # @mo_dir = 'data/locale'
111
+ # @mo_files_regex = /.*\/(.+)\/LC_MESSAGES\/.+\.mo/
112
+ # end
113
+ # def po_files
114
+ # FileList[po_files_glob]
115
+ # end
116
+ # def po_file_for(locale)
117
+ # "#{po_dir}/#{locale}.po"
118
+ # end
119
+ # def locales
120
+ # po_files.map { |po| File.basename(po).split('.')[0] }
121
+ # end
122
+ # def mo_files
123
+ # locales.map { |loc| mo_file_for(loc) }
124
+ # end
125
+ # def mo_file_for(locale)
126
+ # "#{mo_dir}/#{locale}/LC_MESSAGES/#{build.name}.mo"
127
+ # end
128
+ # def source_file(dest_file)
129
+ # dest_file =~ mo_files_regex
130
+ # po_file_for($1)
131
+ # end
132
+ # end
133
+
134
+ # def define_gettext_tasks
135
+ # # extract translations from PO files into other files
136
+ # file files.desktop => ["#{files.desktop}.in",
137
+ # *@gettext.po_files] do |f|
138
+ # raise "Need to install intltool" unless system("intltool-merge -d #{@gettext.po_dir} #{f.name}.in #{f.name}")
139
+ # end
140
+
141
+ # # create MO files
142
+ # rule( /\.mo$/ => [ lambda { |dest| @gettext.source_file(dest) }]) do |t|
143
+ # dest_dir = File.dirname(t.name)
144
+ # FileUtils.makedirs(dest_dir) unless FileTest.exists?(dest_dir)
145
+ # puts "Generating #{t.name}"
146
+ # system("msgfmt #{t.source} -o #{t.name}")
147
+ # raise "msgfmt failed for #{t.source}" if $? != 0
148
+ # end
149
+
150
+ # desc "Generate gettext localization files"
151
+ # task :gettext => [files.desktop, *@gettext.mo_files]
152
+
153
+ # task :clobber_gettext do
154
+ # FileUtils.rm_f(files.desktop)
155
+ # FileUtils.rm_rf(@gettext.mo_dir)
156
+ # end
157
+ # task :clobber => [:clobber_gettext]
158
+ # end