versioned_graph/commit

more code refactoring

authorJacco van Ossenbruggen
Fri Jun 20 13:34:14 2014 +0200
committerJacco van Ossenbruggen
Fri Jun 20 13:34:14 2014 +0200
commitb5f27b52cc1f6e95c239449f32e4d4a9066f429d
tree34f29df1f48a008365f02c332ba9096b3325485f
parentbb1d41cb2396250fc7035c94ac685b9b3a00f862
Diff style: patch stat
diff --git a/lib/graph_version.pl b/lib/graph_version.pl
index 0859a37..56efc23 100644
--- a/lib/graph_version.pl
+++ b/lib/graph_version.pl
@@ -1,19 +1,16 @@
 :- module(graph_version,
-	  [gv_init/0,                % Initialize RDF/GIT repo if needed
-	   gv_commit/5,		     % +GraphList, +Committer, +Message, -Commit, +Options
-	   gv_current_branch/1,      % -Branch, Branch is URI of current branch
-	   gv_branch_head/2,         % +Branch, -HEAD, HEAD is Trusty URI of tip of Branch
-	   gv_head/1,                % -HEAD is Trusty URI of tip of current branch
-	   gv_checkout/0,	     % Load RDF named graphs from current HEAD
-	   gv_checkout/1,	     % Restore named graphs from commit
-
-	   gv_resource_commit/4, % deprecated
-	   gv_commit_property/2,
-	   gv_diff/6,
-	   gv_restore_rdf_from_git/0, % Restore HEAD + all objects
-	   gv_restore_rdf_from_git/2,
-	   gv_restore_git_from_rdf/0,
-	   gv_restore_git_from_rdf/2
+	  [ gv_commit/5,	      % +GraphList, +Committer, +Message, -Commit, +Options
+	    gv_checkout/0,	      % Load RDF named graphs from current HEAD
+	    gv_checkout/1,	      % Restore named graphs from commit
+
+	    gv_current_branch/1,      % -Branch, Branch is URI of current branch
+	    gv_branch_head/2,         % +Branch, -HEAD, HEAD is Trusty URI of tip of Branch
+	    gv_head/1,                % -HEAD is Trusty URI of tip of current branch
+
+	    gv_resource_commit/4, % deprecated
+	    gv_commit_property/2,
+	    gv_diff/6,
+	    gv_init/1		      % +Options
 	  ]).
 
 :- use_module(library(semweb/rdf_db)).
@@ -21,13 +18,11 @@
 :- use_module(library(settings)).
 
 :- use_module(gv_namespaces).
-:- use_module(url_to_filename).
 :- use_module(gv_git_objects).
 :- use_module(gv_git_io).
 :- use_module(gv_hash_uri).
 
 
-
 :- setting(gv_git_dir, atom, 'gv.git',
 	   'GIT repository for named graph snapshots').
 :- setting(gv_blob_store,   oneof([git_only, rdf_only, both]), git_only,
@@ -38,45 +33,71 @@
 	   'Where to store commit objects').
 :- setting(gv_refs_store, oneof([git_only, rdf_only, both]),   git_only,
 	   'Where to store HEAD, refs etc.').
+:- setting(gv_refs_prefix, uri, 'http://localhost/git/',
+	   'Prefix for storing the local refs in RDF').
 
-:- setting(gv_head_graph, uri, 'http://localhost/git/HEAD/',
-	   'Named graph for storing the HEAD in RDF').
-:- setting(gv_refs_graph, uri, 'http://localhost/git/refs/',
-	   'Named graph for storing the refs in RDF').
+:- initialization(gv_init([])).
 
 :- listen(settings(changed(graph_version:_Setting, _Old, _New)),
-	  gv_init).
+	  gv_init([])).
+
+gv_commit(Graphs, Committer, Comment, Commit, Options) :-
+	with_mutex(gv_commit_mutex,
+		   gv_commit_(
+		       Graphs, Committer, Comment, Commit, Options)).
+
+gv_commit_(Graphs0, Committer, Comment, Commit, Options0) :-
+	is_list(Graphs0),
+	sort(Graphs0, Graphs),
+	setting(gv_git_dir, Dir),
+	gv_current_branch(Branch),
+	gv_branch_head(Branch, HEAD),
+	gv_commit_property(HEAD, tree(CurrentTree)),
+	Options=[directory(Dir)|Options0],
+	maplist(gv_create_blob_object(Options),Graphs, Blobs),
+	gv_add_blobs_to_tree(CurrentTree, Graphs, Blobs, NewTree, Options),
+	(   CurrentTree \= NewTree
+	->  true
+	;   format(atom(Message), 'No changes on commit by ~w (~w)', [Committer, Comment]),
+	    throw(nochange(gv_commit/5, Message))
+	),
+
+	gv_create_commit_object(NewTree, HEAD, Committer, Comment, Commit, Options),
+	gv_move_head(Branch, Commit, Options).
 
 
 %%	git_init is det.
 %
 %       Initialise the RDF and/or GIT version repositories.
-gv_init :-
-	setting(gv_git_dir, Dir),
-	setting(gv_blob_store,   BS),
-	setting(gv_tree_store,   TS),
-	setting(gv_commit_store, CS),
-	setting(gv_refs_store,   RS),
-	setting(gv_head_graph, HEAD),
-	setting(gv_refs_graph, Refs),
+gv_init(Options) :-
+	(   option(directory(Dir), Options)      -> true; setting(gv_git_dir, Dir)),
+	(   option(gv_blob_store(BS), Options)   -> true; setting(gv_blob_store, BS)),
+	(   option(gv_tree_store(TS), Options)   -> true; setting(gv_tree_store, TS)),
+	(   option(gv_commit_store(CS), Options) -> true; setting(gv_commit_store, CS)),
+	(   option(gv_refs_store(RS), Options)   -> true; setting(gv_refs_store, RS)),
+	(   option(gv_refs_prefix(Refs), Options)-> true; setting(gv_refs_prefix, Refs)),
+
 	sort([BS,TS,CS,RS], StorageOpts),
-	atom_concat(Refs, 'heads/master', Master),
+	gv_head_graph(HEAD),
+
 	(   (StorageOpts == [git_only] ; rdf_graph(HEAD))
 	->  true % no need to init RDF storage
-	;   gv_init_rdf(Master)
+	;   gv_init_rdf([gv_refs_prefix(Refs) | Options])
 	),
 
 	(   (StorageOpts == [rdf_only] ; exists_directory(Dir) )
 	->  true % no need to init git storage
-	;   gv_init_git
+	;   gv_init_git([directory(Dir) | Options])
 	).
 
-gv_init_rdf(Ref) :-
-	setting(gv_head_graph, HEAD),
-	rdf_assert(gv:current, gv:branch, Ref, HEAD).
-
+gv_init_rdf(Options) :-
+	option(gv_refs_prefix(Refs), Options),
+	atom_concat(Refs, 'refs/heads/master', Ref),
+	gv_init_rdf(Ref, Options).
 
-:- gv_init.
+gv_head_graph(Graph) :-
+	setting(gv_refs_prefix, Refs),
+	atom_concat(Refs, 'HEAD', Graph).
 
 %%	gv_current_branch(-Branch) is det.
 %
@@ -85,12 +106,12 @@ gv_init_rdf(Ref) :-
 
 gv_current_branch(Branch) :-
 	% assume current branch is stored in named graph HEAD:
-	setting(gv_head_graph, HEAD),
+	gv_head_graph(HEAD),
 	rdf(gv:current, gv:branch, Branch, HEAD),!.
 
 gv_current_branch(Branch) :-
 	\+ setting(gv_refs_store, rdf_only),
-	setting(gv_refs_graph, Refs),
+	setting(gv_refs_prefix, Refs),
 	% Assume current branch is the git symbolic ref HEAD:
 	gv_current_branch_git(Ref),
 	atomic_concat(Refs,Ref,Branch).
@@ -104,11 +125,13 @@ gv_branch_head(Branch, Commit) :-
 
 gv_branch_head(Branch, Commit) :-
 	\+ setting(gv_refs_store, rdf_only),
-	setting(gv_refs_graph, Refs),
+	setting(gv_refs_prefix, Refs),
 	atom_length(Refs, RefsLen),
 	sub_atom(Branch, RefsLen,_,0, Ref),
 	gv_branch_head_git(Ref, Hash),
-	gv_hash_uri(Hash, Commit).
+	gv_hash_uri(Hash, Commit),!.
+
+gv_branch_head(_, null) :- !.
 
 %%	gv_head(+Commit) is det.
 %
@@ -142,7 +165,7 @@ gv_checkout(Commit) :-
 
 	setting(gv_blob_store,  BlobsStore),
 	set_setting(gv_blob_store, git_only),
-	load_blobs(TreeTriples, graph),
+	gv_load_blobs(TreeTriples, graph),
 	set_setting(gv_blob_store,  BlobsStore).
 
 
@@ -242,32 +265,6 @@ gv_graphs_changed([rdf(S1,P1,O1)|T1], [rdf(S2,P2,O2)|T2],
 	).
 
 
-%%	gv_move_head(+Branch, +NewHead, +Options) is det.
-%
-%	Advance head to commit NewHead.
-
-gv_move_head(Branch, NewHead, Options) :-
-	with_mutex(gv_head_mutex, gv_move_head_(Branch, NewHead, Options)).
-
-gv_move_head_(Branch, NewHead, Options) :-
-	setting(gv_refs_store, DefaultStoreMode),
-	option(gv_refs_store(StoreMode), Options, DefaultStoreMode),
-	(   (StoreMode == rdf_only ; StoreMode == both)
-	->  gv_move_head_rdf(Branch, NewHead)
-	;   true
-	),
-	(   (StoreMode == git_only ; StoreMode == both)
-	->  gv_hash_uri(Hash, NewHead),
-	    rdf_global_id(localgit:Local, Branch),
-	    gv_move_head_git(Local, Hash)
-	;   true
-	).
-
-gv_move_head_rdf(Branch, NewHead) :-
-	setting(gv_refs_graph, Refs),
-	atomic_concat(Refs, 'heads', RefsHeads),
-	rdf_retractall(Branch, gv:tip, _OldHead, RefsHeads),
-	rdf_assert(    Branch, gv:tip,  NewHead, RefsHeads).
 
 %%      gv_resource_commit(+Graph, +Committer, +Comment, -Commit)
 %
@@ -292,30 +289,6 @@ gv_resource_commit(Graph, Committer, Comment, Commit) :-
 		   gv_commit_(
 		       [Graph], Committer, Comment, Commit, [])).
 
-gv_commit(Graphs, Committer, Comment, Commit, Options) :-
-	with_mutex(gv_commit_mutex,
-		   gv_commit_(
-		       Graphs, Committer, Comment, Commit, Options)).
-
-gv_commit_(Graphs0, Committer, Comment, Commit, Options0) :-
-	is_list(Graphs0),
-	sort(Graphs0, Graphs),
-	setting(gv_git_dir, Dir),
-	gv_current_branch(Branch),
-	gv_branch_head(Branch, HEAD),
-	gv_commit_property(HEAD, tree(CurrentTree)),
-	Options=[directory(Dir)|Options0],
-	maplist(gv_create_blob_object(Options),Graphs, Blobs),
-	gv_add_blobs_to_tree(CurrentTree, Graphs, Blobs, NewTree, Options),
-	(   CurrentTree \= NewTree
-	->  true
-	;   format(atom(Message), 'No changes on commit by ~w (~w)', [Committer, Comment]),
-	    throw(nochange(gv_commit/5, Message))
-	),
-
-	gv_create_commit_object(NewTree, HEAD, Committer, Comment, Commit, Options),
-	gv_move_head(Branch, Commit, Options).
-
 
 ps(P,S, rdf(S,P,_)).
 pso(P,S,O, rdf(S,P,O)).
@@ -330,197 +303,6 @@ gv_add_blobs_to_tree(Tree, Graphs, Blobs, NewTree, Options) :-
 	sort(Triples2, NewTriples),
 	gv_create_tree_object(NewTriples, NewTree, Options).
 
-git_tree_pair_to_triple([hash(H),name(Senc)], rdf(Sdec,P,O)) :-
-	rdf_equal(P, gv:blob),
-	url_to_filename(Sdec, Senc),
-	gv_hash_uri(H,O).
-
-
-gv_tree_triples(null, []) :- !.
-gv_tree_triples(Tree, Triples) :-
-	nonvar(Tree),
-	rdf_graph(Tree),
-	\+ setting(gv_tree_store, git_only),!,
-	findall(rdf(S,P,O), rdf(S,P,O,Tree), Triples0),
-	sort(Triples0, Triples).
-gv_tree_triples(Tree, Triples) :-
-	\+ setting(gv_tree_store, rdf_only),!,
-	gv_hash_uri(Hash, Tree),
-	gv_parse_tree(Hash, TreeObject),
-	maplist(git_tree_pair_to_triple, TreeObject, Triples).
-
-
-load_blobs([], _) :- !.
-load_blobs([rdf(_IRI, _P, Hash)|T], hash) :-
-	rdf_graph(Hash),!,
-	load_blobs(T, hash).
-load_blobs([rdf(IRI,_P,Hash)|T], Mode) :-
-	gv_graph_triples(Hash, Triples),
-	(   Mode == graph
-	->  gv_graph_triples(IRI, Triples)
-	;   gv_graph_triples(Hash, Triples)
-	),
-	load_blobs(T, Mode).
-
-store_blobs([], _) :- !.
-store_blobs([rdf(_IRI,_P, Blob)|T], Options) :-
-	gv_create_blob_object(Options, Blob, Blob),
-	store_blobs(T, Options).
-
-gv_restore_rdf_from_git :-
-	gv_restore_rdf_from_git(
-	    [commits(restore),
-	     trees(restore),
-	     blobs(restore)
-	    ]).
-
-gv_restore_rdf_from_git(Options) :-
-	setting(gv_commit_store, CommitStore),
-	setting(gv_tree_store,   TreeStore),
-	setting(gv_blob_store,   BlobsStore),
-	setting(gv_refs_store,   RefStore),
-
-	set_setting(gv_commit_store, git_only),
-	set_setting(gv_tree_store, git_only),
-	set_setting(gv_blob_store, git_only),
-	set_setting(gv_refs_store, git_only),
-
-	gv_current_branch(Branch),
-	gv_branch_head(Branch, Head),
-	gv_init_rdf(Branch),  % make sure RDF is on branch too
-	gv_move_head(Branch, Head, [gv_refs_store(rdf_only)]),
-	gv_checkout(Head),
-	gv_restore_rdf_from_git(Head, Options),
-
-	set_setting(gv_commit_store, CommitStore),
-	set_setting(gv_tree_store,   TreeStore),
-	set_setting(gv_blob_store,   BlobsStore),
-	set_setting(gv_refs_store,   RefStore).
-
-gv_restore_rdf_from_git(Commit, Options) :-
-	debug(gv, 'Restoring commit ~p', [Commit]),
-	gv_commit_property(Commit, tree(Tree)),
-	tree_to_rdf(Tree, Options),
-	commit_to_rdf(Commit, Options),
-	(   gv_commit_property(Commit, parent(Parent))
-	->  gv_restore_rdf_from_git(Parent, Options)
-	;   true
-	).
-
-gv_restore_git_from_rdf :-
-	setting(graph_version:gv_git_dir, Dir),
-	gv_restore_git_from_rdf(
-	    [commits(restore),
-	     trees(restore),
-	     blobs(restore),
-	     directory(Dir)
-	    ]).
-
-gv_restore_git_from_rdf(Options) :-
-	setting(gv_commit_store, CommitStore),
-	setting(gv_tree_store,   TreeStore),
-	setting(gv_blob_store,   BlobsStore),
-	setting(gv_refs_store,   RefStore),
-
-	set_setting(gv_commit_store, rdf_only),
-	set_setting(gv_tree_store, rdf_only),
-	set_setting(gv_blob_store, rdf_only),
-	set_setting(gv_refs_store, rdf_only),
-
-	gv_current_branch(Branch),
-	gv_branch_head(Branch, Head),
-	gv_move_head(Branch, Head, [gv_refs_store(git_only)| Options]),
-	gv_restore_git_from_rdf(Head, Options),
-
-	set_setting(gv_commit_store, CommitStore),
-	set_setting(gv_tree_store,   TreeStore),
-	set_setting(gv_blob_store,   BlobsStore),
-	set_setting(gv_refs_store,   RefStore).
-
-gv_restore_git_from_rdf(Commit, Options) :-
-	debug(gv, 'Restoring commit ~p', [Commit]),
-	gv_commit_property(Commit, tree(Tree)),
-	tree_to_git(Tree, Options),
-	rdf_commit_to_git(Commit, Tree, Options),
-	(   gv_commit_property(Commit, parent(Parent))
-	->  gv_restore_git_from_rdf(Parent, Options)
-	;   true
-	).
-
-tree_to_rdf(Tree, Options) :-
-	gv_tree_triples(Tree, Triples),
-	(   rdf_graph(Tree)
-	->  true
-	;
-	    (	option(trees(ignore), Options)
-	    ->  true
-	    ;	gv_graph_triples(Tree, Triples)
-	    )
-	),
-	(   option(blobs(ignore), Options)
-	->  true
-	;   load_blobs(Triples, hash)
-	).
-
-tree_to_git(Tree, Options) :-
-	gv_tree_triples(Tree, Triples),
-	(   option(trees(ignore), Options)
-	->  true
-	;   gv_create_tree_object(Triples, Tree, [gv_tree_store(git_only)|Options])
-	),
-	(   option(blobs(ignore), Options)
-	->  true
-	;   store_blobs(Triples, [gv_blob_store(git_only)|Options])
-	).
-
-commit_to_rdf(Commit, Options) :-
-	(   rdf_graph(Commit)
-	->  true
-	;   option(commits(ignore), Options)
-	->  true
-	;   gv_hash_uri(Hash, Commit),
-	    gv_parse_commit(Hash, CommitObject),
-	    assert_commit_props(CommitObject, Commit)
-	).
-
-rdf_commit_to_git(Commit, Tree, Options) :-
-	(   option(commits(ignore), Options)
-	->  true
-	;   gv_commit_property(Commit, comment(Comment)),
-	    gv_commit_property(Commit, committer_url(Committer)),
-	    (	gv_commit_property(Commit, parent(Parent))
-	    ->	true
-	    ;	Parent = null
-	    ),
-	    findall(P, gv_commit_property(Commit, P), CommitProps),
-	    append([CommitProps, [gv_commit_store(git_only)], Options], AllOptions),
-	    gv_create_commit_object(Tree, Parent, Committer, Comment, Commit, AllOptions)
-	).
-
-
-assert_commit_props([], _).
-assert_commit_props([parent(null)|T], Graph) :-
-	!,
-	assert_commit_props(T, Graph).
-assert_commit_props([H|T], Graph) :-
-	H =.. [P,V],
-	member(P, [comment, author_url, author_date, author_email,
-		  committer_url, committer_date, committer_email]),
-	!,
-	rdf_global_id(gv:P, Pred),
-        rdf_assert(Graph, Pred, V, Graph),
-	assert_commit_props(T, Graph).
-assert_commit_props([H|T], Graph) :-
-	!,
-	H =.. [P,V],
-	(   member(P, [tree, parent])
-	->  gv_hash_uri(V, Object),
-	    rdf_global_id(gv:P, Pred),
-	    rdf_assert(Graph, Pred, Object, Graph)
-	;   assert_commit_props(V, Graph)
-	),
-	assert_commit_props(T, Graph).
-
 
 cliopatria:list_resource(URI) :-
 	gv_hash_uri(_Hash, URI),
diff --git a/lib/gv_git_io.pl b/lib/gv_git_io.pl
index b66a341..52c3542 100644
--- a/lib/gv_git_io.pl
+++ b/lib/gv_git_io.pl
@@ -1,5 +1,5 @@
 :- module(gv_git_io,
-	  [ gv_init_git/0,
+	  [ gv_init_git/1,
 	    gv_current_branch_git/1,
 	    gv_commit_property_git/2,
 	    gv_branch_head_git/2,
@@ -14,8 +14,8 @@
 :- use_module(parse_git_objects).
 
 
-gv_init_git :-
-	setting(graph_version:gv_git_dir, Dir),
+gv_init_git(Options) :-
+	option(directory(Dir), Options),
 	(   exists_directory(Dir)
 	->  true
 	;   make_directory(Dir),
diff --git a/lib/gv_git_objects.pl b/lib/gv_git_objects.pl
index 5064059..37f5cc0 100644
--- a/lib/gv_git_objects.pl
+++ b/lib/gv_git_objects.pl
@@ -4,8 +4,11 @@
 	    gv_create_commit_object/6,
 
 	    % do we need to export these?
-	    gv_graph_triples/2
-
+	    gv_graph_triples/2,
+	    gv_tree_triples/2,
+	    gv_load_blobs/2,
+	    gv_init_rdf/2,
+	    gv_move_head/3
 	  ]).
 
 :- use_module(library(memfile)).
@@ -198,3 +201,69 @@ tree_triple_to_git(rdf(S,P,O), Atom) :-
 	atom_codes(HashCode,Codes),
 	format(atom(A), '100644 ~w\u0000', [Filename]),
 	atom_concat(A, HashCode, Atom).
+
+git_tree_pair_to_triple([hash(H),name(Senc)], rdf(Sdec,P,O)) :-
+	rdf_equal(P, gv:blob),
+	url_to_filename(Sdec, Senc),
+	gv_hash_uri(H,O).
+
+
+gv_tree_triples(null, []) :- !.
+gv_tree_triples(Tree, Triples) :-
+	nonvar(Tree),
+	rdf_graph(Tree),
+	\+ setting(graph_version:gv_tree_store, git_only),!,
+	findall(rdf(S,P,O), rdf(S,P,O,Tree), Triples0),
+	sort(Triples0, Triples).
+gv_tree_triples(Tree, Triples) :-
+	\+ setting(graph_version:gv_tree_store, rdf_only),!,
+	gv_hash_uri(Hash, Tree),
+	gv_parse_tree(Hash, TreeObject),
+	maplist(git_tree_pair_to_triple, TreeObject, Triples).
+
+
+gv_load_blobs([], _) :- !.
+gv_load_blobs([rdf(_IRI, _P, Hash)|T], hash) :-
+	rdf_graph(Hash),!,
+	gv_load_blobs(T, hash).
+gv_load_blobs([rdf(IRI,_P,Hash)|T], Mode) :-
+	gv_graph_triples(Hash, Triples),
+	(   Mode == graph
+	->  gv_graph_triples(IRI, Triples)
+	;   gv_graph_triples(Hash, Triples)
+	),
+	gv_load_blobs(T, Mode).
+
+
+
+gv_init_rdf(Ref, Options) :-
+	option(gv_refs_prefix(Refs), Options),
+	atom_concat(Refs, 'HEAD', HEAD),
+	rdf_assert(gv:current, gv:branch, Ref, HEAD).
+
+%%	gv_move_head(+Branch, +NewHead, +Options) is det.
+%
+%	Advance head to commit NewHead.
+
+gv_move_head(Branch, NewHead, Options) :-
+	with_mutex(gv_head_mutex, gv_move_head_(Branch, NewHead, Options)).
+
+gv_move_head_(Branch, NewHead, Options) :-
+	setting(graph_version:gv_refs_store, DefaultStoreMode),
+	option(gv_refs_store(StoreMode), Options, DefaultStoreMode),
+	(   (StoreMode == rdf_only ; StoreMode == both)
+	->  gv_move_head_rdf(Branch, NewHead)
+	;   true
+	),
+	(   (StoreMode == git_only ; StoreMode == both)
+	->  gv_hash_uri(Hash, NewHead),
+	    rdf_global_id(localgit:Local, Branch),
+	    gv_move_head_git(Local, Hash)
+	;   true
+	).
+
+gv_move_head_rdf(Branch, NewHead) :-
+	setting(graph_version:gv_refs_prefix, Refs),
+	atomic_concat(Refs, 'refs/heads', RefsHeads),
+	rdf_retractall(Branch, gv:tip, _OldHead, RefsHeads),
+	rdf_assert(    Branch, gv:tip,  NewHead, RefsHeads).
diff --git a/lib/gv_replay.pl b/lib/gv_replay.pl
new file mode 100644
index 0000000..f8011b8
--- /dev/null
+++ b/lib/gv_replay.pl
@@ -0,0 +1,169 @@
+:- module(gv_replay,
+	  [ gv_restore_rdf_from_git/0, % Restore HEAD + all objects
+	    gv_restore_rdf_from_git/2,
+	    gv_restore_git_from_rdf/0,
+	    gv_restore_git_from_rdf/2
+	  ]).
+
+:- use_module(graph_version).
+:- use_module(gv_git_objects).
+:- use_module(gv_git_io).
+:- use_module(gv_hash_uri).
+
+gv_restore_rdf_from_git :-
+	gv_restore_rdf_from_git(
+	    [commits(restore),
+	     trees(restore),
+	     blobs(restore)
+	    ]).
+
+gv_restore_rdf_from_git(Options) :-
+	setting(gv_commit_store, CommitStore),
+	setting(gv_tree_store,   TreeStore),
+	setting(gv_blob_store,   BlobsStore),
+	setting(gv_refs_store,   RefStore),
+
+	set_setting(gv_commit_store, git_only),
+	set_setting(gv_tree_store, git_only),
+	set_setting(gv_blob_store, git_only),
+	set_setting(gv_refs_store, git_only),
+
+	gv_current_branch(Branch),
+	gv_branch_head(Branch, Head),
+	gv_init_rdf(Branch, Options),  % make sure RDF is on branch too
+	gv_move_head(Branch, Head, [gv_refs_store(rdf_only)]),
+	gv_checkout(Head),
+	gv_restore_rdf_from_git(Head, Options),
+
+	set_setting(gv_commit_store, CommitStore),
+	set_setting(gv_tree_store,   TreeStore),
+	set_setting(gv_blob_store,   BlobsStore),
+	set_setting(gv_refs_store,   RefStore).
+
+gv_restore_rdf_from_git(Commit, Options) :-
+	debug(gv, 'Restoring commit ~p', [Commit]),
+	gv_commit_property(Commit, tree(Tree)),
+	tree_to_rdf(Tree, Options),
+	git_commit_to_rdf(Commit, Options),
+	(   gv_commit_property(Commit, parent(Parent))
+	->  gv_restore_rdf_from_git(Parent, Options)
+	;   true
+	).
+
+gv_restore_git_from_rdf :-
+	setting(graph_version:gv_git_dir, Dir),
+	gv_restore_git_from_rdf(
+	    [commits(restore),
+	     trees(restore),
+	     blobs(restore),
+	     directory(Dir)
+	    ]).
+
+gv_restore_git_from_rdf(Options) :-
+	setting(gv_commit_store, CommitStore),
+	setting(gv_tree_store,   TreeStore),
+	setting(gv_blob_store,   BlobsStore),
+	setting(gv_refs_store,   RefStore),
+
+	set_setting(gv_commit_store, rdf_only),
+	set_setting(gv_tree_store, rdf_only),
+	set_setting(gv_blob_store, rdf_only),
+	set_setting(gv_refs_store, rdf_only),
+
+	gv_current_branch(Branch),
+	gv_branch_head(Branch, Head),
+	gv_move_head(Branch, Head, [gv_refs_store(git_only)| Options]),
+	gv_restore_git_from_rdf(Head, Options),
+
+	set_setting(gv_commit_store, CommitStore),
+	set_setting(gv_tree_store,   TreeStore),
+	set_setting(gv_blob_store,   BlobsStore),
+	set_setting(gv_refs_store,   RefStore).
+
+gv_restore_git_from_rdf(Commit, Options) :-
+	debug(gv, 'Restoring commit ~p', [Commit]),
+	gv_commit_property(Commit, tree(Tree)),
+	tree_to_git(Tree, Options),
+	rdf_commit_to_git(Commit, Tree, Options),
+	(   gv_commit_property(Commit, parent(Parent))
+	->  gv_restore_git_from_rdf(Parent, Options)
+	;   true
+	).
+tree_to_rdf(Tree, Options) :-
+	gv_tree_triples(Tree, Triples),
+	(   rdf_graph(Tree)
+	->  true
+	;
+	    (	option(trees(ignore), Options)
+	    ->  true
+	    ;	gv_graph_triples(Tree, Triples)
+	    )
+	),
+	(   option(blobs(ignore), Options)
+	->  true
+	;   gv_load_blobs(Triples, hash)
+	).
+
+tree_to_git(Tree, Options) :-
+	gv_tree_triples(Tree, Triples),
+	(   option(trees(ignore), Options)
+	->  true
+	;   gv_create_tree_object(Triples, Tree, [gv_tree_store(git_only)|Options])
+	),
+	(   option(blobs(ignore), Options)
+	->  true
+	;   store_blobs(Triples, [gv_blob_store(git_only)|Options])
+	).
+
+git_commit_to_rdf(Commit, Options) :-
+	(   rdf_graph(Commit)
+	->  true
+	;   option(commits(ignore), Options)
+	->  true
+	;   gv_hash_uri(Hash, Commit),
+	    gv_parse_commit(Hash, CommitObject),
+	    assert_commit_props(CommitObject, Commit)
+	).
+
+rdf_commit_to_git(Commit, Tree, Options) :-
+	(   option(commits(ignore), Options)
+	->  true
+	;   gv_commit_property(Commit, comment(Comment)),
+	    gv_commit_property(Commit, committer_url(Committer)),
+	    (	gv_commit_property(Commit, parent(Parent))
+	    ->	true
+	    ;	Parent = null
+	    ),
+	    findall(P, gv_commit_property(Commit, P), CommitProps),
+	    append([CommitProps, [gv_commit_store(git_only)], Options], AllOptions),
+	    gv_create_commit_object(Tree, Parent, Committer, Comment, Commit, AllOptions)
+	).
+
+store_blobs([], _) :- !.
+store_blobs([rdf(_IRI,_P, Blob)|T], Options) :-
+	gv_create_blob_object(Options, Blob, Blob),
+	store_blobs(T, Options).
+
+
+assert_commit_props([], _).
+assert_commit_props([parent(null)|T], Graph) :-
+	!,
+	assert_commit_props(T, Graph).
+assert_commit_props([H|T], Graph) :-
+	H =.. [P,V],
+	member(P, [comment, author_url, author_date, author_email,
+		  committer_url, committer_date, committer_email]),
+	!,
+	rdf_global_id(gv:P, Pred),
+        rdf_assert(Graph, Pred, V, Graph),
+	assert_commit_props(T, Graph).
+assert_commit_props([H|T], Graph) :-
+	!,
+	H =.. [P,V],
+	(   member(P, [tree, parent])
+	->  gv_hash_uri(V, Object),
+	    rdf_global_id(gv:P, Pred),
+	    rdf_assert(Graph, Pred, Object, Graph)
+	;   assert_commit_props(V, Graph)
+	),
+	assert_commit_props(T, Graph).