Class: Git::Si::SvnInterface

Inherits:
Thor
  • Object
show all
Includes:
Pager, Thor::Actions
Defined in:
lib/git/si.rb

Constant Summary collapse

@@mirror_branch =
'MIRRORBRANCH'

Instance Method Summary collapse

Instance Method Details

#add(*args) ⇒ Object



105
106
107
108
109
110
111
112
# File 'lib/git/si.rb', line 105

def add(*args)
  on_local_branch do
    command = "svn add " + args.join(' ')
    run_command(command)
    command = "git add " + args.join(' ')
    run_command(command)
  end
end

#blame(*args) ⇒ Object



236
237
238
239
240
241
# File 'lib/git/si.rb', line 236

def blame(*args)
  on_local_branch do
    command = "svn blame " + args.join(' ')
    run_command(command)
  end
end

#commitObject



145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
# File 'lib/git/si.rb', line 145

def commit
  mirror_is_updated = false

  on_local_branch do
    local_branch = get_local_branch()
    if local_branch == 'master'
      notice_message "Warning: you're using the master branch as working copy. This can
cause trouble because when your changes are committed and you try to
rebase on top of them, you may end up with merge errors as you are
trying to apply patches of previous versions of your code. If you
continue, it's wise to reset the master branch afterward."
      return if ask("Do you want to continue with this commit? [Y/n] ", :green) =~ /\s*^n/i
    end

    git_status = `git status --porcelain`
    raise GitError.new("There are local changes; please commit them before continuing.") if git_status.match(/^[^\?]/)

    notice_message "Adding any files that are not already in svn to ensure changes are committed."
    readd()

    svn_diff = `svn diff`
    raise SvnError.new("Failed to get the svn diff. I'm not sure why. Check for any errors above.") if ! $?.success?
    raise SvnError.new("There are no changes to commit.") if svn_diff.strip.empty?

    run_command("svn commit")
    success_message "commit complete!"
    if yes? "Do you want to update the mirror branch to the latest commit? [y/N] ", :green
      on_mirror_branch do
        fetch
        mirror_is_updated = true
      end
    end
  end

  if mirror_is_updated
    local_branch = get_local_branch()
    if local_branch == 'master'
      if yes? "Do you want to reset the current branch to the latest commit (losing all git history)? [y/N] ", :green
        run_command("git checkout #{@@mirror_branch}")
        run_command("git branch -D '#{local_branch}'")
        run_command("git checkout -b #{local_branch}")
        success_message "branch '#{local_branch}' reset!"
      end
    else
      if yes? "Do you want to switch to master and delete the committed branch '#{local_branch}'? [y/N] ", :green
        run_command("git checkout master")
        rebase
        run_command("git branch -D '#{local_branch}'")
        success_message "branch '#{local_branch}' deleted!"
      end
    end
  end
end

#diff(*args) ⇒ Object



73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
# File 'lib/git/si.rb', line 73

def diff(*args)
  on_local_branch do
    last_fetched_version = get_svn_version()
    git_log = `git log --pretty=%B`
    results = git_log.match(/svn update to version (\d+)/i)
    last_rebased_version = results[1] if results
    if last_fetched_version and last_rebased_version
      if last_fetched_version > last_rebased_version
        raise VersionError.new("This branch is out-of-date (rev #{last_rebased_version}; mirror branch is at #{last_fetched_version}). You should do a git si rebase.")
      elsif last_fetched_version < last_rebased_version
        return if ask("This branch is newer (rev #{last_rebased_version}) than the mirror branch (rev #{last_fetched_version}). That can happen when svn changes have been made directly and may be fine. Do you want to continue? [Y/n] ", :green) =~ /\s*^n/i
      end
    else
      notice_message "Could not determine last version information. This may be fine if you haven't used git-si before."
    end

    notice_message "Adding any files that are not already in svn to ensure an accurate diff."
    readd()

    command = "svn diff " + args.join(' ')
    notice_message "Running #{command}"
    results = `#{command}`
    if STDOUT.tty?
      page
      print_colordiff results
    else
      say results
    end
  end
end

#fetchObject



115
116
117
118
119
120
121
122
123
124
125
126
127
128
# File 'lib/git/si.rb', line 115

def fetch
  on_local_branch do
    git_status = `git status --porcelain`
    raise GitError.new("There are local changes; please commit them before continuing.") if git_status.match(/^[^\?]/)
  end
  on_mirror_branch do
    notice_message "Fetching remote data from svn"
    run_command("svn up --accept theirs-full --ignore-externals")
    run_command("svn revert -R ./")
    system("git add .")
    run_command("git commit --allow-empty -am 'svn update to version #{get_svn_version}'")
  end
  success_message "fetch complete!"
end

#initObject



244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
# File 'lib/git/si.rb', line 244

def init
  on_local_branch do
    # check for svn repo
    `svn info`
    raise SvnError.new("No svn repository was found here. Maybe you're in the wrong directory?") unless $?.success?
    make_a_commit = false

    # check for existing .git repo
    if File.exist? '.git'
      notice_message "Looks like a git repository already exists here."
    else
      notice_message "Initializing git repository"
      `git init`
      raise GitError.new("Failed to initialize git repository. I'm not sure why. Check for any errors above.") unless $?.success?
      make_a_commit = true
    end

    # check for existing .gitingore
    gitignore = [".svn", "*.sw?", ".config", "*.err", "*.pid", "*.log", "svn-commit.*", "*.orig"]
    command = "svn status --ignore-externals "
    svn_status = `#{command}`
    raise SvnError.new("Failed to get the svn status. I'm not sure why. Check for any errors above.") if ! $?.success?
    externals = []
    svn_status.each_line do |line|
      externals << $1 if line.strip.match(/^X\s+(\S.+)/)
    end
    gitignore += externals
    gitignore = gitignore.join("\n")

    if File.exist? '.gitignore'
      notice_message "Looks like a gitignore file already exists here."
      error_message "Be SURE that the gitignore contains the following:\n#{gitignore}"
    else
      notice_message "Creating gitignore file."
      create_file('.gitignore', gitignore)
      run_command("git add .gitignore")
      make_a_commit = true
    end

    # make initial commit
    if make_a_commit
      notice_message "Making initial commit."
      run_command("git add .")
      run_command("git commit -am 'initial commit by git-si'")
    end

    # check for exiting mirror branch
    `git show-ref refs/heads/#{@@mirror_branch}`
    if $?.success?
      notice_message "Looks like the mirror branch already exists here."
    else
      notice_message "Creating mirror branch '#{@@mirror_branch}'."
      run_command("git branch '#{@@mirror_branch}'")
    end

    success_message "init complete!"
  end
end

#pullObject



139
140
141
142
# File 'lib/git/si.rb', line 139

def pull
  fetch
  rebase
end

#readdObject



200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
# File 'lib/git/si.rb', line 200

def readd()
  on_local_branch do
    command = "svn status --ignore-externals"
    svn_status = `#{command}`
    raise SvnError.new("Failed to get the svn status. I'm not sure why. Check for any errors above.") if ! $?.success?
    files_to_add = []
    using_stderr do
      svn_status.each_line do |line|
        case line.strip!
        when /^X/, /\.git/, /\.swp$/
        when /^\?\s+(\S.+)/
          filename = $1
          file_in_git = `git ls-files #{filename}`
          raise GitError.new("Failed to list git files. I'm not sure why. Check for any errors above.") unless $?.success?
          if not file_in_git.empty?
            files_to_add << filename if file_in_git
            say filename
          end
        end
      end
    end
    if files_to_add.empty?
      notice_message "There are no files to add."
      return
    end
    using_stderr do
      if yes? "Do you want to add the above files to svn? [y/N] ", :green
        command = "svn add " + files_to_add.join(' ')
        run_command(command)
        success_message "Added files to svn that had been added to git."
      end
    end
  end
end

#rebaseObject



131
132
133
134
135
136
# File 'lib/git/si.rb', line 131

def rebase
  on_local_branch do
    run_command("git rebase '#{@@mirror_branch}'")
    success_message "rebase complete!"
  end
end

#status(*args) ⇒ Object



53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/git/si.rb', line 53

def status(*args)
  on_local_branch do
    command = "svn status --ignore-externals " + args.join(' ')
    svn_status = `#{command}`
    raise SvnError.new("Failed to get the svn status. I'm not sure why. Check for any errors above.") if ! $?.success?
    svn_status.each_line do |line|
      case line.strip!
      when /^X/, /\.git/, /\.swp$/
      else
        if STDOUT.tty?
          print_colordiff line
        else
          say line
        end
      end
    end
  end
end

#usageObject



38
39
40
41
42
43
44
45
46
47
48
49
50
# File 'lib/git/si.rb', line 38

def usage
  say "git-si #{Git::Si::VERSION}

Git Svn Interface: a simple git extention to use git locally with a remote svn
repo. It's like a simple version of git-svn which doesn't keep track of history
locally.

Start with the init command to set up the mirror branch and from there you can
use the commands below.

"
  help
end

#versionObject



33
34
35
# File 'lib/git/si.rb', line 33

def version
  say "git-si version #{Git::Si::VERSION}"
end