Removing a tree and committing with Rugged

152 Views Asked by At

I'm trying to remove an array of directories in a git repo and make 1 commit for each directory removed. I'm using Rugged and Gitlab_git (which is more or less just a wrapper around Rugged) and so far I've managed to do everything I need to except the actually deletion and commit.

I don't see anything in the Rugged Readme that explains how to remove an entire tree/directory. I tried using their commit example for a blob and replacing a single file with a direcotry, but It didnt work

I also tried editing the code they had for the tree builder, but it added a commit to my history that showed every file ever in the repo having been added, and then left staging showing the same thing. Nothing was deleted.

oid = repo.write("Removing folder", :blob)
builder = Rugged::Tree::Builder.new(repo)
builder << { :type => :blob, :name => "_delete", :oid => oid, :filemode => 0100644 }

options = {}
options[:tree] = builder.write

options[:author] = { :email => "[email protected]", :name => 'Test Author', :time => Time.now }
options[:committer] = { :email => "[email protected]", :name => 'Test Author', :time => Time.now }
options[:message] ||= "Making a commit via Rugged!"
options[:parents] = repo.empty? ? [] : [ repo.head.target ].compact
options[:update_ref] = 'HEAD'

Rugged::Commit.create(repo, options)

Any suggestions? Im still a bit fuzzy on the git internals, so maybe thats my issue.

2

There are 2 best solutions below

0
Jason Haslam On

The git index doesn't track directories explicitly, only their contents. To remove a directory, stage the removal of all of its contents.

0
matt On

You can make a Tree::Builder that is based on an existing tree in the repository, which you can then manipulate as you want.

If you already have the Commit object you want to have as your parent commit, then you can do this:

parent_commit = ... # e.g. this might be repo.head.target

# Create a Tree::Builder containing the current commit tree.
tree_builder = Rugged::Tree::Builder.new(repo, parent_commit.tree)

# Next remove the directory you want from the Tree::Builder.
tree_builder.remove('path/to/directory/to/remove')

# Now create a commit using the contents of the modified tree
# builder. (You might want to include the :update_ref option here
# depending on what you are trying to do - something like
# :update_ref => 'HEAD'.)
commit_data = {:message => "Remove directory with Rugged",
  :parents => [commit],
  :tree => tree_builder.write
}

Rugged::Commit.create(repo, commit_data)

This will create the commit in the repo with the directory removed, but might not update any branch pointers if you didn’t use :update_ref.

It also won’t update your current working directory or index. If you want to update them you could reset to the new HEAD, but be careful about losing any work. Alternatively you could just remove the directory with Dir.rmdir, mimicking what you would do when removing the directory directly.

Check out the docs for more info, especially Tree::Builder and Commit.create.