Begin replication of host repo state

This commit is contained in:
Corey Johnson & Kevin Sawicki
2013-07-10 15:42:32 -07:00
committed by Kevin Sawicki
parent 601efa53e6
commit 72d76e511e
5 changed files with 115 additions and 37 deletions

View File

@@ -11,7 +11,7 @@
"ctags": "0.5.0",
"oniguruma": "0.16.0",
"mkdirp": "0.3.5",
"git-utils": "0.19.0",
"git-utils": "0.21.0",
"underscore": "1.4.4",
"d3": "3.0.8",
"coffee-cache": "0.1.0",

View File

@@ -215,6 +215,12 @@ class Git
getConfigValue: (key) -> @getRepo().getConfigValue(key)
getReferenceTarget: (reference) -> @getRepo().getReferenceTarget(reference)
getAheadBehindCount: (reference) -> @getRepo().getAheadBehindCount(reference)
hasBranch: (branch) -> @getReferenceTarget("refs/heads/#{branch}")?
### Internal ###
refreshStatus: ->

View File

@@ -1,10 +1,15 @@
require 'atom'
require 'window'
{exec} = require 'child_process'
fs = require 'fs'
remote = require 'remote'
path = require 'path'
url = require 'url'
require 'atom'
require 'window'
$ = require 'jquery'
temp = require 'temp'
{$$} = require 'space-pen'
Git = require 'git'
GuestSession = require './guest-session'
window.setDimensions(width: 350, height: 100)
@@ -19,14 +24,41 @@ atom.show()
syncRepositoryState = ->
repoUrl = atom.guestSession.repository.get('url')
branch = atom.guestSession.repository.get('branch')
[repoName] = url.parse(repoUrl).path.split('/')[-1..]
repoName = repoName.replace(/\.git$/, '')
repoPath = path.join(remote.require('app').getHomeDir(), 'github', repoName)
git = new Git(repoPath)
# clone if missing
# clone or fetch
# abort if working directory is unclean
# apply bundle of unpushed changes from host
# prompt for branch name if branch already exists and is cannot be fast-forwarded
{unpushedChanges, head} =atom.guestSession.repositoryDelta
if unpushedChanges
tempFile = temp.path(suffix: '.bundle')
fs.writeFileSync(tempFile, new Buffer(atom.guestSession.repositoryDelta.unpushedChanges, 'base64'))
command = "git bundle unbundle #{tempFile}"
exec command, {cwd: repoPath}, (error, stdout, stderr) ->
if error?
console.error error
return
if git.hasBranch(branch)
if git.getAheadBehindCount(branch).ahead is 0
command = "git checkout #{branch} && git reset --hard #{head}"
exec command, {cwd: repoPath}, (error, stdout, stderr) ->
if error?
console.error error
return
else
# prompt for new branch name
# create branch at head
else
# create branch at head
# create branch if it doesn't exist
# prompt for branch name if branch already exists and it cannot be fast-forwarded
# checkout branch
# sync modified and untracked files from host session

View File

@@ -16,13 +16,14 @@ class GuestSession
connection.on 'open', =>
console.log 'connection opened'
connection.once 'data', (data) =>
console.log 'received document'
doc = telepath.Document.deserialize(data, site: telepath.createSite(@getId()))
console.log 'received document', data
@repositoryDelta = data.repositoryDelta
doc = telepath.Document.deserialize(data.doc, site: telepath.createSite(@getId()))
atom.windowState = doc.get('windowState')
@participants = doc.get('collaborationState.participants')
@participants.on 'changed', =>
@trigger 'participants-changed', @participants.toObject()
@repository = doc.get('collaborationState.repository')
@repository = doc.get('collaborationState.repositoryState')
connectDocument(doc, connection)
@trigger 'started'

View File

@@ -1,4 +1,7 @@
fs = require 'fs'
_ = require 'underscore'
async = require 'async'
temp = require 'temp'
telepath = require 'telepath'
{createPeer, connectDocument} = require './session-utils'
@@ -11,46 +14,82 @@ class HostSession
peer: null
sharing: false
bundleUnpushedChanges: (callback) ->
localBranch = git.getShortHead()
upstreamBranch = git.getRepo().getUpstreamBranch()
{exec} = require 'child_process'
tempFile = temp.path(suffix: '.bundle')
command = "git bundle create #{tempFile} #{upstreamBranch}..#{localBranch}"
exec command, {cwd: git.getWorkingDirectory()}, (error, stdout, stderr) ->
callback(error, tempFile)
bundleWorkingDirectoryChanges: ->
bundleRepositoryDelta: (callback) ->
repositoryDelta = {}
operations = []
if git.upstream.ahead > 0
operations.push (callback) =>
@bundleUnpushedChanges (error, bundleFile) ->
unless error?
repositoryDelta.unpushedChanges = fs.readFileSync(bundleFile, 'base64')
repositoryDelta.head = git.getRepo().getReferenceTarget(git.getRepo().getHead())
callback(error)
async.waterfall operations, (error) ->
callback(error, repositoryDelta)
unless _.isEmpty(git.statuses)
repositoryDelta.workingDirectoryChanges = @bundleWorkingDirectoryChanges()
start: ->
return if @peer?
@peer = createPeer()
@doc = telepath.Document.create({}, site: telepath.createSite(@getId()))
@doc.set('windowState', atom.windowState)
@doc.set 'collaborationState',
participants: []
repository:
url: git.getConfigValue('remote.origin.url')
branch: git.getShortHead()
@bundleRepositoryDelta (error, repositoryDelta) =>
if error?
console.error(error)
return
@participants = @doc.get('collaborationState.participants')
@participants.push
id: @getId()
email: git.getConfigValue('user.email')
@participants.on 'changed', =>
@trigger 'participants-changed', @participants.toObject()
@doc.set 'collaborationState',
participants: []
repositoryState:
url: git.getConfigValue('remote.origin.url')
branch: git.getShortHead()
@peer.on 'connection', (connection) =>
connection.on 'open', =>
console.log 'sending document'
connection.send(@doc.serialize())
connectDocument(@doc, connection)
@participants = @doc.get('collaborationState.participants')
@participants.push
id: @getId()
email: git.getConfigValue('user.email')
@participants.on 'changed', =>
@trigger 'participants-changed', @participants.toObject()
connection.on 'close', =>
console.log 'conection closed'
@participants.each (participant, index) =>
if connection.peer is participant.get('id')
@participants.remove(index)
@peer.on 'connection', (connection) =>
connection.on 'open', =>
console.log 'sending document'
connection.send({repositoryDelta, doc: @doc.serialize()})
connectDocument(@doc, connection)
@peer.on 'open', =>
console.log 'sharing session started'
@sharing = true
@trigger 'started'
connection.on 'close', =>
console.log 'conection closed'
@participants.each (participant, index) =>
if connection.peer is participant.get('id')
@participants.remove(index)
@peer.on 'close', =>
console.log 'sharing session stopped'
@sharing = false
@trigger 'stopped'
@peer.on 'open', =>
console.log 'sharing session started'
@sharing = true
@trigger 'started'
@peer.on 'close', =>
console.log 'sharing session stopped'
@sharing = false
@trigger 'stopped'
@getId()