<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" /><style type="text/css"><!--
#msg dl { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fc0 solid; padding: 6px; }
#msg ul, pre { overflow: auto; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<title>[653] trunk/alexandria/lib/alexandria: BACKUP LIBRARY FOR NOW</title>
</head>
<body>

<div id="msg">
<dl>
<dt>Revision</dt> <dd>653</dd>
<dt>Author</dt> <dd>method</dd>
<dt>Date</dt> <dd>2007-03-12 23:52:46 -0400 (Mon, 12 Mar 2007)</dd>
</dl>

<h3>Log Message</h3>
<pre>BACKUP LIBRARY FOR NOW

- Should be okay, but might lose a cover.
- Tries to coerce all books to ean
- Additional code that has been neutralized.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkalexandrialibalexandrialibraryrb">trunk/alexandria/lib/alexandria/library.rb</a></li>
<li><a href="#trunkalexandrialibalexandriauimain_apprb">trunk/alexandria/lib/alexandria/ui/main_app.rb</a></li>
<li><a href="#trunkalexandrialibalexandriauinew_book_dialogrb">trunk/alexandria/lib/alexandria/ui/new_book_dialog.rb</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkalexandrialibalexandrialibraryrb"></a>
<div class="modfile"><h4>Modified: trunk/alexandria/lib/alexandria/library.rb (652 => 653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/alexandria/lib/alexandria/library.rb        2007-03-12 09:31:13 UTC (rev 652)
+++ trunk/alexandria/lib/alexandria/library.rb        2007-03-13 03:52:46 UTC (rev 653)
</span><span class="lines">@@ -33,6 +33,7 @@
</span><span class="cx"> module Alexandria
</span><span class="cx">     class Library &lt; Array
</span><span class="cx">         attr_reader :name
</span><ins>+        attr_accessor :ruined_books
</ins><span class="cx">         DIR = File.join(ENV['HOME'], '.alexandria')
</span><span class="cx">         EXT = { :book =&gt; '.yaml', :cover =&gt; '.cover' }
</span><span class="cx">         
</span><span class="lines">@@ -62,7 +63,9 @@
</span><span class="cx"> 
</span><span class="cx">         FIX_BIGNUM_REGEX = 
</span><span class="cx">             /loaned_since:\s*(\!ruby\/object\:Bignum\s*)?(\d+)\n/
</span><ins>+        
</ins><span class="cx">         def self.load(name)
</span><ins>+                ruined_books = []
</ins><span class="cx">             library = Library.new(name)
</span><span class="cx">             FileUtils.mkdir_p(library.path) unless File.exists?(library.path)
</span><span class="cx">             Dir.chdir(library.path) do
</span><span class="lines">@@ -72,11 +75,13 @@
</span><span class="cx">                     #Code to remove the mystery string in books imported from Amazon
</span><span class="cx">                     # (In the past, still?) To allow ruby-amazon to be removed.
</span><span class="cx">                     
</span><ins>+                    # The string is removed on load, but can't make it stick, maybe has to do with cache
+                    
</ins><span class="cx">                     if /!str:Amazon::Search::Response/.match(text)
</span><del>-                            puts text
</del><ins>+                            puts text if $DEBUG
</ins><span class="cx">                             text.gsub!(&quot;!str:Amazon::Search::Response&quot;, &quot;&quot;)
</span><del>-                            puts &quot;got one!&quot;
-                            puts text
</del><ins>+                            puts &quot;got one!&quot; if $DEBUG
+                            puts text if $DEBUG
</ins><span class="cx">                     end
</span><span class="cx">                     
</span><span class="cx">                     # Backward compatibility with versions &lt;= 0.6.0, where the 
</span><span class="lines">@@ -88,24 +93,47 @@
</span><span class="cx">                         text.sub!(md[0], &quot;loaned_since: #{new_yaml}\n&quot;)
</span><span class="cx">                     end
</span><span class="cx">                     book = YAML.load(text)
</span><del>-                        begin 
</del><ins>+                    old_isbn = book.isbn
+                        begin
+                        book.isbn = self.canonicalise_ean(book.isbn).to_s unless book.isbn == nil
+     
</ins><span class="cx">                     raise &quot;Not a book: #{text.inspect}&quot; unless book.is_a?(Book)
</span><del>-                    rescue =&gt; e
-                            puts e.message
-                    end
</del><ins>+                    rescue InvalidISBNError =&gt; e
+                            # ruined_books &lt;&lt; [book, book.isbn, library]
+                            puts e.message if $DEBUG
+                            book.isbn = old_isbn
+                                         end
+                                 
</ins><span class="cx">                     library &lt;&lt; book
</span><span class="cx">                 end
</span><del>-
</del><ins>+                
</ins><span class="cx">                 # Since 0.4.0 the cover files '_small.jpg' and 
</span><span class="cx">                 # '_medium.jpg' have been deprecated for a single medium
</span><span class="cx">                 # cover file named '.cover'.
</span><ins>+                
</ins><span class="cx">                 Dir[&quot;*&quot; + '_medium.jpg'].each do |medium_cover|
</span><span class="cx">                     FileUtils.mv(medium_cover, 
</span><span class="cx">                                  medium_cover.sub(/_medium\.jpg$/,
</span><span class="cx">                                                   EXT[:cover]))
</span><span class="cx">                 end
</span><ins>+                
+                
+                
+                Dir[&quot;*&quot; + EXT[:cover]].each do |cover|
+                        md = /(.+)\.cover/.match(cover)
+                        begin
+                                ean = self.canonicalise_ean(md[1])
+                        rescue
+                                ean = md[1]
+                        end
+                                FileUtils.mv(cover, ean + EXT[:cover]) unless cover == ean + EXT[:cover]
+                end
+                
</ins><span class="cx">                 FileUtils.rm_f(Dir['*_small.jpg'])
</span><span class="cx">             end
</span><ins>+            #puts ruined_books.inspect
+            library.ruined_books = ruined_books
+
</ins><span class="cx">             library
</span><span class="cx">         end
</span><span class="cx">        
</span><span class="lines">@@ -119,14 +147,17 @@
</span><span class="cx">                     next unless File.stat(File.join(DIR, file)).directory?
</span><span class="cx">     
</span><span class="cx">                     a &lt;&lt; self.load(file)       
</span><del>-                end
</del><ins>+                    end
+             
</ins><span class="cx">             rescue Errno::ENOENT
</span><span class="cx">                 FileUtils.mkdir_p(DIR)
</span><span class="cx">             end
</span><span class="cx">             # Create the default library if there is no library yet.
</span><ins>+            
</ins><span class="cx">             if a.empty?
</span><span class="cx">                 a &lt;&lt; self.load(_(&quot;My Library&quot;))
</span><span class="cx">             end
</span><ins>+            
</ins><span class="cx">             return a
</span><span class="cx">         end
</span><span class="cx"> 
</span><span class="lines">@@ -238,7 +269,7 @@
</span><span class="cx">         end
</span><span class="cx"> 
</span><span class="cx">         def self.canonicalise_ean(code)
</span><del>-            code = code.delete('- ')
</del><ins>+            code = code.to_s.delete('- ')
</ins><span class="cx">             if self.valid_ean?(code)
</span><span class="cx">                 return code
</span><span class="cx">             elsif self.valid_isbn?(code)
</span><span class="lines">@@ -276,8 +307,8 @@
</span><span class="cx">             canonical.map { |x| x.to_s }.join()
</span><span class="cx">         end
</span><span class="cx"> 
</span><del>-        def save(book)
-            changed
</del><ins>+        def save(book, final=false)
+            changed unless final
</ins><span class="cx">             
</span><span class="cx">             puts &quot;Saving book #{book.title}...&quot; if $DEBUG
</span><span class="cx">             
</span><span class="lines">@@ -295,11 +326,12 @@
</span><span class="cx">     
</span><span class="cx">                 # Notify before updating the saved identifier, so the views
</span><span class="cx">                 # can still use the old one to update their models.
</span><del>-                notify_observers(self, BOOK_UPDATED, book)
</del><ins>+                notify_observers(self, BOOK_UPDATED, book) unless final
</ins><span class="cx">                 book.saved_ident = book.ident
</span><span class="cx">             end
</span><span class="cx">             already_there = (File.exists?(yaml(book)) and 
</span><span class="cx">                              !@deleted_books.include?(book))
</span><ins>+            
</ins><span class="cx">             puts &quot;Doing the saving deed: #{book.title} -- #{book.isbn}&quot; if $DEBUG
</span><span class="cx">             File.open(yaml(book), &quot;w&quot;) { |io| io.puts book.to_yaml }
</span><span class="cx">             
</span><span class="lines">@@ -354,7 +386,7 @@
</span><span class="cx">                 end
</span><span class="cx">             end
</span><span class="cx">         end
</span><del>- 
</del><ins>+
</ins><span class="cx">         alias_method :old_delete, :delete
</span><span class="cx">         def delete(book=nil)
</span><span class="cx">             if book.nil?
</span><span class="lines">@@ -475,7 +507,7 @@
</span><span class="cx">     end
</span><span class="cx">     
</span><span class="cx">     class Libraries
</span><del>-        attr_reader :all_libraries
</del><ins>+        attr_reader :all_libraries, :ruined_books
</ins><span class="cx"> 
</span><span class="cx">         include Observable
</span><span class="cx">         include Singleton
</span><span class="lines">@@ -484,6 +516,13 @@
</span><span class="cx">             @all_libraries.clear 
</span><span class="cx">             @all_libraries.concat(Library.loadall)
</span><span class="cx">             @all_libraries.concat(SmartLibrary.loadall)
</span><ins>+                   ruined = [] 
+                   last = []
+                   all_regular_libraries.each {|library|
+                                                                           ruined += library.ruined_books 
+                                                                           }        
+                   #puts ruined.inspect
+                   @ruined_books = ruined
</ins><span class="cx">         end
</span><span class="cx"> 
</span><span class="cx">         def all_regular_libraries
</span><span class="lines">@@ -511,6 +550,12 @@
</span><span class="cx">             SmartLibrary.really_delete_deleted_libraries
</span><span class="cx">         end
</span><span class="cx">         
</span><ins>+        def really_save_all_books
+                all_regular_libraries.each do |library|
+                        library.each {|book| library.save(book, true)}        
+                end
+        end
+        
</ins><span class="cx">         #######
</span><span class="cx">         private
</span><span class="cx">         #######
</span></span></pre></div>
<a id="trunkalexandrialibalexandriauimain_apprb"></a>
<div class="modfile"><h4>Modified: trunk/alexandria/lib/alexandria/ui/main_app.rb (652 => 653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/alexandria/lib/alexandria/ui/main_app.rb        2007-03-12 09:31:13 UTC (rev 652)
+++ trunk/alexandria/lib/alexandria/ui/main_app.rb        2007-03-13 03:52:46 UTC (rev 653)
</span><span class="lines">@@ -393,8 +393,46 @@
</span><span class="cx">                 end
</span><span class="cx">                 @libraries.reload
</span><span class="cx">             else
</span><del>-                @libraries = Libraries.instance
</del><ins>+                    #On start

+                @libraries = Libraries.instance 
</ins><span class="cx">                 @libraries.reload
</span><ins>+                unless @libraries.ruined_books.empty?
+                        message = _(&quot;These books do not conform to the ISBN-13 standard. We will attempt to replace them from the book providers. Otherwise, we will turn them into manual entries.\n&quot; )
+                        @libraries.ruined_books.each {|bi| message += &quot;\n#{bi[1] or bi[1].inspect}&quot;}
+                        bad_isbn_warn = Gtk::MessageDialog.new(@main_app, Gtk::Dialog::MODAL, Gtk::MessageDialog::WARNING,  Gtk::MessageDialog::BUTTONS_CLOSE, message ).show
+                        bad_isbn_warn.signal_connect('response') { bad_isbn_warn.destroy }
+                        books_to_add = []
+                        
+                        #This is the restoration thread. We can come up with strategies for restoring 'bad' books here.
+                        
+                        Thread.new do
+                                #Needs a progress indicator.
+                                @libraries.ruined_books.each {|book, isbn, library|
+                                                                                            begin 
+                                                                                            books_to_add &lt;&lt; [Alexandria::BookProviders.isbn_search(isbn.to_s), library].flatten
+                                                                                            puts book.title
+                                                                                           rescue
+                                                                                           
+                                                                                           books_to_add &lt;&lt; [book, nil, library]
+                                                                                            puts &quot;#{book.title} didn't make it.&quot;
+                                                                                            end
+                                                                                         }
+                                # Will crash here when it gets to it.
+                                books_to_add.each do |book, cover_uri, library|
+                                
+                                    unless cover_uri.nil?
+                                        library.save_cover(book, cover_uri)
+                                    end
+                                    
+                                    library &lt;&lt; book
+                                    library.save(book)
+                                    
+                                end
+                        
+                        end
+                             puts books_to_add if $DEBUG
+                end
</ins><span class="cx">             end
</span><span class="cx">             @libraries.all_regular_libraries.each do |library| 
</span><span class="cx">                 library.add_observer(self)
</span><span class="lines">@@ -411,7 +449,9 @@
</span><span class="cx">         ICON_WIDTH = 60
</span><span class="cx">         ICON_HEIGHT = 90         # pixels
</span><span class="cx">         REDUCE_TITLE_REGEX = /^(.{#{ICON_TITLE_MAXLEN}}).*$/
</span><ins>+        
</ins><span class="cx">         def fill_iter_with_book(iter, book)
</span><ins>+                
</ins><span class="cx">             iter[Columns::IDENT] = book.ident.to_s
</span><span class="cx">             iter[Columns::TITLE] = book.title
</span><span class="cx">             title = book.title.sub(REDUCE_TITLE_REGEX, '\1...')
</span><span class="lines">@@ -443,7 +483,9 @@
</span><span class="cx">         end
</span><span class="cx"> 
</span><span class="cx">         def append_book(book, tail=nil)
</span><ins>+                #puts &quot;Blah: #{@model.inspect}&quot; if $DEBUG
</ins><span class="cx">             iter = tail ? @model.insert_after(tail) : @model.append
</span><ins>+            #puts iter
</ins><span class="cx">             fill_iter_with_book(iter, book)
</span><span class="cx">             return iter
</span><span class="cx">         end
</span><span class="lines">@@ -1265,6 +1307,7 @@
</span><span class="cx">             on_quit = proc do
</span><span class="cx">                 save_preferences
</span><span class="cx">                 Gtk.main_quit
</span><ins>+                @libraries.really_save_all_books
</ins><span class="cx">                 @libraries.really_delete_deleted_libraries
</span><span class="cx">                 @libraries.all_regular_libraries.each do |library|
</span><span class="cx">                     library.really_delete_deleted_books
</span></span></pre></div>
<a id="trunkalexandrialibalexandriauinew_book_dialogrb"></a>
<div class="modfile"><h4>Modified: trunk/alexandria/lib/alexandria/ui/new_book_dialog.rb (652 => 653)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/alexandria/lib/alexandria/ui/new_book_dialog.rb        2007-03-12 09:31:13 UTC (rev 652)
+++ trunk/alexandria/lib/alexandria/ui/new_book_dialog.rb        2007-03-13 03:52:46 UTC (rev 653)
</span><span class="lines">@@ -322,7 +322,7 @@
</span><span class="cx">                     rescue
</span><span class="cx">                         raise _(&quot;Couldn't validate the EAN/ISBN you &quot; +
</span><span class="cx">                                 &quot;provided.  Make sure it is written &quot; +
</span><del>-                                &quot;correcty, and try again.&quot;)
</del><ins>+                                &quot;correctly, and try again.&quot;)
</ins><span class="cx">                     end
</span><span class="cx">                     assert_not_exist(library, @entry_isbn.text)
</span><span class="cx">                     books_to_add &lt;&lt; Alexandria::BookProviders.isbn_search(isbn)
</span></span></pre>
</div>
</div>

</body>
</html>