Class: Amp::Repositories::HTTPRepository
- Inherits:
-
Repository
- Object
- Repository
- Amp::Repositories::HTTPRepository
- Includes:
- Amp::RevlogSupport::Node
- Defined in:
- lib/amp/repository/repositories/http_repository.rb
Overview
This is the class for connecting to an HTTP-based repository.
The protocol’s pretty simple - just ?cmd=“command”, and any other args you need. Should be pretty easy.
Direct Known Subclasses
Constant Summary collapse
Constants included from Amp::RevlogSupport::Node
Amp::RevlogSupport::Node::NULL_ID, Amp::RevlogSupport::Node::NULL_REV
Instance Attribute Summary collapse
-
#secure ⇒ Object
Should the repository connect via SSL?.
-
#url ⇒ Object
readonly
The URL we connect to for this repository.
Instance Method Summary collapse
-
#between(pairs) ⇒ Array<Array<String>>
For each provided pair of nodes, return the nodes between the pair.
-
#branches(nodes) ⇒ Array<Array<String>>
Gets the node IDs of all the branch roots in the repository.
-
#changegroup(nodes, kind) ⇒ StringIO
Asks the server to bundle up the given nodes into a changegroup, and returns it uncompressed.
-
#changegroup_subset(bases, heads, source) ⇒ StringIO
Asks the server to bundle up all the necessary nodes between the lists bases and heads.
-
#get_capabilities ⇒ Hash
Loads the capabilities from the server when necessary.
-
#heads ⇒ Array<String>
Gets all the heads of the repository.
-
#initialize(path = "", create = false, config = nil) ⇒ HTTPRepository
constructor
Standard initializer for a repository.
-
#local? ⇒ Boolean
Returns whether the repository is local or not.
-
#lock ⇒ Object
Unsupported - raises an error.
-
#lookup(key) ⇒ String
Looks up a node with the given key.
- #stream_out ⇒ Object
-
#unbundle(cg, heads, source) ⇒ Fixnum
Sends a bundled up changegroup to the server, who will add it to its repository.
Methods included from Amp::RevlogSupport::Node
Methods inherited from Repository
#add_path, #can_copy?, #capable?, #require_capability
Constructor Details
#initialize(path = "", create = false, config = nil) ⇒ HTTPRepository
Standard initializer for a repository. However, “create” is a no-op.
48 49 50 51 52 |
# File 'lib/amp/repository/repositories/http_repository.rb', line 48 def initialize(path="", create=false, config=nil) @url, @config = URI.parse(path), config @auth_mode = :none raise InvalidArgumentError.new("Invalid URL for an HTTP repo!") if @url.nil? end |
Instance Attribute Details
#secure ⇒ Object
Should the repository connect via SSL?
33 34 35 |
# File 'lib/amp/repository/repositories/http_repository.rb', line 33 def secure @secure end |
#url ⇒ Object (readonly)
The URL we connect to for this repository
29 30 31 |
# File 'lib/amp/repository/repositories/http_repository.rb', line 29 def url @url end |
Instance Method Details
#between(pairs) ⇒ Array<Array<String>>
For each provided pair of nodes, return the nodes between the pair.
add lstrip to split_newlines to fix but not cure bug
228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 |
# File 'lib/amp/repository/repositories/http_repository.rb', line 228 def between(pairs) batch = 8 ret = [] (0..(pairs.size)).step(batch) do |i| n = pairs[i..(i+batch-1)].map {|p| p.map {|k| k.hexlify }.join("-") }.join(" ") d, code = *do_read("between", :pairs => n) raise RepoError.new("unexpected code: #{code}") unless code == 200 ret += d.lstrip.split_newlines.map {|l| (l && l.split(" ").map{|i| i.unhexlify }) || []} end Amp::UI.debug "between returns: #{ret.inspect}" ret end |
#branches(nodes) ⇒ Array<Array<String>>
Gets the node IDs of all the branch roots in the repository. Uses the supplied nodes to use to search for branches.
120 121 122 123 124 125 126 |
# File 'lib/amp/repository/repositories/http_repository.rb', line 120 def branches(nodes) n = nodes.map {|n| n.hexlify }.join(" ") data = do_read("branches", :nodes => n).first data.split("\n").map do |b| b.split(" ").map {|b| b.unhexlify} end end |
#changegroup(nodes, kind) ⇒ StringIO
figure out what the kind
parameter is for
Asks the server to bundle up the given nodes into a changegroup, and returns it uncompressed. This is for pulls.
136 137 138 139 140 141 142 143 144 |
# File 'lib/amp/repository/repositories/http_repository.rb', line 136 def changegroup(nodes, kind) n = nodes.map{|i| i.hexlify }.join ' ' f = do_read('changegroup', n.empty? ? {} : {:roots => n}).first s = StringIO.new "",(ruby_19? ? "w+:ASCII-8BIT" : "w+") s.write Zlib::Inflate.inflate(f) s.pos = 0 s end |
#changegroup_subset(bases, heads, source) ⇒ StringIO
Asks the server to bundle up all the necessary nodes between the lists bases and heads. It is returned as a stream that reads it in a decompressed fashion. This is for pulls.
157 158 159 160 161 162 163 164 165 166 167 168 |
# File 'lib/amp/repository/repositories/http_repository.rb', line 157 def changegroup_subset(bases, heads, source) #require_capability 'changegroupsubset', 'look up remote changes' base_list = bases.map {|n| n.hexlify }.join ' ' head_list = heads.map {|n| n.hexlify }.join ' ' # p base_list, head_list f, code = *do_read("changegroupsubset", :bases => base_list, :heads => head_list) s = StringIO.new "",(ruby_19? ? "w+:ASCII-8BIT" : "w+") s.write Zlib::Inflate.inflate(f) s.rewind s end |
#get_capabilities ⇒ Hash
Loads the capabilities from the server when necessary. (Lazy loading)
or
{ capability => "capability;settings;"}
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 |
# File 'lib/amp/repository/repositories/http_repository.rb', line 61 def get_capabilities return @capabilities if @capabilities begin @capabilities = {} do_read("capabilities").first.split.each do |k| if k.include? "=" key, value = k.split("=", 2) @capabilities[key] = value else @capabilities[k] = true end end rescue @capabilities = [] end @capabilities end |
#heads ⇒ Array<String>
Gets all the heads of the repository. Returned in binary form.
105 106 107 108 |
# File 'lib/amp/repository/repositories/http_repository.rb', line 105 def heads data = do_read("heads").first data.chomp.split(" ").map {|h| h.unhexlify } end |
#local? ⇒ Boolean
Returns whether the repository is local or not. Which it isn’t. Because we’re connecting over HTTP.
40 |
# File 'lib/amp/repository/repositories/http_repository.rb', line 40 def local?; false; end |
#lock ⇒ Object
Unsupported - raises an error.
81 |
# File 'lib/amp/repository/repositories/http_repository.rb', line 81 def lock; raise RepoError.new("You can't lock an HTTP repo."); end |
#lookup(key) ⇒ String
Looks up a node with the given key. The key could be a node ID (full or partial), an index number (though this is slightly risky as it might match a node ID partially), “tip”, and so on. See LocalRepository#[].
91 92 93 94 95 96 97 98 |
# File 'lib/amp/repository/repositories/http_repository.rb', line 91 def lookup(key) require_capability("lookup", "Look up Remote Revision") data = do_read("lookup", :key => key).first code, data = data.chomp.split(" ", 2) return data.unhexlify if code.to_i > 0 raise RepoError.new("Unknown Revision #{data}") end |
#stream_out ⇒ Object
216 217 218 |
# File 'lib/amp/repository/repositories/http_repository.rb', line 216 def stream_out do_cmd 'stream_out' end |
#unbundle(cg, heads, source) ⇒ Fixnum
Sends a bundled up changegroup to the server, who will add it to its repository. Uses the bundle format.
178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 |
# File 'lib/amp/repository/repositories/http_repository.rb', line 178 def unbundle(cg, heads, source) # have to stream bundle to a temp file because we do not have # http 1.1 chunked transfer type = '' types = capable? 'unbundle' # servers older than d1b16a746db6 will send 'unbundle' as a boolean # capability # this will be a list of allowed bundle compression types types = types.split ',' rescue [''] # pick a compression format types.each do |x| (type = x and break) if RevlogSupport::ChangeGroup::BUNDLE_HEADERS.include? x end # compress and create the bundle data = RevlogSupport::ChangeGroup.write_bundle cg, type # send the data resp = do_read 'unbundle', :data => data.string, :headers => {'Content-Type' => 'application/octet-stream'}, :heads => heads.map{|h| h.hexlify }.join(' ') # parse output resp_code, output = resp.first.split "\n" # make sure the reponse was in an expected format (i.e. with a response code) unless resp_code.to_i.to_s == resp_code raise abort("push failed (unexpected response): #{resp}") end # output any text from the server UI::say output # return 1 for success, 0 for failure resp_code.to_i end |