コード
const Client = require('svn-spawn');
const client = new Client({
// ディレクトリがなければ作成される
cwd: __dirname + '/../target',
// 実行時に手動入力できるのでコードに載せなくても良い。
//username: 'username', // optional if authentication not required or is already saved
//password: 'password', // optional if authentication not required or is already saved
noAuthCache: true, // optional, if true, username does not become the logged in user on the machine
});
// targetディレクトリは作成されないので、cwdの方に新規ディレクトリを指定しないと混ざるので注意
client.checkout('http://repo/~/target');
実行すると、
> node .\checkout.js
Authentication realm: <http://repo:80> Kerberos Login
Password for 'khsk': ********
A hogehoge.txt
~~
Checked out revision xxxx.
とパスワードを聞いてくるので入力してやる。
ユーザー名はたぶん普段遣いのSVNの記録から読み込んでいると思われる。パスワードを間違えればUsernameからの入力になるので、違うユーザーでチェックアウトしたいときも焦らない。
実行環境
- Windows7
- node v9.3.0
ライブラリ
Readmeにはcheckout
がなくて、client.cmd
からか…と凹んだが、念の為コードを検索すると
node-svn-spawn/svn.js at 59c4295e33403023f4e8a0e1fe34447a1cef9b5b · ddliu/node-svn-spawn
ちゃんと生えていた。
(peteward44/node-svn-ultimate: The ultimate SVN wrapper for node. Contains all the basic methods checkout, update, info, etc, and includes svnmucc supportを先に試したんですが、失敗したんですよね)
Promise化したい
await
大好きマンなので、コールバックはちょっと…
コールバック関数をPromise化して使う - Qiita
いいのがあった。
const Client = require('svn-spawn');
const {promisify} = require('util');
const client = new Client({
// ディレクトリがなければ作成される
cwd: __dirname + '/../target',
// 実行時に手動入力できるのでコードに載せなくても良い。
//username: 'username', // optional if authentication not required or is already saved
//password: 'password', // optional if authentication not required or is already saved
noAuthCache: true, // optional, if true, username does not become the logged in user on the machine
});
// targetディレクトリは作成されないので、cwdの方に新規ディレクトリを指定しないと混ざるので注意
(async () => {
await promisify(client.checkout)('http://repo/~/target');
})();
(node:7396) UnhandledPromiseRejectionWarning:TypeError: Cannot read property 'getOption' of undefin
ed at Client.checkout (~\node_modules\svn-spawn\lib\svn.js:4
0:20)
…
4行目ではないけれど
node-svn-spawn/svn.js at 59c4295e33403023f4e8a0e1fe34447a1cef9b5b · ddliu/node-svn-spawn
このthis.getOption
が問題な気がする。(util.inherits
初めてみた。継承らしい。)
this
の値が変わっちゃったのかな?
this
をclient
に戻してやればいいのかなーと.bind(client)
の位置をあれこれいじり、
const Client = require('svn-spawn');
const {promisify} = require('util');
const client = new Client({
// ディレクトリがなければ作成される
cwd: __dirname + '/../target',
// 実行時に手動入力できるのでコードに載せなくても良い。
//username: 'username', // optional if authentication not required or is already saved
//password: 'password', // optional if authentication not required or is already saved
noAuthCache: true, // optional, if true, username does not become the logged in user on the machine
});
// targetディレクトリは作成されないので、cwdの方に新規ディレクトリを指定しないと混ざるので注意
(async () => {
await promisify(client.checkout).bind(client)('http://repo/~/target');
})();
とした。
が、どうやらコールバックのときから、チェックアウトには成功するものの失敗扱いらしく、Rejectされるのでtry/catch
してやらないといけない。1
ついでにakamecoさん風ならawait/catch
。
というか今回は
- 同期処理(
await
)が目的 - 成功がエラーなので握りつぶす(邪悪)
なので、await/catch
の方が簡潔に握りつぶせると気づいた。
async関数においてtry/catchではなくawait/catchパターンを活用する - Qiita
(ちよ父すき)
つまり
(async () => {
try {
await promisify(client.checkout).bind(client)('http://repo/~/target');
} catch () {}
})();
// よりも
(async () => {
await promisify(client.checkout).bind(client)('http://repo/~/target').catch(() => {});
})();
ネストも行数も減るし見やすい。
(ちゃんとしたtry/catch
の場合は上下どちらにももう一段try/catch
が必要かな。上のtry/catch
は握りつぶすためのtry/catch
なので)
これでひとまず、チェックアウト後の処理をコールバックの中に書かずに済むようになった。
やっぱりexportも
同じフォルダにSVNから別のファイルを参照用に置きたくなった。
となると同一ディレクトリに別リポジトリはおけないので、エクスポートすることに。
exportは残念ながら実装されていないみたい
Issues · ddliu/node-svn-spawn
なので、結局コマンドで実行することに。
await promisify(client.cmd).bind(client)(['export','http://repo/~/targetfile']).catch(() => {});
と続けて書いてエクスポートした。
client
を使いまわしているので、ダウンロード先は同じcwd
になる。
-
普段から真面目に
try/catch
してる人なら出ない発言 ↩