lib/dbox/database.rb in dbox-0.5.0 vs lib/dbox/database.rb in dbox-0.5.1
- old
+ new
@@ -9,19 +9,21 @@
def self.create(remote_path, local_path)
db = new(local_path)
if db.bootstrapped?
raise DatabaseError, "Database already initialized -- please use 'dbox pull' or 'dbox push'."
end
- db.bootstrap(remote_path, local_path)
+ db.bootstrap(remote_path)
+ db.migrate()
db
end
def self.load(local_path)
db = new(local_path)
unless db.bootstrapped?
raise DatabaseError, "Database not initialized -- please run 'dbox create' or 'dbox clone'."
end
+ db.migrate()
db
end
def self.exists?(local_path)
File.exists?(File.join(local_path, DB_FILENAME))
@@ -31,14 +33,17 @@
new_db = create(old_db.remote_path, old_db.local_path)
new_db.delete_entry_by_path("") # clear out root record
new_db.migrate_entry_from_old_db_format(old_db.root)
end
+ attr_reader :local_path
+
# IMPORTANT: Database.new is private. Please use Database.create
# or Database.load as the entry point.
private_class_method :new
def initialize(local_path)
+ @local_path = local_path
FileUtils.mkdir_p(local_path)
@db = SQLite3::Database.new(File.join(local_path, DB_FILENAME))
@db.trace {|sql| log.debug sql.strip }
@db.execute("PRAGMA foreign_keys = ON;")
ensure_schema_exists
@@ -46,11 +51,10 @@
def ensure_schema_exists
@db.execute_batch(%{
CREATE TABLE IF NOT EXISTS metadata (
id integer PRIMARY KEY AUTOINCREMENT NOT NULL,
- local_path varchar(255) NOT NULL,
remote_path varchar(255) NOT NULL,
version integer NOT NULL
);
CREATE TABLE IF NOT EXISTS entries (
id integer PRIMARY KEY AUTOINCREMENT NOT NULL,
@@ -63,17 +67,26 @@
);
CREATE INDEX IF NOT EXISTS entry_parent_ids ON entries(parent_id);
})
end
- METADATA_COLS = [ :local_path, :remote_path, :version ] # don't need to return id
+ def migrate
+ if metadata[:version] < 2
+ @db.execute_batch(%{
+ ALTER TABLE metadata DROP COLUMN local_path;
+ UPDATE_TABLE metadata SET version = 2;
+ })
+ end
+ end
+
+ METADATA_COLS = [ :remote_path, :version ] # don't need to return id
ENTRY_COLS = [ :id, :path, :is_dir, :parent_id, :hash, :modified, :revision ]
- def bootstrap(remote_path, local_path)
+ def bootstrap(remote_path)
@db.execute(%{
- INSERT INTO metadata (local_path, remote_path, version) VALUES (?, ?, ?);
- }, local_path, remote_path, 1)
+ INSERT INTO metadata (remote_path, version) VALUES (?, ?);
+ }, remote_path, 2)
@db.execute(%{
INSERT INTO entries (path, is_dir) VALUES (?, ?)
}, "", 1)
end
@@ -87,11 +100,13 @@
def metadata
cols = METADATA_COLS
res = @db.get_first_row(%{
SELECT #{cols.join(',')} FROM metadata LIMIT 1;
})
- make_fields(cols, res) if res
+ out = { :local_path => local_path }
+ out.merge!(make_fields(cols, res)) if res
+ out
end
def update_metadata(fields)
set_str = fields.keys.map {|k| "#{k}=?" }.join(",")
@db.execute(%{
@@ -126,11 +141,20 @@
raise(ArgumentError, "path cannot be null") unless path
update_entry(["WHERE path=?", path], fields)
end
def delete_entry_by_path(path)
- raise(ArgumentError, "path cannot be null") unless path
- delete_entry("WHERE path=?", path)
+ delete_entry_by_entry(find_by_path(path))
+ end
+
+ def delete_entry_by_entry(entry)
+ raise(ArgumentError, "entry cannot be null") unless entry
+
+ # cascade delete children, if any
+ contents(entry[:id]).each {|child| delete_entry_by_entry(child) }
+
+ # delete main entry
+ delete_entry("WHERE id=?", entry[:id])
end
def migrate_entry_from_old_db_format(entry, parent = nil)
# insert entry into sqlite db
add_entry(entry.path, entry.dir?, (parent ? parent[:id] : nil), entry.modified_at, entry.revision, nil)