diff --git a/src/services.ts b/src/services.ts index 0c926eca..62a8fdac 100644 --- a/src/services.ts +++ b/src/services.ts @@ -19,7 +19,10 @@ export interface GHSession extends GHRepoMetadata { reponame : string; // repo name repopath : string; // "user/repo" prefix : string; // file prefix, "local/" or "" + branch : string; // "master" is default repo : any; // [repo object] + tree? : any; // [tree object] + head? : any; // [head ref] paths? : string[]; } @@ -30,11 +33,12 @@ export function getRepos() : {[key:string]:GHRepoMetadata} { } export function parseGithubURL(ghurl:string) { - var toks = ghurl.split('/'); + var toks = ghurl.split('/', 8); if (toks.length < 5) return null; if (toks[0] != 'https:') return null; if (toks[2] != 'github.com') return null; - return {user:toks[3], repo:toks[4], repopath:toks[3]+'/'+toks[4]}; + if (toks[5] && toks[5] != 'tree') return null; + return {user:toks[3], repo:toks[4], repopath:toks[3]+'/'+toks[4], branch:toks[6], treepath:toks[7]}; } export class GithubService { @@ -44,7 +48,6 @@ export class GithubService { github; store; project : CodeProject; - branch : string = "master"; constructor(githubCons:() => any, githubToken:string, store, project : CodeProject) { this.githubCons = githubCons; @@ -99,6 +102,7 @@ export class GithubService { user: urlparse.user, reponame: urlparse.repo, repopath: urlparse.repopath, + branch: urlparse.branch || "master", prefix: '', //this.getPrefix(urlparse.user, urlparse.repo), repo: this.github.repos(urlparse.user, urlparse.repo), platform_id: this.project ? this.project.platform_id : null @@ -106,6 +110,22 @@ export class GithubService { yes(sess); }); } + + getGithubHEADTree(ghurl:string) : Promise { + var sess; + return this.getGithubSession(ghurl).then( (session) => { + sess = session; + return sess.repo.git.refs.heads(sess.branch).fetch(); + }) + .then( (head) => { + sess.head = head; + return sess.repo.git.trees(head.object.sha).fetch(); + }) + .then( (tree) => { + sess.tree = tree; + return sess; + }); + } bind(sess:GHSession, dobind:boolean) { var repos = getRepos(); @@ -157,17 +177,11 @@ export class GithubService { pull(ghurl:string, deststore?) : Promise { var sess : GHSession; - return this.getGithubSession(ghurl).then( (session) => { + return this.getGithubHEADTree(ghurl).then( (session) => { sess = session; - return sess.repo.commits(this.branch).fetch(); - }) - .then( (sha) => { - return sess.repo.git.trees(sha.sha).fetch(); - }) - .then( (tree) => { let blobreads = []; sess.paths = []; - tree.tree.forEach( (item) => { + sess.tree.tree.forEach( (item) => { console.log(item.path, item.type, item.size); sess.paths.push(item.path); if (item.type == 'blob' && !this.isFileIgnored(item.path)) { @@ -238,33 +252,23 @@ export class GithubService { commitPush( ghurl:string, message:string, files:{path:string,data:FileData}[] ) : Promise { var sess : GHSession; - var repo; - var head; - var tree; - return this.getGithubSession(ghurl).then( (session) => { + return this.getGithubHEADTree(ghurl).then( (session) => { sess = session; - repo = sess.repo; - return repo.git.refs.heads(this.branch).fetch(); - }).then( (_head) => { - head = _head; - return repo.git.trees(head.object.sha).fetch(); - }).then( (_tree) => { - tree = _tree; return Promise.all(files.map( (file) => { if (typeof file.data === 'string') { - return repo.git.blobs.create({ + return sess.repo.git.blobs.create({ content: file.data, encoding: 'utf-8' }); } else { - return repo.git.blobs.create({ + return sess.repo.git.blobs.create({ content: btoa(byteArrayToString(file.data)), encoding: 'base64' }); } })); }).then( (blobs) => { - return repo.git.trees.create({ + return sess.repo.git.trees.create({ tree: files.map( (file, index) => { return { path: file.path, @@ -273,18 +277,18 @@ export class GithubService { sha: blobs[index]['sha'] }; }), - base_tree: tree.sha + base_tree: sess.tree.sha }); - }).then( (tree) => { - return repo.git.commits.create({ + }).then( (newtree) => { + return sess.repo.git.commits.create({ message: message, - tree: tree.sha, + tree: newtree.sha, parents: [ - head.object.sha + sess.head.object.sha ] }); }).then( (commit) => { - return repo.git.refs.heads(this.branch).update({ + return sess.head.update({ sha: commit.sha }); }).then( (update) => { diff --git a/test/cli/testgithub.js b/test/cli/testgithub.js index 6174a008..6ef58325 100644 --- a/test/cli/testgithub.js +++ b/test/cli/testgithub.js @@ -65,6 +65,17 @@ describe('Store', function() { }); }); + it('Should import from Github (subdirectory tree)', function(done) { + var store = mstore.createNewPersistentStore('nes', function(store) { + var gh = newGH(store, 'nes'); + gh.importAndPull('https://github.com/brovador/NESnake/tree/master/src').then( (sess) => { + console.log(sess.paths); + assert.equal(5, sess.paths.length); + done(); + }); + }); + }); + it('Should publish (fail) on Github', function(done) { var store = mstore.createNewPersistentStore(test_platform_id, function(store) { var gh = newGH(store); @@ -113,7 +124,7 @@ describe('Store', function() { assert.deepEqual(serv.getRepos(), {'foo/bar':{url:'_',platform_id:'vcs',mainPath:'test.c'}}); gh.bind(sess, false); assert.deepEqual(serv.getRepos(), {}); - gh.getGithubSession('https://github.com/foo/bar/baz').then((sess) => { + gh.getGithubSession('https://github.com/foo/bar/tree').then((sess) => { assert.equal(sess.url, 'https://github.com/foo/bar'); assert.equal(sess.repopath, 'foo/bar'); done();