GitHub APIは大変よくできていて、Gitのさまざまな操作をAPI経由で行うことができる。
スマートフォンなどのgitがインストールしにくい環境であっても、GitHubからプログラムをクローンしたりコミットすることが可能になる。これは素晴らしいのでまずはレポジトリのクローンから試してみることにした。
レポジトリの取得
ongaeshi/tango: Flashcard for RubyPico から。GitHubのAPIは分かりやすくてurlの項目を数珠つなぎに見ていけば目的のデータを取得できる。
$ curl https://api.github.com/repos/ongaeshi/tango/git/trees/master?recursive=1
{
"sha": "f5ef6ef11cba6ad1654e04631395e5758d5ad6f2",
"url": "https://api.github.com/repos/ongaeshi/tango/git/trees/f5ef6ef11cba6ad1654e04631395e5758d5ad6f2",
"tree": [
{
"path": ".gitignore",
"mode": "100644",
"type": "blob",
"sha": "d045bfa4618473ed28e1fa157d6fda40ccc1059a",
"size": 9,
"url": "https://api.github.com/repos/ongaeshi/tango/git/blobs/d045bfa4618473ed28e1fa157d6fda40ccc1059a"
},
{
"path": "README.md",
"mode": "100644",
"type": "blob",
"sha": "17092b70377aec764a6bc3ce9b8bf891ff407737",
"size": 279,
"url": "https://api.github.com/repos/ongaeshi/tango/git/blobs/17092b70377aec764a6bc3ce9b8bf891ff407737"
},
{
"path": "cli.rb",
"mode": "100644",
"type": "blob",
"sha": "55a1a4266ddfde1833582afcf7408e045d63ba2d",
"size": 1075,
"url": "https://api.github.com/repos/ongaeshi/tango/git/blobs/55a1a4266ddfde1833582afcf7408e045d63ba2d"
},
.
.
],
"truncated": false
}
treeの取得
各ファイルやディレクトリの情報。例としてcli.rb
のtreeを取り出す。
$ curl https://api.github.com/repos/ongaeshi/tango/git/blobs/55a1a4266ddfde1833582afcf7408e045d63ba2d
{
"sha": "55a1a4266ddfde1833582afcf7408e045d63ba2d",
"size": 1075,
"url": "https://api.github.com/repos/ongaeshi/tango/git/blobs/55a1a4266ddfde1833582afcf7408e045d63ba2d",
"content": "cmVxdWlyZSAidGFuZ28vanNvbl9maWxlIgpyZXF1aXJlICJ0YW5nby93b3Jk\ncyIKCm1vZHVsZSBUYW5nbwogIGNsYXNzIENsaQogICAgZGVmIGluaXRpYWxp\nemUKICAgICAgQGpzb24gPSBKc29uRmlsZS5uZXcoIndvcmQuanNvbiIpCiAg\nICAgIEB3b3JkcyA9IFdvcmRzLm5ldyhAanNvbikKICAgIGVuZAogICAgCiAg\nICBkZWYgbWFpbmxvb3AKICAgICAgbG9vcCBkbwogICAgICAgIGNvbW1hbmQg\nPSBwcm9tcHQKCiAgICAgICAgY2FzZSBjb21tYW5kCiAgICAgICAgd2hlbiAv\nXmwvCiAgICAgICAgICBsaXN0KGNvbW1hbmQuc3BsaXRbMS4uLTFdKQogICAg\nICAgIHdoZW4gL15ybS8KICAgICAgICAgIHJtKGNvbW1hbmQuc3BsaXRbMS4u\nLTFdKQogICAgICAgIHdoZW4gInQiCiAgICAgICAgd2hlbiAiaCIKICAgICAg\nICAgIGhlbHAKICAgICAgICBlbHNlCiAgICAgICAgICBhZGQoY29tbWFuZCkK\nICAgICAgICBlbmQKICAgICAgZW5kCiAgICBlbmQKICAgIAogICAgZGVmIGFk\nZChjb21tYW5kKQogICAgICBjbWRzID0gY29tbWFuZC5zcGxpdCgiICIpCgog\nICAgICBAd29yZHMuYWRkX29yX3VwZGF0ZShjbWRzWzBdLCBjbWRzWzFdKQog\nICAgICBAd29yZHMuc2F2ZQogICAgZW5kCiAgICAgIAogICAgZGVmIGxpc3Qo\nYXJncykKICAgICAgd29yZHMgPSBAd29yZHMudG9fYQogICAgICB3b3JkcyA9\nIHdvcmRzLnNvcnRfYnkgeyB8ZXwgZS51cGRhdGVkX2F0IH0ucmV2ZXJzZQog\nICAgICAKICAgICAgd29yZHMuZWFjaCBkbyB8ZXwKICAgICAgICBpZiBhcmdz\nLmVtcHR5PwogICAgICAgICAgcHV0cyBlLmFzdHIKICAgICAgICBlbHNlCiAg\nICAgICAgICBwdXRzIGUuYXN0ciBpZiBlLndvcmQuaW5jbHVkZT8gYXJnc1sw\nXQogICAgICAgIGVuZAogICAgICBlbmQKICAgIGVuZAogICAgCiAgICBkZWYg\ncm0oYXJncykKICAgICAgYXJncy5lYWNoIGRvIHxlfAogICAgICAgIHIgPSBA\nd29yZHMucm0gZQogICAgICAgIHB1dHMgIk5vdCBmb3VuZCAje2V9IiB1bmxl\nc3MgcgogICAgICBlbmQKICAgICAgCiAgICAgIEB3b3Jkcy5zYXZlCiAgICBl\nbmQKICAgIAogICAgZGVmIGhlbHAKICAgIGVuZAogIGVuZAplbmQKCg==\n",
"encoding": "base64"
}
contentの変換
base64エンコーディングされているのでデコードすれば中身を取り出すことができる。以下は雑なRubyスクリプト。
require 'base64'
str = "cmVxdWlyZSAidGFuZ28vanNvbl9maWxlIgpyZXF1aXJlICJ0YW5nby93b3Jk\ncyIKCm1vZHVsZSBUYW5nbwogIGNsYXNzIENsaQogICAgZGVmIGluaXRpYWxp\nemUKICAgICAgQGpzb24gPSBKc29uRmlsZS5uZXcoIndvcmQuanNvbiIpCiAg\nICAgIEB3b3JkcyA9IFdvcmRzLm5ldyhAanNvbikKICAgIGVuZAogICAgCiAg\nICBkZWYgbWFpbmxvb3AKICAgICAgbG9vcCBkbwogICAgICAgIGNvbW1hbmQg\nPSBwcm9tcHQKCiAgICAgICAgY2FzZSBjb21tYW5kCiAgICAgICAgd2hlbiAv\nXmwvCiAgICAgICAgICBsaXN0KGNvbW1hbmQuc3BsaXRbMS4uLTFdKQogICAg\nICAgIHdoZW4gL15ybS8KICAgICAgICAgIHJtKGNvbW1hbmQuc3BsaXRbMS4u\nLTFdKQogICAgICAgIHdoZW4gInQiCiAgICAgICAgd2hlbiAiaCIKICAgICAg\nICAgIGhlbHAKICAgICAgICBlbHNlCiAgICAgICAgICBhZGQoY29tbWFuZCkK\nICAgICAgICBlbmQKICAgICAgZW5kCiAgICBlbmQKICAgIAogICAgZGVmIGFk\nZChjb21tYW5kKQogICAgICBjbWRzID0gY29tbWFuZC5zcGxpdCgiICIpCgog\nICAgICBAd29yZHMuYWRkX29yX3VwZGF0ZShjbWRzWzBdLCBjbWRzWzFdKQog\nICAgICBAd29yZHMuc2F2ZQogICAgZW5kCiAgICAgIAogICAgZGVmIGxpc3Qo\nYXJncykKICAgICAgd29yZHMgPSBAd29yZHMudG9fYQogICAgICB3b3JkcyA9\nIHdvcmRzLnNvcnRfYnkgeyB8ZXwgZS51cGRhdGVkX2F0IH0ucmV2ZXJzZQog\nICAgICAKICAgICAgd29yZHMuZWFjaCBkbyB8ZXwKICAgICAgICBpZiBhcmdz\nLmVtcHR5PwogICAgICAgICAgcHV0cyBlLmFzdHIKICAgICAgICBlbHNlCiAg\nICAgICAgICBwdXRzIGUuYXN0ciBpZiBlLndvcmQuaW5jbHVkZT8gYXJnc1sw\nXQogICAgICAgIGVuZAogICAgICBlbmQKICAgIGVuZAogICAgCiAgICBkZWYg\ncm0oYXJncykKICAgICAgYXJncy5lYWNoIGRvIHxlfAogICAgICAgIHIgPSBA\nd29yZHMucm0gZQogICAgICAgIHB1dHMgIk5vdCBmb3VuZCAje2V9IiB1bmxl\nc3MgcgogICAgICBlbmQKICAgICAgCiAgICAgIEB3b3Jkcy5zYXZlCiAgICBl\nbmQKICAgIAogICAgZGVmIGhlbHAKICAgIGVuZAogIGVuZAplbmQKCg==\n"
puts Base64.decode64 str
結果
require "tango/json_file"
require "tango/words"
module Tango
class Cli
def initialize
@json = JsonFile.new("word.json")
@words = Words.new(@json)
end
def mainloop
loop do
command = prompt
case command
when /^l/
list(command.split[1..-1])
when /^rm/
rm(command.split[1..-1])
when "t"
when "h"
help
else
add(command)
end
end
end
def add(command)
cmds = command.split(" ")
@words.add_or_update(cmds[0], cmds[1])
@words.save
end
def list(args)
words = @words.to_a
words = words.sort_by { |e| e.updated_at }.reverse
words.each do |e|
if args.empty?
puts e.astr
else
puts e.astr if e.word.include? args[0]
end
end
end
def rm(args)
args.each do |e|
r = @words.rm e
puts "Not found #{e}" unless r
end
@words.save
end
def help
end
end
end
残り
- treeをたどる
- treeだったらディレクトリ作成
- blobだったらcontentをbase64デコードして内容をファイルに書き出し
だれかすでに書いてそうだなぁ。探してみよう。
mrubyで動かすには
mrubyで動くようになればRubyPicoでもできるようになるはず。
GETはすでにBrowser.get
でできるようになっているので、あとはbase64。
mruby-base64 mgemを追加すればよさそう。今回もmattnさんに足を向けて寝られない結果となりました。