Class: Rudy::SCM::GIT

Inherits:
Object
  • Object
show all
Includes:
Grit, ObjectBase
Defined in:
lib/rudy/scm/git.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from ObjectBase

#execute_rbox_command

Constructor Details

#initialize(args = {}) ⇒ GIT

  • args a hash of params from the git block in the routines config



24
25
26
27
28
29
30
31
32
33
34
35
36
# File 'lib/rudy/scm/git.rb', line 24

def initialize(args={})
  args = {
    :privatekey => nil,
    :remote => :origin,
    :branch => :master,
    :user => :root,
    :changes => :enforce,
    :path => nil
  }.merge(args)
  @remote, @branch, @path = args[:remote], args[:branch], args[:path]
  @user, @pkey, @changes = args[:user], args[:privatekey], args[:changes]
  @repo = Repo.new(Dir.pwd) if GIT.working_copy?
end

Instance Attribute Details

#base_uriObject

Returns the value of attribute base_uri.



12
13
14
# File 'lib/rudy/scm/git.rb', line 12

def base_uri
  @base_uri
end

#branchObject

Returns the value of attribute branch.



14
15
16
# File 'lib/rudy/scm/git.rb', line 14

def branch
  @branch
end

#changesObject (readonly)

Returns the value of attribute changes.



20
21
22
# File 'lib/rudy/scm/git.rb', line 20

def changes
  @changes
end

#pkeyObject (readonly)

Returns the value of attribute pkey.



19
20
21
# File 'lib/rudy/scm/git.rb', line 19

def pkey
  @pkey
end

#rboxObject (readonly)

Returns the value of attribute rbox.



16
17
18
# File 'lib/rudy/scm/git.rb', line 16

def rbox
  @rbox
end

#remoteObject

Returns the value of attribute remote.



13
14
15
# File 'lib/rudy/scm/git.rb', line 13

def remote
  @remote
end

#repoObject (readonly)

Returns the value of attribute repo.



15
16
17
# File 'lib/rudy/scm/git.rb', line 15

def repo
  @repo
end

#rtagObject (readonly)

Returns the value of attribute rtag.



17
18
19
# File 'lib/rudy/scm/git.rb', line 17

def rtag
  @rtag
end

#userObject (readonly)

Returns the value of attribute user.



18
19
20
# File 'lib/rudy/scm/git.rb', line 18

def user
  @user
end

Class Method Details

.clean_working_copy?(path = Dir.pwd) ⇒ Boolean

Are all local changes committed?

Returns:

  • (Boolean)


189
190
191
# File 'lib/rudy/scm/git.rb', line 189

def self.clean_working_copy?(path=Dir.pwd)
  Rye.shell(:git, 'diff').stdout == []
end

.working_copy?(path = Dir.pwd) ⇒ Boolean

Returns:

  • (Boolean)


194
195
196
# File 'lib/rudy/scm/git.rb', line 194

def self.working_copy?(path=Dir.pwd)
  (File.exists?(File.join(path, '.git')))
end

Instance Method Details

#clean_working_copy?Boolean

Returns:

  • (Boolean)


192
# File 'lib/rudy/scm/git.rb', line 192

def clean_working_copy?; GIT.clean_working_copy?; end

#create_release(username = nil, msg = nil) ⇒ Object



44
45
46
47
48
49
50
51
52
53
54
55
# File 'lib/rudy/scm/git.rb', line 44

def create_release(username=nil, msg=nil)
  @rtag = find_next_rtag(username)
  msg ||= 'Another Release by Rudy!'
  msg.tr!("'", "''")
  ret = Rye.shell(:git, "tag", @rtag)  # Use annotated? -a -m '#{msg}' 
  raise ret.stderr.join($/) if ret.exit_code > 0
  ret = Rye.shell(:git, "push") if @remote
  raise ret.stderr.join($/) if ret.exit_code > 0
  ret = Rye.shell(:git, "push #{@remote} #{rtag}") if @remote
  raise ret.stderr.join($/) if ret.exit_code > 0
  @rtag
end

#create_remote_checkout(rbox) ⇒ Object



80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
# File 'lib/rudy/scm/git.rb', line 80

def create_remote_checkout(rbox)
  
  # Make sure the directory above the clone path exists 
  # and that it's owned by the request user. 
  rbox.mkdir(:p, File.dirname(@path)) 
  rbox.chown(@user, File.dirname(@path)) 
  
  begin
    original_user = rbox.user
    rbox.switch_user(@user)
    
    if @pkey
      # Try when debugging: ssh -vi path/2/pkey [email protected]
      key = File.basename(@pkey)
      homedir = rbox.getenv['HOME']
      rbox.mkdir(:p, :m, '700', '.ssh') rescue nil # :p says keep quiet if it exists              
      if rbox.file_exists?(".ssh/#{key}")
        puts "  Remote private key #{key} already exists".colour(:red)
      else
        rbox.upload(@pkey, ".ssh/#{key}")
      end
      
      ## NOTE: The following are two attempts at telling git which 
      ## private key to use. Both fail. The only thing I could get
      ## to work is modifying the ~/.ssh/config file. 
      ##
      ## This runs fine, but "git clone" doesn't care. 
      ## git config --global --replace-all http.sslKey /home/delano/.ssh/id_rsa
      ## rbox.git('config', '--global', '--replace-all', 'http.sslKey', "#{homedir}/.ssh/#{key}")
      ##
      ## "git clone" doesn't care about this either. Note that both these
      ## config attempts come directly from the git-config man page:
      ## http://www.kernel.org/pub/software/scm/git/docs/git-config.html
      ## export GIT_SSL_KEY=/home/delano/.ssh/id_rsa
      ## rbox.setenv("GIT_SSL_KEY", "#{homedir}/.ssh/#{key}")
      
      if rbox.file_exists?('.ssh/config')
        rbox.cp('.ssh/config', ".ssh/config-previous")
        ssh_config = rbox.download('.ssh/config')
      end
      
      ssh_config ||= StringIO.new
      ssh_config.puts $/, "IdentityFile #{homedir}/.ssh/#{key}"
      puts "  Adding IdentityFile #{key} to #{homedir}/.ssh/config"
      
      rbox.upload(ssh_config, '.ssh/config')
      rbox.chmod('0600', '.ssh/config')
      
    end
    
    # We need to add the host keys to the user's known_hosts file
    # to prevent the git commands from failing when it raises the
    # "Host key verification failed." messsage.
    if rbox.file_exists?('.ssh/known_hosts')
      rbox.cp('.ssh/known_hosts', ".ssh/known_hosts-previous")
      known_hosts = rbox.download('.ssh/known_hosts')
    end
    known_hosts ||= StringIO.new
    remote = get_remote_uri
    host = URI.parse(remote).host rescue nil
    host ||= remote.scan(/\A.+?@(.+?)\:/).flatten.first
    known_hosts.puts $/, Rye.remote_host_keys(host)
    puts "  Adding host key for #{host} to .ssh/known_hosts"

    rbox.upload(known_hosts, '.ssh/known_hosts')
    rbox.chmod('0600', '.ssh/known_hosts')

    execute_rbox_command {
      rbox.git('clone', get_remote_uri, @path)
    }
    rbox.cd(@path)
    execute_rbox_command {
      rbox.git('checkout', :b, @rtag)
    }
  rescue Rye::CommandError => ex
    puts ex.message
  ensure
    # Return to the original user and directory
    rbox.switch_user(original_user)
    rbox.cd
  end
  
end

#delete_rtag(rtag = nil) ⇒ Object



70
71
72
73
74
75
76
77
78
# File 'lib/rudy/scm/git.rb', line 70

def delete_rtag(rtag=nil)
  rtag ||= @rtag
  ret = execute_rbox_command { Rye.shell(:git, 'tag', :d, rtag) }
  raise ret.stderr.join($/) if ret.exit_code > 0 # TODO: retest
  # Equivalent to: "git push origin :tag-name" which deletes a remote tag
  ret = execute_rbox_command { Rye.shell(:git, "push #{@remote} :#{rtag}") } if @remote
  raise ret.stderr.join($/) if ret.exit_code > 0
  true
end

#engineObject



38
# File 'lib/rudy/scm/git.rb', line 38

def engine; :git; end

#find_next_rtag(username = nil) ⇒ Object

rel-2009-03-05-user-rev

Raises:



58
59
60
61
62
63
64
65
66
67
68
# File 'lib/rudy/scm/git.rb', line 58

def find_next_rtag(username=nil)
  now = Time.now
  mon = now.mon.to_s.rjust(2, '0')
  day = now.day.to_s.rjust(2, '0')
  rev = "01"
  criteria = ['rel', now.year, mon, day, rev]
  criteria.insert(-2, username) if username
  rev.succ! while valid_rtag?(criteria.join(Rudy::DELIM)) && rev.to_i < 50
  raise TooManyTags if rev.to_i >= 50
  criteria.join(Rudy::DELIM)
end

#get_remote_uriObject



165
166
167
168
# File 'lib/rudy/scm/git.rb', line 165

def get_remote_uri
  ret = Rye.shell(:git, "config", "remote.#{@remote}.url")
  ret.stdout.first
end

#liner_noteObject



40
41
42
# File 'lib/rudy/scm/git.rb', line 40

def liner_note
  "%-40s  (git:%s:%s)" % [@rtag, @remote, @branch]
end

#raise_early_exceptionsObject

Raises:



199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
# File 'lib/rudy/scm/git.rb', line 199

def raise_early_exceptions
  raise NotAWorkingCopy, :git unless working_copy?
  raise DirtyWorkingCopy, :git unless @changes.to_s == 'ignore' || clean_working_copy?
  raise NoRemoteURI, "remote.#{@remote}.url not set" if get_remote_uri.nil?
  raise NoRemotePath, :git if @path.nil?
  raise PrivateKeyNotFound, @pkey if @pkey && !File.exists?(@pkey)
  find_next_rtag # will raise exception is there's a problem
  
  # We can't check stuff that requires access to the machine b/c the 
  # machine may not be running yet. These include:
  # * Remote checkout path already exists
  # * No git available
  # ...
  # If create_remote_checkout should fail, it should print a message
  # about the release that was created and how to install it manually
end

#valid_rtag?(tag) ⇒ Boolean

Check if the given remote is valid. def has_remote?(remote)

success = false
(@repo.remotes || []).each do |r|
end
success

end

Returns:

  • (Boolean)


178
179
180
181
182
183
184
185
186
# File 'lib/rudy/scm/git.rb', line 178

def valid_rtag?(tag)
  # git tag -l tagname returns a 0 exit code and stdout is empty
  # when a tag does not exit. When it does exist, the exit code
  # is 0 and stdout contains the tagname. 
  ret = Rye.shell(:git, 'tag', :l, tag)  
  # change :l to :d for quick deleting above and return true
  # OR: just change to :d to always recreate the same tag
  (ret.exit_code == 0 && ret.stdout.to_s == tag)
end

#working_copy?Boolean

Returns:

  • (Boolean)


197
# File 'lib/rudy/scm/git.rb', line 197

def working_copy?; GIT.working_copy?; end