2

i'm trying to use rugged to do something pretty simple: create and commit a file, leaving the repository in the same state as doing:

git init
echo "blah blah blah" > blah.txt
git add blah.txt
git commit -m "write blah.txt"

which leaves git status printing

On branch master
nothing to commit, working directory clean

i'm using code adapted from the rugged repo's readme, which boils down to:

name = "blah.txt"
repo = Rugged::Repository.init_at dir

File.open File.join(dir, name), 'w' do |f|
  f.write content
end

oid = Rugged::Blob.from_workdir repo, name
index = repo.index

index.add(:path => name, :oid => oid, :mode => 0100644)

options = {}
options[:tree] = index.write_tree(repo)

options[:author] = {  :email => "testuser@github.com",
                      :name => 'Test Author',
                      :time => Time.now }
options[:committer] = { :email => "testuser@github.com",
                        :name => 'Test Author',
                        :time => Time.now }
options[:message] =  "write #{ name }"
options[:parents] = repo.empty? ? [] : [ repo.head.target ].compact
options[:update_ref] = 'HEAD'

commit = Rugged::Commit.create(repo, options)

this seems to leave the repository in the right state, but the working dir in a weird place, with git status printing

On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    deleted:    blah.txt

Untracked files:
  (use "git add <file>..." to include in what will be committed)

    blah.txt

i don't understand what git thinks is happening at this point (blah.txt is staged for delete?). executing git reset --hard puts the working dir back in the desired state from what i can tell.

thanks in advance for the help.

nrser
  • 1,287
  • 1
  • 13
  • 23

1 Answers1

4

You've forgotten to save your changes to the index. You've updated the reference to point to the new commit, but the index is unchanged (as you never call Index#write), so as far as git is concerned the deletion is staged because the file is not in the index, just as if you had run git rm blah.txt.

Carlos Martín Nieto
  • 5,207
  • 1
  • 15
  • 16
  • how would i change the above code to fix it? or what code would accomplish it? forgive me, but i don't know much about git internals and am finding zero-to-no documentation on rugged. the above example is adapted from the 'write' example on the project's readme: https://github.com/libgit2/rugged#writing-to-a-repository – nrser Jul 04 '14 at 00:25
  • 1
    I would add what I said, add a call to `Index#write` to persist your changes to the index to disk, in your code that would be `index.write()`. – Carlos Martín Nieto Jul 04 '14 at 05:37
  • yup, that seems to fix it. any idea why that is missing from the `rugged` docs at https://github.com/libgit2/rugged#writing-to-a-repository? is there some reason you wouldn't want to write the index before making the commit? – nrser Jul 07 '14 at 09:50
  • That example does not emulate the git-commit command, it just creates a new commit. An Index is not just the .git/index file but a data structure, it's common to want to use it without affecting the index file. – Carlos Martín Nieto Jul 07 '14 at 09:56
  • ok, so, along the lines of the initial question, how *can* i emulate the `git add ...; git commit` commands? that what i'm trying to do. i notice after adding the `index.write` call, modifications to `blah.txt` do not show up as changes in `git status`, for instance, and i'm guessing from your response there may be more issues as well. – nrser Jul 07 '14 at 10:02
  • `git add` would be something like `idx = repo.index; idx.add(String); idx.write`, for commit it depends which options you want to emulate. The simplest form is what it shows in the README, pass a branch you'd like to update. – Carlos Martín Nieto Jul 07 '14 at 11:28