Use patrick to mirror repository state

This commit is contained in:
Corey Johnson & Kevin Sawicki 2013-07-10 16:44:00 -07:00 committed by Kevin Sawicki
parent 33f538ebf4
commit 8812b6c31d
5 changed files with 50 additions and 114 deletions

View File

@ -36,6 +36,7 @@
"guid": "0.0.10",
"tantamount": "0.3.0",
"coffeestack": "0.4.0",
"patrick": "0.1.0",
"c-tmbundle": "1.0.0",
"coffee-script-tmbundle": "2.0.0",
"css-tmbundle": "1.0.0",

View File

@ -10,6 +10,28 @@ GitUtils = require 'git-utils'
# Ultimately, this is an overlay to the native [git-utils](https://github.com/atom/node-git) module.
module.exports =
class Git
### Public ###
# Creates a new `Git` instance.
#
# path - The git repository to open
# options - A hash with one key:
# refreshOnWindowFocus: A {Boolean} that identifies if the windows should refresh
#
# Returns a new {Git} object.
@open: (path, options) ->
return null unless path
try
new Git(path, options)
catch e
null
@exists: (path) ->
if git = @open(path)
git.destroy()
true
else
false
path: null
statuses: null
upstream: null
@ -57,20 +79,6 @@ class Git
### Public ###
# Creates a new `Git` instance.
#
# path - The git repository to open
# options - A hash with one key:
# refreshOnWindowFocus: A {Boolean} that identifies if the windows should refresh
#
# Returns a new {Git} object.
@open: (path, options) ->
return null unless path
try
new Git(path, options)
catch e
null
# Retrieves the git repository.
#
# Returns a new `Repository`.

View File

@ -1,15 +1,8 @@
require 'atom'
require 'window'
{exec} = require 'child_process'
fs = require 'fs'
remote = require 'remote'
path = require 'path'
url = require 'url'
$ = require 'jquery'
temp = require 'temp'
{$$} = require 'space-pen'
Git = require 'git'
GuestSession = require './guest-session'
window.setDimensions(width: 350, height: 100)
@ -22,60 +15,5 @@ loadingView = $$ ->
$(window.rootViewParentSelector).append(loadingView)
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 or fetch
# abort if working directory is unclean
# apply bundle of unpushed changes from host
{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
i = 1
loop
newBranch = "#{branch}-#{i++}"
break unless git.hasBranch(newBranch)
command = "git checkout -b #{newBranch} #{head}"
exec command, {cwd: repoPath}, (error, stdout, stderr) ->
if error?
console.error error
return
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
atom.getLoadSettings().initialPath = repoPath
atom.guestSession = new GuestSession(sessionId)
atom.guestSession.on 'started', ->
syncRepositoryState()
loadingView.remove()
window.startEditorWindow()
atom.guestSession.on 'started', -> loadingView.remove()

View File

@ -1,5 +1,11 @@
path = require 'path'
remote = require 'remote'
url = require 'url'
_ = require 'underscore'
patrick = require 'patrick'
telepath = require 'telepath'
{connectDocument, createPeer} = require './session-utils'
module.exports =
@ -17,17 +23,30 @@ class GuestSession
console.log 'connection opened'
connection.once 'data', (data) =>
console.log 'received document', data
@repositoryDelta = data.repositoryDelta
doc = telepath.Document.deserialize(data.doc, site: telepath.createSite(@getId()))
atom.windowState = doc.get('windowState')
@repository = doc.get('collaborationState.repositoryState')
@participants = doc.get('collaborationState.participants')
@participants.on 'changed', =>
@trigger 'participants-changed', @participants.toObject()
@repository = doc.get('collaborationState.repositoryState')
connectDocument(doc, connection)
@mirrorRepository(data.repoSnapshot)
mirrorRepository: (repoSnapshot)->
repoUrl = @repository.get('url')
[repoName] = url.parse(repoUrl).path.split('/')[-1..]
repoName = repoName.replace(/\.git$/, '')
repoPath = path.join(remote.require('app').getHomeDir(), 'github', repoName)
patrick.mirror repoPath, repoSnapshot, (error) =>
if error?
console.error(error)
else
@trigger 'started'
atom.getLoadSettings().initialPath = repoPath
window.startEditorWindow()
@participants.push
id: @getId()
email: git.getConfigValue('user.email')

View File

@ -1,8 +1,9 @@
fs = require 'fs'
_ = require 'underscore'
async = require 'async'
temp = require 'temp'
patrick = require 'patrick'
telepath = require 'telepath'
{createPeer, connectDocument} = require './session-utils'
module.exports =
@ -14,44 +15,13 @@ 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)
@bundleRepositoryDelta (error, repositoryDelta) =>
patrick.snapshot project.getPath(), (error, repoSnapshot) =>
if error?
console.error(error)
return
@ -72,7 +42,7 @@ class HostSession
@peer.on 'connection', (connection) =>
connection.on 'open', =>
console.log 'sending document'
connection.send({repositoryDelta, doc: @doc.serialize()})
connection.send({repoSnapshot, doc: @doc.serialize()})
connectDocument(@doc, connection)
connection.on 'close', =>