From 49e4d2844b7474af7e94c1998c649aecffcc909a Mon Sep 17 00:00:00 2001 From: Eric West Date: Mon, 20 May 2013 19:11:48 -0500 Subject: [PATCH 1/5] Track now properly traverses folder structure --- .gitignore | 4 ++++ lib/homesick.rb | 14 ++++++++++---- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/.gitignore b/.gitignore index 88cf2e9..e605e1e 100644 --- a/.gitignore +++ b/.gitignore @@ -39,3 +39,7 @@ pkg # # For vim: *.swp +# +# For IDEA: +.idea/ +*.iml diff --git a/lib/homesick.rb b/lib/homesick.rb index 341e3f9..a61645e 100644 --- a/lib/homesick.rb +++ b/lib/homesick.rb @@ -112,16 +112,22 @@ class Homesick < Thor desc "track FILE CASTLE", "add a file to a castle" def track(file, castle) castle = Pathname.new(castle) - file = Pathname.new(file) + file = Pathname.new(file.chomp('/')) check_castle_existance(castle, 'track') absolute_path = file.expand_path - castle_path = castle_dir(castle) + relative_dir = absolute_path.relative_path_from(home_dir).dirname + castle_path = Pathname.new(castle_dir(castle)).join(relative_dir) + + unless castle_path.exist? + FileUtils.mkdir_p castle_path + end + mv absolute_path, castle_path inside home_dir do - absolute_path = castle_dir(castle) + file.basename - home_path = home_dir + file + absolute_path = castle_path + file.basename + home_path = home_dir + relative_dir + file.basename ln_s absolute_path, home_path end From 7332aa4acd1a4a64384f59d1012f8268d943b75e Mon Sep 17 00:00:00 2001 From: Eric West Date: Mon, 20 May 2013 21:06:31 -0500 Subject: [PATCH 2/5] Specs for track --- spec/homesick_spec.rb | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/spec/homesick_spec.rb b/spec/homesick_spec.rb index 81fafb7..9e34ed3 100644 --- a/spec/homesick_spec.rb +++ b/spec/homesick_spec.rb @@ -169,5 +169,27 @@ describe "homesick" do some_rc_file.readlink.should == tracked_file end + + it 'should track a file in nested folder structure' do + castle = given_castle('castle_repo') + + some_nested_file = home.file('some/nested/file.txt') + homesick.track(some_nested_file.to_s, 'castle_repo') + + tracked_file = castle.join('some/nested/file.txt') + tracked_file.should exist + some_nested_file.readlink.should == tracked_file + end + + it 'should track a nested directory' do + castle = given_castle('castle_repo') + + some_nested_dir = home.directory('some/nested/directory/') + homesick.track(some_nested_dir.to_s, 'castle_repo') + + tracked_file = castle.join('some/nested/directory/') + tracked_file.should exist + File.realdirpath(some_nested_dir).should == File.realdirpath(tracked_file) + end end end From b93eea0e24c6c40d4dca1e1b6943e218e4e55e63 Mon Sep 17 00:00:00 2001 From: Eric West Date: Fri, 24 May 2013 07:52:54 -0500 Subject: [PATCH 3/5] Track makes entries in .manifest When a user tracks a file or directory that is in a nested folder, Homesick creates a .manifest in the user's castle (if there isn't one already) and adds an entry listing the file or directory's parent directory (if it isn't already listed). --- lib/homesick.rb | 9 +++++++++ spec/homesick_spec.rb | 29 +++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/lib/homesick.rb b/lib/homesick.rb index a61645e..9f5a63f 100644 --- a/lib/homesick.rb +++ b/lib/homesick.rb @@ -134,6 +134,15 @@ class Homesick < Thor inside castle_path do git_add absolute_path end + + # are we tracking something nested? Add the parent dir to the manifest unless its already listed + unless relative_dir.eql?(Pathname.new('.')) + manifest_path = Pathname.new(repos_dir.join(castle, '.manifest')) + File.open(manifest_path, 'a+') do |manifest| + manifest.puts relative_dir unless manifest.readlines.inject(false) { |memo, line| line.eql?("#{relative_dir.to_s}\n") || memo } + end + end + end desc "list", "List cloned castles" diff --git a/spec/homesick_spec.rb b/spec/homesick_spec.rb index 9e34ed3..d769489 100644 --- a/spec/homesick_spec.rb +++ b/spec/homesick_spec.rb @@ -191,5 +191,34 @@ describe "homesick" do tracked_file.should exist File.realdirpath(some_nested_dir).should == File.realdirpath(tracked_file) end + + describe "manifest" do + + it 'should add the nested files parent to the manifest' do + castle = given_castle('castle_repo') + + some_nested_file = home.file('some/nested/file.txt') + homesick.track(some_nested_file.to_s, 'castle_repo') + + manifest = Pathname.new(castle.parent.join('.manifest')) + File.open(manifest, 'r') do |f| + f.readline.should == "some/nested\n" + end + end + + it 'should NOT add anything if the files parent is already listed' do + castle = given_castle('castle_repo') + + some_nested_file = home.file('some/nested/file.txt') + other_nested_file = home.file('some/nested/other.txt') + homesick.track(some_nested_file.to_s, 'castle_repo') + homesick.track(other_nested_file.to_s, 'castle_repo') + + manifest = Pathname.new(castle.parent.join('.manifest')) + File.open(manifest, 'r') do |f| + f.readlines.size.should == 1 + end + end + end end end From 6867ef78dc91290022fbd70c5af266715e26d004 Mon Sep 17 00:00:00 2001 From: Eric West Date: Fri, 24 May 2013 16:24:42 -0500 Subject: [PATCH 4/5] Handling edge cases Covers only edge cases related to tracking, not yet handling linking or updating. Getting a bit hairy, must be refactored. --- lib/homesick.rb | 33 ++++++++++++++++++++++++++++++++- spec/homesick_spec.rb | 14 ++++++++++++++ 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/lib/homesick.rb b/lib/homesick.rb index 9f5a63f..e2cc155 100644 --- a/lib/homesick.rb +++ b/lib/homesick.rb @@ -123,7 +123,38 @@ class Homesick < Thor FileUtils.mkdir_p castle_path end - mv absolute_path, castle_path + # Are we already tracking this or anything inside it? + target = Pathname.new(castle_path.join(file.basename)) + + if target.exist? + + if absolute_path.directory? + child_files = absolute_path.children + child_files.each do |child| + + if target.join(child.basename).exist? + next + end + + mv child, target + end + absolute_path.rmtree + manifest = Pathname.new(repos_dir.join(castle, '.manifest')) + if manifest.exist? + lines = IO.readlines(manifest).delete_if { |line| line == "#{relative_dir + file.basename}\n" } + File.open(manifest, 'w') { |manfile| manfile.puts lines } + end + + elsif absolute_path.mtime > target.mtime && !absolute_path.symlink? + target.delete + mv absolute_path, castle_path + else + shell.say_status(:track, "#{target} already exists, and is more recent than #{file}. Run 'homesick SYMLINK CASTLE' to create symlinks.") + end + + else + mv absolute_path, castle_path + end inside home_dir do absolute_path = castle_path + file.basename diff --git a/spec/homesick_spec.rb b/spec/homesick_spec.rb index d769489..7880d1f 100644 --- a/spec/homesick_spec.rb +++ b/spec/homesick_spec.rb @@ -219,6 +219,20 @@ describe "homesick" do f.readlines.size.should == 1 end end + + it 'should remove the parent of a tracked file from the manifest if the parent itself is tracked' do + castle = given_castle('castle_repo') + + some_nested_file = home.file('some/nested/file.txt') + nested_parent = home.directory('some/nested/') + homesick.track(some_nested_file.to_s, 'castle_repo') + homesick.track(nested_parent.to_s, 'castle_repo') + + manifest = Pathname.new(castle.parent.join('.manifest')) + File.open(manifest, 'r') do |f| + f.each_line { |line| line.should_not == "some/nested\n" } + end + end end end end From e924cbefda7a0173f6f21aaf8fbbe040f4f5e1b1 Mon Sep 17 00:00:00 2001 From: Eric West Date: Fri, 24 May 2013 21:57:12 -0500 Subject: [PATCH 5/5] refactor, cleanup and tweak --- lib/homesick.rb | 81 ++++++++++++++++++++++++++++++++++--------------- 1 file changed, 56 insertions(+), 25 deletions(-) diff --git a/lib/homesick.rb b/lib/homesick.rb index e2cc155..0f1507c 100644 --- a/lib/homesick.rb +++ b/lib/homesick.rb @@ -125,33 +125,18 @@ class Homesick < Thor # Are we already tracking this or anything inside it? target = Pathname.new(castle_path.join(file.basename)) - if target.exist? - if absolute_path.directory? - child_files = absolute_path.children - child_files.each do |child| - - if target.join(child.basename).exist? - next - end - - mv child, target - end + move_dir_contents(target, absolute_path) absolute_path.rmtree - manifest = Pathname.new(repos_dir.join(castle, '.manifest')) - if manifest.exist? - lines = IO.readlines(manifest).delete_if { |line| line == "#{relative_dir + file.basename}\n" } - File.open(manifest, 'w') { |manfile| manfile.puts lines } - end + manifest_remove(castle, relative_dir + file.basename) - elsif absolute_path.mtime > target.mtime && !absolute_path.symlink? + elsif more_recent? absolute_path, target target.delete mv absolute_path, castle_path else - shell.say_status(:track, "#{target} already exists, and is more recent than #{file}. Run 'homesick SYMLINK CASTLE' to create symlinks.") + shell.say_status(:track, "#{target} already exists, and is more recent than #{file}. Run 'homesick SYMLINK CASTLE' to create symlinks.", :blue) unless options[:quiet] end - else mv absolute_path, castle_path end @@ -166,14 +151,10 @@ class Homesick < Thor git_add absolute_path end - # are we tracking something nested? Add the parent dir to the manifest unless its already listed + # are we tracking something nested? Add the parent dir to the manifest unless relative_dir.eql?(Pathname.new('.')) - manifest_path = Pathname.new(repos_dir.join(castle, '.manifest')) - File.open(manifest_path, 'a+') do |manifest| - manifest.puts relative_dir unless manifest.readlines.inject(false) { |memo, line| line.eql?("#{relative_dir.to_s}\n") || memo } - end + manifest_add(castle, relative_dir) end - end desc "list", "List cloned castles" @@ -265,4 +246,54 @@ class Homesick < Thor git_push end end + + def manifest(castle) + Pathname.new(repos_dir.join(castle, '.manifest')) + end + + def manifest_add(castle, path) + manifest_path = manifest(castle) + File.open(manifest_path, 'a+') do |manifest| + manifest.puts path unless manifest.readlines.inject(false) { |memo, line| line.eql?("#{path.to_s}\n") || memo } + end + + inside castle_dir(castle) do + git_add manifest_path + end + end + + def manifest_remove(castle, path) + manifest_file = manifest(castle) + if manifest_file.exist? + lines = IO.readlines(manifest_file).delete_if { |line| line == "#{path}\n" } + File.open(manifest_file, 'w') { |manfile| manfile.puts lines } + end + + inside castle_dir(castle) do + git_add manifest_file + end + end + + def move_dir_contents(target, dir_path) + child_files = dir_path.children + child_files.each do |child| + + target_path = target.join(child.basename) + if target_path.exist? + if more_recent?(child, target_path) && target.file? + target_path.delete + mv child, target + end + next + end + + mv child, target + end + end + + def more_recent?(first, second) + first_p = Pathname.new(first) + second_p = Pathname.new(second) + first_p.mtime > second_p.mtime && !first_p.symlink? + end end