annotate git_handler.py @ 29:2a5c0bf0fef5

Another way of fixing no-bookmark issue, along with updated test.
author Augie Fackler <durin42@gmail.com>
date Tue, 28 Apr 2009 06:30:11 -0700
parents b258ef16ae37
children 562fc51b991e
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
7
89992b6d2eef mapping parents properly now
Scott Chacon <schacon@gmail.com>
parents: 6
diff changeset
1 import os, errno, sys, time, datetime, pickle, copy
5
d6c443a91b18 refactored the git handling stuff out into another class
Scott Chacon <schacon@gmail.com>
parents:
diff changeset
2 import dulwich
d6c443a91b18 refactored the git handling stuff out into another class
Scott Chacon <schacon@gmail.com>
parents:
diff changeset
3 from dulwich.repo import Repo
d6c443a91b18 refactored the git handling stuff out into another class
Scott Chacon <schacon@gmail.com>
parents:
diff changeset
4 from dulwich.client import SimpleFetchGraphWalker
12
227b11d75844 updates bookmarks and beginnings of seperate remotes support
Scott Chacon <schacon@gmail.com>
parents: 11
diff changeset
5 from dulwich.objects import hex_to_sha
5
d6c443a91b18 refactored the git handling stuff out into another class
Scott Chacon <schacon@gmail.com>
parents:
diff changeset
6 from hgext import bookmarks
d6c443a91b18 refactored the git handling stuff out into another class
Scott Chacon <schacon@gmail.com>
parents:
diff changeset
7 from mercurial.i18n import _
6
c77197123d95 importing basic, mostly stubbed changesets
Scott Chacon <schacon@gmail.com>
parents: 5
diff changeset
8 from mercurial.node import bin, hex, nullid
c77197123d95 importing basic, mostly stubbed changesets
Scott Chacon <schacon@gmail.com>
parents: 5
diff changeset
9 from mercurial import hg, util, context, error
5
d6c443a91b18 refactored the git handling stuff out into another class
Scott Chacon <schacon@gmail.com>
parents:
diff changeset
10
24
41f4e0a85d15 fully converts hg changeset/manifest/files to git commits/trees/blobs
Scott Chacon <schacon@gmail.com>
parents: 23
diff changeset
11 import math
41f4e0a85d15 fully converts hg changeset/manifest/files to git commits/trees/blobs
Scott Chacon <schacon@gmail.com>
parents: 23
diff changeset
12
41f4e0a85d15 fully converts hg changeset/manifest/files to git commits/trees/blobs
Scott Chacon <schacon@gmail.com>
parents: 23
diff changeset
13 def seconds_to_offset(time):
41f4e0a85d15 fully converts hg changeset/manifest/files to git commits/trees/blobs
Scott Chacon <schacon@gmail.com>
parents: 23
diff changeset
14 hours = (float(time) / 60 / 60)
41f4e0a85d15 fully converts hg changeset/manifest/files to git commits/trees/blobs
Scott Chacon <schacon@gmail.com>
parents: 23
diff changeset
15 hour_diff = math.fmod(time, 60)
41f4e0a85d15 fully converts hg changeset/manifest/files to git commits/trees/blobs
Scott Chacon <schacon@gmail.com>
parents: 23
diff changeset
16 minutes = int(hour_diff)
41f4e0a85d15 fully converts hg changeset/manifest/files to git commits/trees/blobs
Scott Chacon <schacon@gmail.com>
parents: 23
diff changeset
17 hours = int(math.floor(hours))
41f4e0a85d15 fully converts hg changeset/manifest/files to git commits/trees/blobs
Scott Chacon <schacon@gmail.com>
parents: 23
diff changeset
18 if hours > 12:
41f4e0a85d15 fully converts hg changeset/manifest/files to git commits/trees/blobs
Scott Chacon <schacon@gmail.com>
parents: 23
diff changeset
19 sign = '+'
41f4e0a85d15 fully converts hg changeset/manifest/files to git commits/trees/blobs
Scott Chacon <schacon@gmail.com>
parents: 23
diff changeset
20 hours = 12 - (hours - 12)
41f4e0a85d15 fully converts hg changeset/manifest/files to git commits/trees/blobs
Scott Chacon <schacon@gmail.com>
parents: 23
diff changeset
21 else:
41f4e0a85d15 fully converts hg changeset/manifest/files to git commits/trees/blobs
Scott Chacon <schacon@gmail.com>
parents: 23
diff changeset
22 sign = '-'
41f4e0a85d15 fully converts hg changeset/manifest/files to git commits/trees/blobs
Scott Chacon <schacon@gmail.com>
parents: 23
diff changeset
23 return sign + str(hours).rjust(2, '0') + str(minutes).rjust(2, '0')
41f4e0a85d15 fully converts hg changeset/manifest/files to git commits/trees/blobs
Scott Chacon <schacon@gmail.com>
parents: 23
diff changeset
24
41f4e0a85d15 fully converts hg changeset/manifest/files to git commits/trees/blobs
Scott Chacon <schacon@gmail.com>
parents: 23
diff changeset
25 def offset_to_seconds(offset):
41f4e0a85d15 fully converts hg changeset/manifest/files to git commits/trees/blobs
Scott Chacon <schacon@gmail.com>
parents: 23
diff changeset
26 if len(offset) == 5:
41f4e0a85d15 fully converts hg changeset/manifest/files to git commits/trees/blobs
Scott Chacon <schacon@gmail.com>
parents: 23
diff changeset
27 sign = offset[0:1]
41f4e0a85d15 fully converts hg changeset/manifest/files to git commits/trees/blobs
Scott Chacon <schacon@gmail.com>
parents: 23
diff changeset
28 hours = int(offset[1:3])
41f4e0a85d15 fully converts hg changeset/manifest/files to git commits/trees/blobs
Scott Chacon <schacon@gmail.com>
parents: 23
diff changeset
29 minutes = int(offset[3:5])
41f4e0a85d15 fully converts hg changeset/manifest/files to git commits/trees/blobs
Scott Chacon <schacon@gmail.com>
parents: 23
diff changeset
30 if sign == '+':
41f4e0a85d15 fully converts hg changeset/manifest/files to git commits/trees/blobs
Scott Chacon <schacon@gmail.com>
parents: 23
diff changeset
31 hours = 12 + (12 - hours)
41f4e0a85d15 fully converts hg changeset/manifest/files to git commits/trees/blobs
Scott Chacon <schacon@gmail.com>
parents: 23
diff changeset
32 return (hours * 60 * 60) + (minutes) * 60
41f4e0a85d15 fully converts hg changeset/manifest/files to git commits/trees/blobs
Scott Chacon <schacon@gmail.com>
parents: 23
diff changeset
33 else:
41f4e0a85d15 fully converts hg changeset/manifest/files to git commits/trees/blobs
Scott Chacon <schacon@gmail.com>
parents: 23
diff changeset
34 return 0
41f4e0a85d15 fully converts hg changeset/manifest/files to git commits/trees/blobs
Scott Chacon <schacon@gmail.com>
parents: 23
diff changeset
35
5
d6c443a91b18 refactored the git handling stuff out into another class
Scott Chacon <schacon@gmail.com>
parents:
diff changeset
36 class GitHandler(object):
19
2be9c0bd88af Warn, but don't fail when bookmarks is not enabled.
Augie Fackler <durin42@gmail.com>
parents: 17
diff changeset
37
5
d6c443a91b18 refactored the git handling stuff out into another class
Scott Chacon <schacon@gmail.com>
parents:
diff changeset
38 def __init__(self, dest_repo, ui):
d6c443a91b18 refactored the git handling stuff out into another class
Scott Chacon <schacon@gmail.com>
parents:
diff changeset
39 self.repo = dest_repo
d6c443a91b18 refactored the git handling stuff out into another class
Scott Chacon <schacon@gmail.com>
parents:
diff changeset
40 self.ui = ui
16
58cd05129119 moved init into git_handler
Scott Chacon <schacon@gmail.com>
parents: 14
diff changeset
41 self.init_if_missing()
7
89992b6d2eef mapping parents properly now
Scott Chacon <schacon@gmail.com>
parents: 6
diff changeset
42 self.load_git()
89992b6d2eef mapping parents properly now
Scott Chacon <schacon@gmail.com>
parents: 6
diff changeset
43 self.load_map()
14
36e94e805fa7 added basic config file for remembering remote urls
Scott Chacon <schacon@gmail.com>
parents: 13
diff changeset
44 self.load_config()
19
2be9c0bd88af Warn, but don't fail when bookmarks is not enabled.
Augie Fackler <durin42@gmail.com>
parents: 17
diff changeset
45
2be9c0bd88af Warn, but don't fail when bookmarks is not enabled.
Augie Fackler <durin42@gmail.com>
parents: 17
diff changeset
46 # make the git data directory
16
58cd05129119 moved init into git_handler
Scott Chacon <schacon@gmail.com>
parents: 14
diff changeset
47 def init_if_missing(self):
58cd05129119 moved init into git_handler
Scott Chacon <schacon@gmail.com>
parents: 14
diff changeset
48 git_hg_path = os.path.join(self.repo.path, 'git')
17
ace0f6ed65a1 setting up for upload-pack functionality
Scott Chacon <schacon@gmail.com>
parents: 16
diff changeset
49 if not os.path.exists(git_hg_path):
ace0f6ed65a1 setting up for upload-pack functionality
Scott Chacon <schacon@gmail.com>
parents: 16
diff changeset
50 os.mkdir(git_hg_path)
ace0f6ed65a1 setting up for upload-pack functionality
Scott Chacon <schacon@gmail.com>
parents: 16
diff changeset
51 dulwich.repo.Repo.init_bare(git_hg_path)
19
2be9c0bd88af Warn, but don't fail when bookmarks is not enabled.
Augie Fackler <durin42@gmail.com>
parents: 17
diff changeset
52
7
89992b6d2eef mapping parents properly now
Scott Chacon <schacon@gmail.com>
parents: 6
diff changeset
53 def load_git(self):
5
d6c443a91b18 refactored the git handling stuff out into another class
Scott Chacon <schacon@gmail.com>
parents:
diff changeset
54 git_dir = os.path.join(self.repo.path, 'git')
d6c443a91b18 refactored the git handling stuff out into another class
Scott Chacon <schacon@gmail.com>
parents:
diff changeset
55 self.git = Repo(git_dir)
7
89992b6d2eef mapping parents properly now
Scott Chacon <schacon@gmail.com>
parents: 6
diff changeset
56
14
36e94e805fa7 added basic config file for remembering remote urls
Scott Chacon <schacon@gmail.com>
parents: 13
diff changeset
57 ## FILE LOAD AND SAVE METHODS
36e94e805fa7 added basic config file for remembering remote urls
Scott Chacon <schacon@gmail.com>
parents: 13
diff changeset
58
21
13b9a020e382 gpush coming along. will now write blobs it doesn't have yet to git repo.
Scott Chacon <schacon@gmail.com>
parents: 19
diff changeset
59 def map_set(self, gitsha, hgsha):
13b9a020e382 gpush coming along. will now write blobs it doesn't have yet to git repo.
Scott Chacon <schacon@gmail.com>
parents: 19
diff changeset
60 self._map_git[gitsha] = hgsha
13b9a020e382 gpush coming along. will now write blobs it doesn't have yet to git repo.
Scott Chacon <schacon@gmail.com>
parents: 19
diff changeset
61 self._map_hg[hgsha] = gitsha
13b9a020e382 gpush coming along. will now write blobs it doesn't have yet to git repo.
Scott Chacon <schacon@gmail.com>
parents: 19
diff changeset
62
13b9a020e382 gpush coming along. will now write blobs it doesn't have yet to git repo.
Scott Chacon <schacon@gmail.com>
parents: 19
diff changeset
63 def map_hg_get(self, gitsha):
13b9a020e382 gpush coming along. will now write blobs it doesn't have yet to git repo.
Scott Chacon <schacon@gmail.com>
parents: 19
diff changeset
64 if gitsha in self._map_git:
13b9a020e382 gpush coming along. will now write blobs it doesn't have yet to git repo.
Scott Chacon <schacon@gmail.com>
parents: 19
diff changeset
65 return self._map_git[gitsha]
13b9a020e382 gpush coming along. will now write blobs it doesn't have yet to git repo.
Scott Chacon <schacon@gmail.com>
parents: 19
diff changeset
66 else:
13b9a020e382 gpush coming along. will now write blobs it doesn't have yet to git repo.
Scott Chacon <schacon@gmail.com>
parents: 19
diff changeset
67 return None
13b9a020e382 gpush coming along. will now write blobs it doesn't have yet to git repo.
Scott Chacon <schacon@gmail.com>
parents: 19
diff changeset
68
13b9a020e382 gpush coming along. will now write blobs it doesn't have yet to git repo.
Scott Chacon <schacon@gmail.com>
parents: 19
diff changeset
69 def map_git_get(self, hgsha):
13b9a020e382 gpush coming along. will now write blobs it doesn't have yet to git repo.
Scott Chacon <schacon@gmail.com>
parents: 19
diff changeset
70 if hgsha in self._map_hg:
13b9a020e382 gpush coming along. will now write blobs it doesn't have yet to git repo.
Scott Chacon <schacon@gmail.com>
parents: 19
diff changeset
71 return self._map_hg[hgsha]
13b9a020e382 gpush coming along. will now write blobs it doesn't have yet to git repo.
Scott Chacon <schacon@gmail.com>
parents: 19
diff changeset
72 else:
13b9a020e382 gpush coming along. will now write blobs it doesn't have yet to git repo.
Scott Chacon <schacon@gmail.com>
parents: 19
diff changeset
73 return None
13b9a020e382 gpush coming along. will now write blobs it doesn't have yet to git repo.
Scott Chacon <schacon@gmail.com>
parents: 19
diff changeset
74
7
89992b6d2eef mapping parents properly now
Scott Chacon <schacon@gmail.com>
parents: 6
diff changeset
75 def load_map(self):
21
13b9a020e382 gpush coming along. will now write blobs it doesn't have yet to git repo.
Scott Chacon <schacon@gmail.com>
parents: 19
diff changeset
76 self._map_git = {}
13b9a020e382 gpush coming along. will now write blobs it doesn't have yet to git repo.
Scott Chacon <schacon@gmail.com>
parents: 19
diff changeset
77 self._map_hg = {}
7
89992b6d2eef mapping parents properly now
Scott Chacon <schacon@gmail.com>
parents: 6
diff changeset
78 if os.path.exists(self.repo.join('git-mapfile')):
89992b6d2eef mapping parents properly now
Scott Chacon <schacon@gmail.com>
parents: 6
diff changeset
79 for line in self.repo.opener('git-mapfile'):
89992b6d2eef mapping parents properly now
Scott Chacon <schacon@gmail.com>
parents: 6
diff changeset
80 gitsha, hgsha = line.strip().split(' ', 1)
21
13b9a020e382 gpush coming along. will now write blobs it doesn't have yet to git repo.
Scott Chacon <schacon@gmail.com>
parents: 19
diff changeset
81 self._map_git[gitsha] = hgsha
13b9a020e382 gpush coming along. will now write blobs it doesn't have yet to git repo.
Scott Chacon <schacon@gmail.com>
parents: 19
diff changeset
82 self._map_hg[hgsha] = gitsha
19
2be9c0bd88af Warn, but don't fail when bookmarks is not enabled.
Augie Fackler <durin42@gmail.com>
parents: 17
diff changeset
83
7
89992b6d2eef mapping parents properly now
Scott Chacon <schacon@gmail.com>
parents: 6
diff changeset
84 def save_map(self):
89992b6d2eef mapping parents properly now
Scott Chacon <schacon@gmail.com>
parents: 6
diff changeset
85 file = self.repo.opener('git-mapfile', 'w+')
21
13b9a020e382 gpush coming along. will now write blobs it doesn't have yet to git repo.
Scott Chacon <schacon@gmail.com>
parents: 19
diff changeset
86 for gitsha, hgsha in self._map_git.iteritems():
7
89992b6d2eef mapping parents properly now
Scott Chacon <schacon@gmail.com>
parents: 6
diff changeset
87 file.write("%s %s\n" % (gitsha, hgsha))
89992b6d2eef mapping parents properly now
Scott Chacon <schacon@gmail.com>
parents: 6
diff changeset
88 file.close()
19
2be9c0bd88af Warn, but don't fail when bookmarks is not enabled.
Augie Fackler <durin42@gmail.com>
parents: 17
diff changeset
89
14
36e94e805fa7 added basic config file for remembering remote urls
Scott Chacon <schacon@gmail.com>
parents: 13
diff changeset
90 def load_config(self):
36e94e805fa7 added basic config file for remembering remote urls
Scott Chacon <schacon@gmail.com>
parents: 13
diff changeset
91 self._config = {}
36e94e805fa7 added basic config file for remembering remote urls
Scott Chacon <schacon@gmail.com>
parents: 13
diff changeset
92 if os.path.exists(self.repo.join('git-config')):
36e94e805fa7 added basic config file for remembering remote urls
Scott Chacon <schacon@gmail.com>
parents: 13
diff changeset
93 for line in self.repo.opener('git-config'):
36e94e805fa7 added basic config file for remembering remote urls
Scott Chacon <schacon@gmail.com>
parents: 13
diff changeset
94 key, value = line.strip().split(' ', 1)
36e94e805fa7 added basic config file for remembering remote urls
Scott Chacon <schacon@gmail.com>
parents: 13
diff changeset
95 self._config[key] = value
19
2be9c0bd88af Warn, but don't fail when bookmarks is not enabled.
Augie Fackler <durin42@gmail.com>
parents: 17
diff changeset
96
14
36e94e805fa7 added basic config file for remembering remote urls
Scott Chacon <schacon@gmail.com>
parents: 13
diff changeset
97 def save_config(self):
36e94e805fa7 added basic config file for remembering remote urls
Scott Chacon <schacon@gmail.com>
parents: 13
diff changeset
98 file = self.repo.opener('git-config', 'w+')
36e94e805fa7 added basic config file for remembering remote urls
Scott Chacon <schacon@gmail.com>
parents: 13
diff changeset
99 for key, value in self._config.iteritems():
36e94e805fa7 added basic config file for remembering remote urls
Scott Chacon <schacon@gmail.com>
parents: 13
diff changeset
100 file.write("%s %s\n" % (key, value))
36e94e805fa7 added basic config file for remembering remote urls
Scott Chacon <schacon@gmail.com>
parents: 13
diff changeset
101 file.close()
19
2be9c0bd88af Warn, but don't fail when bookmarks is not enabled.
Augie Fackler <durin42@gmail.com>
parents: 17
diff changeset
102
14
36e94e805fa7 added basic config file for remembering remote urls
Scott Chacon <schacon@gmail.com>
parents: 13
diff changeset
103
36e94e805fa7 added basic config file for remembering remote urls
Scott Chacon <schacon@gmail.com>
parents: 13
diff changeset
104 ## END FILE LOAD AND SAVE METHODS
7
89992b6d2eef mapping parents properly now
Scott Chacon <schacon@gmail.com>
parents: 6
diff changeset
105
12
227b11d75844 updates bookmarks and beginnings of seperate remotes support
Scott Chacon <schacon@gmail.com>
parents: 11
diff changeset
106 def fetch(self, remote_name):
227b11d75844 updates bookmarks and beginnings of seperate remotes support
Scott Chacon <schacon@gmail.com>
parents: 11
diff changeset
107 self.ui.status(_("fetching from : " + remote_name + "\n"))
5
d6c443a91b18 refactored the git handling stuff out into another class
Scott Chacon <schacon@gmail.com>
parents:
diff changeset
108 self.export_git_objects()
12
227b11d75844 updates bookmarks and beginnings of seperate remotes support
Scott Chacon <schacon@gmail.com>
parents: 11
diff changeset
109 self.fetch_pack(remote_name)
227b11d75844 updates bookmarks and beginnings of seperate remotes support
Scott Chacon <schacon@gmail.com>
parents: 11
diff changeset
110 self.import_git_objects(remote_name)
7
89992b6d2eef mapping parents properly now
Scott Chacon <schacon@gmail.com>
parents: 6
diff changeset
111 self.save_map()
89992b6d2eef mapping parents properly now
Scott Chacon <schacon@gmail.com>
parents: 6
diff changeset
112
17
ace0f6ed65a1 setting up for upload-pack functionality
Scott Chacon <schacon@gmail.com>
parents: 16
diff changeset
113 def push(self, remote_name):
ace0f6ed65a1 setting up for upload-pack functionality
Scott Chacon <schacon@gmail.com>
parents: 16
diff changeset
114 self.ui.status(_("pushing to : " + remote_name + "\n"))
ace0f6ed65a1 setting up for upload-pack functionality
Scott Chacon <schacon@gmail.com>
parents: 16
diff changeset
115 self.export_git_objects()
24
41f4e0a85d15 fully converts hg changeset/manifest/files to git commits/trees/blobs
Scott Chacon <schacon@gmail.com>
parents: 23
diff changeset
116 self.update_references()
17
ace0f6ed65a1 setting up for upload-pack functionality
Scott Chacon <schacon@gmail.com>
parents: 16
diff changeset
117 self.upload_pack(remote_name)
ace0f6ed65a1 setting up for upload-pack functionality
Scott Chacon <schacon@gmail.com>
parents: 16
diff changeset
118 self.save_map()
19
2be9c0bd88af Warn, but don't fail when bookmarks is not enabled.
Augie Fackler <durin42@gmail.com>
parents: 17
diff changeset
119
12
227b11d75844 updates bookmarks and beginnings of seperate remotes support
Scott Chacon <schacon@gmail.com>
parents: 11
diff changeset
120 # TODO: make these actually save and recall
227b11d75844 updates bookmarks and beginnings of seperate remotes support
Scott Chacon <schacon@gmail.com>
parents: 11
diff changeset
121 def remote_add(self, remote_name, git_url):
14
36e94e805fa7 added basic config file for remembering remote urls
Scott Chacon <schacon@gmail.com>
parents: 13
diff changeset
122 self._config['remote.' + remote_name + '.url'] = git_url
36e94e805fa7 added basic config file for remembering remote urls
Scott Chacon <schacon@gmail.com>
parents: 13
diff changeset
123 self.save_config()
19
2be9c0bd88af Warn, but don't fail when bookmarks is not enabled.
Augie Fackler <durin42@gmail.com>
parents: 17
diff changeset
124
12
227b11d75844 updates bookmarks and beginnings of seperate remotes support
Scott Chacon <schacon@gmail.com>
parents: 11
diff changeset
125 def remote_name_to_url(self, remote_name):
14
36e94e805fa7 added basic config file for remembering remote urls
Scott Chacon <schacon@gmail.com>
parents: 13
diff changeset
126 return self._config['remote.' + remote_name + '.url']
19
2be9c0bd88af Warn, but don't fail when bookmarks is not enabled.
Augie Fackler <durin42@gmail.com>
parents: 17
diff changeset
127
24
41f4e0a85d15 fully converts hg changeset/manifest/files to git commits/trees/blobs
Scott Chacon <schacon@gmail.com>
parents: 23
diff changeset
128 def update_references(self):
25
88e9e9e1caf1 will now set the current tip() as your git 'master' branch for packfile upload
Scott Chacon <schacon@gmail.com>
parents: 24
diff changeset
129 # TODO : if bookmarks exist, add them as git branches
88e9e9e1caf1 will now set the current tip() as your git 'master' branch for packfile upload
Scott Chacon <schacon@gmail.com>
parents: 24
diff changeset
130 c = self.map_git_get(hex(self.repo.changelog.tip()))
88e9e9e1caf1 will now set the current tip() as your git 'master' branch for packfile upload
Scott Chacon <schacon@gmail.com>
parents: 24
diff changeset
131 self.git.set_ref('refs/heads/master', c)
24
41f4e0a85d15 fully converts hg changeset/manifest/files to git commits/trees/blobs
Scott Chacon <schacon@gmail.com>
parents: 23
diff changeset
132
21
13b9a020e382 gpush coming along. will now write blobs it doesn't have yet to git repo.
Scott Chacon <schacon@gmail.com>
parents: 19
diff changeset
133 def export_git_objects(self):
13b9a020e382 gpush coming along. will now write blobs it doesn't have yet to git repo.
Scott Chacon <schacon@gmail.com>
parents: 19
diff changeset
134 print "exporting git objects"
13b9a020e382 gpush coming along. will now write blobs it doesn't have yet to git repo.
Scott Chacon <schacon@gmail.com>
parents: 19
diff changeset
135 for rev in self.repo.changelog:
24
41f4e0a85d15 fully converts hg changeset/manifest/files to git commits/trees/blobs
Scott Chacon <schacon@gmail.com>
parents: 23
diff changeset
136 self.export_hg_commit(rev)
41f4e0a85d15 fully converts hg changeset/manifest/files to git commits/trees/blobs
Scott Chacon <schacon@gmail.com>
parents: 23
diff changeset
137
41f4e0a85d15 fully converts hg changeset/manifest/files to git commits/trees/blobs
Scott Chacon <schacon@gmail.com>
parents: 23
diff changeset
138 # convert this commit into git objects
41f4e0a85d15 fully converts hg changeset/manifest/files to git commits/trees/blobs
Scott Chacon <schacon@gmail.com>
parents: 23
diff changeset
139 # go through the manifest, convert all blobs/trees we don't have
41f4e0a85d15 fully converts hg changeset/manifest/files to git commits/trees/blobs
Scott Chacon <schacon@gmail.com>
parents: 23
diff changeset
140 # write the commit object (with metadata info)
41f4e0a85d15 fully converts hg changeset/manifest/files to git commits/trees/blobs
Scott Chacon <schacon@gmail.com>
parents: 23
diff changeset
141 def export_hg_commit(self, rev):
41f4e0a85d15 fully converts hg changeset/manifest/files to git commits/trees/blobs
Scott Chacon <schacon@gmail.com>
parents: 23
diff changeset
142 # return if we've already processed this
41f4e0a85d15 fully converts hg changeset/manifest/files to git commits/trees/blobs
Scott Chacon <schacon@gmail.com>
parents: 23
diff changeset
143 node = self.repo.changelog.lookup(rev)
41f4e0a85d15 fully converts hg changeset/manifest/files to git commits/trees/blobs
Scott Chacon <schacon@gmail.com>
parents: 23
diff changeset
144 phgsha = hex(node)
41f4e0a85d15 fully converts hg changeset/manifest/files to git commits/trees/blobs
Scott Chacon <schacon@gmail.com>
parents: 23
diff changeset
145 pgit_sha = self.map_git_get(phgsha)
41f4e0a85d15 fully converts hg changeset/manifest/files to git commits/trees/blobs
Scott Chacon <schacon@gmail.com>
parents: 23
diff changeset
146 if pgit_sha:
41f4e0a85d15 fully converts hg changeset/manifest/files to git commits/trees/blobs
Scott Chacon <schacon@gmail.com>
parents: 23
diff changeset
147 return pgit_sha
41f4e0a85d15 fully converts hg changeset/manifest/files to git commits/trees/blobs
Scott Chacon <schacon@gmail.com>
parents: 23
diff changeset
148
41f4e0a85d15 fully converts hg changeset/manifest/files to git commits/trees/blobs
Scott Chacon <schacon@gmail.com>
parents: 23
diff changeset
149 print "converting revision " + str(rev)
41f4e0a85d15 fully converts hg changeset/manifest/files to git commits/trees/blobs
Scott Chacon <schacon@gmail.com>
parents: 23
diff changeset
150
41f4e0a85d15 fully converts hg changeset/manifest/files to git commits/trees/blobs
Scott Chacon <schacon@gmail.com>
parents: 23
diff changeset
151 # make sure parents are converted first
41f4e0a85d15 fully converts hg changeset/manifest/files to git commits/trees/blobs
Scott Chacon <schacon@gmail.com>
parents: 23
diff changeset
152 parents = self.repo.parents(rev)
41f4e0a85d15 fully converts hg changeset/manifest/files to git commits/trees/blobs
Scott Chacon <schacon@gmail.com>
parents: 23
diff changeset
153 for parent in parents:
41f4e0a85d15 fully converts hg changeset/manifest/files to git commits/trees/blobs
Scott Chacon <schacon@gmail.com>
parents: 23
diff changeset
154 p_rev = parent.rev()
41f4e0a85d15 fully converts hg changeset/manifest/files to git commits/trees/blobs
Scott Chacon <schacon@gmail.com>
parents: 23
diff changeset
155 hgsha = hex(parent.node())
21
13b9a020e382 gpush coming along. will now write blobs it doesn't have yet to git repo.
Scott Chacon <schacon@gmail.com>
parents: 19
diff changeset
156 git_sha = self.map_git_get(hgsha)
13b9a020e382 gpush coming along. will now write blobs it doesn't have yet to git repo.
Scott Chacon <schacon@gmail.com>
parents: 19
diff changeset
157 if not git_sha:
24
41f4e0a85d15 fully converts hg changeset/manifest/files to git commits/trees/blobs
Scott Chacon <schacon@gmail.com>
parents: 23
diff changeset
158 self.export_hg_commit(self, p_rev)
21
13b9a020e382 gpush coming along. will now write blobs it doesn't have yet to git repo.
Scott Chacon <schacon@gmail.com>
parents: 19
diff changeset
159
13b9a020e382 gpush coming along. will now write blobs it doesn't have yet to git repo.
Scott Chacon <schacon@gmail.com>
parents: 19
diff changeset
160 ctx = self.repo.changectx(rev)
23
ee217d3c6363 will now write all trees and blobs needed. all thats left is commits for basic data conversion
Scott Chacon <schacon@gmail.com>
parents: 22
diff changeset
161 tree_sha = self.write_git_tree(ctx)
22
f390f3d183e0 saving the blob ids in the map now
Scott Chacon <schacon@gmail.com>
parents: 21
diff changeset
162
24
41f4e0a85d15 fully converts hg changeset/manifest/files to git commits/trees/blobs
Scott Chacon <schacon@gmail.com>
parents: 23
diff changeset
163 # TODO : something with tags?
25
88e9e9e1caf1 will now set the current tip() as your git 'master' branch for packfile upload
Scott Chacon <schacon@gmail.com>
parents: 24
diff changeset
164 # TODO : explicit file renaming, copying?
88e9e9e1caf1 will now set the current tip() as your git 'master' branch for packfile upload
Scott Chacon <schacon@gmail.com>
parents: 24
diff changeset
165
24
41f4e0a85d15 fully converts hg changeset/manifest/files to git commits/trees/blobs
Scott Chacon <schacon@gmail.com>
parents: 23
diff changeset
166 commit = {}
41f4e0a85d15 fully converts hg changeset/manifest/files to git commits/trees/blobs
Scott Chacon <schacon@gmail.com>
parents: 23
diff changeset
167 commit['tree'] = tree_sha
41f4e0a85d15 fully converts hg changeset/manifest/files to git commits/trees/blobs
Scott Chacon <schacon@gmail.com>
parents: 23
diff changeset
168 (time, timezone) = ctx.date()
41f4e0a85d15 fully converts hg changeset/manifest/files to git commits/trees/blobs
Scott Chacon <schacon@gmail.com>
parents: 23
diff changeset
169 commit['author'] = ctx.user() + ' ' + str(int(time)) + ' ' + seconds_to_offset(timezone)
41f4e0a85d15 fully converts hg changeset/manifest/files to git commits/trees/blobs
Scott Chacon <schacon@gmail.com>
parents: 23
diff changeset
170 message = ctx.description()
41f4e0a85d15 fully converts hg changeset/manifest/files to git commits/trees/blobs
Scott Chacon <schacon@gmail.com>
parents: 23
diff changeset
171 commit['message'] = ctx.description()
41f4e0a85d15 fully converts hg changeset/manifest/files to git commits/trees/blobs
Scott Chacon <schacon@gmail.com>
parents: 23
diff changeset
172 commit['message'] += "\n\n--HG EXTRAS--\n"
41f4e0a85d15 fully converts hg changeset/manifest/files to git commits/trees/blobs
Scott Chacon <schacon@gmail.com>
parents: 23
diff changeset
173 commit['message'] += "branch : " + ctx.branch() + "\n"
41f4e0a85d15 fully converts hg changeset/manifest/files to git commits/trees/blobs
Scott Chacon <schacon@gmail.com>
parents: 23
diff changeset
174
41f4e0a85d15 fully converts hg changeset/manifest/files to git commits/trees/blobs
Scott Chacon <schacon@gmail.com>
parents: 23
diff changeset
175 commit['parents'] = []
41f4e0a85d15 fully converts hg changeset/manifest/files to git commits/trees/blobs
Scott Chacon <schacon@gmail.com>
parents: 23
diff changeset
176 for parent in parents:
41f4e0a85d15 fully converts hg changeset/manifest/files to git commits/trees/blobs
Scott Chacon <schacon@gmail.com>
parents: 23
diff changeset
177 hgsha = hex(parent.node())
41f4e0a85d15 fully converts hg changeset/manifest/files to git commits/trees/blobs
Scott Chacon <schacon@gmail.com>
parents: 23
diff changeset
178 git_sha = self.map_git_get(hgsha)
41f4e0a85d15 fully converts hg changeset/manifest/files to git commits/trees/blobs
Scott Chacon <schacon@gmail.com>
parents: 23
diff changeset
179 commit['parents'].append(git_sha)
41f4e0a85d15 fully converts hg changeset/manifest/files to git commits/trees/blobs
Scott Chacon <schacon@gmail.com>
parents: 23
diff changeset
180
41f4e0a85d15 fully converts hg changeset/manifest/files to git commits/trees/blobs
Scott Chacon <schacon@gmail.com>
parents: 23
diff changeset
181 commit_sha = self.git.write_commit_hash(commit) # writing new blobs to git
41f4e0a85d15 fully converts hg changeset/manifest/files to git commits/trees/blobs
Scott Chacon <schacon@gmail.com>
parents: 23
diff changeset
182 self.map_set(commit_sha, phgsha)
41f4e0a85d15 fully converts hg changeset/manifest/files to git commits/trees/blobs
Scott Chacon <schacon@gmail.com>
parents: 23
diff changeset
183 return commit_sha
23
ee217d3c6363 will now write all trees and blobs needed. all thats left is commits for basic data conversion
Scott Chacon <schacon@gmail.com>
parents: 22
diff changeset
184
ee217d3c6363 will now write all trees and blobs needed. all thats left is commits for basic data conversion
Scott Chacon <schacon@gmail.com>
parents: 22
diff changeset
185 def write_git_tree(self, ctx):
ee217d3c6363 will now write all trees and blobs needed. all thats left is commits for basic data conversion
Scott Chacon <schacon@gmail.com>
parents: 22
diff changeset
186 trees = {}
ee217d3c6363 will now write all trees and blobs needed. all thats left is commits for basic data conversion
Scott Chacon <schacon@gmail.com>
parents: 22
diff changeset
187 man = ctx.manifest()
ee217d3c6363 will now write all trees and blobs needed. all thats left is commits for basic data conversion
Scott Chacon <schacon@gmail.com>
parents: 22
diff changeset
188 for filenm in man.keys():
ee217d3c6363 will now write all trees and blobs needed. all thats left is commits for basic data conversion
Scott Chacon <schacon@gmail.com>
parents: 22
diff changeset
189 # write blob if not in our git database
ee217d3c6363 will now write all trees and blobs needed. all thats left is commits for basic data conversion
Scott Chacon <schacon@gmail.com>
parents: 22
diff changeset
190 fctx = ctx.filectx(filenm)
ee217d3c6363 will now write all trees and blobs needed. all thats left is commits for basic data conversion
Scott Chacon <schacon@gmail.com>
parents: 22
diff changeset
191 is_exec = 'x' in fctx.flags()
ee217d3c6363 will now write all trees and blobs needed. all thats left is commits for basic data conversion
Scott Chacon <schacon@gmail.com>
parents: 22
diff changeset
192 is_link = 'l' in fctx.flags()
ee217d3c6363 will now write all trees and blobs needed. all thats left is commits for basic data conversion
Scott Chacon <schacon@gmail.com>
parents: 22
diff changeset
193 file_id = hex(fctx.filenode())
ee217d3c6363 will now write all trees and blobs needed. all thats left is commits for basic data conversion
Scott Chacon <schacon@gmail.com>
parents: 22
diff changeset
194 blob_sha = self.map_git_get(file_id)
ee217d3c6363 will now write all trees and blobs needed. all thats left is commits for basic data conversion
Scott Chacon <schacon@gmail.com>
parents: 22
diff changeset
195 if not blob_sha:
ee217d3c6363 will now write all trees and blobs needed. all thats left is commits for basic data conversion
Scott Chacon <schacon@gmail.com>
parents: 22
diff changeset
196 blob_sha = self.git.write_blob(fctx.data()) # writing new blobs to git
ee217d3c6363 will now write all trees and blobs needed. all thats left is commits for basic data conversion
Scott Chacon <schacon@gmail.com>
parents: 22
diff changeset
197 self.map_set(blob_sha, file_id)
ee217d3c6363 will now write all trees and blobs needed. all thats left is commits for basic data conversion
Scott Chacon <schacon@gmail.com>
parents: 22
diff changeset
198
ee217d3c6363 will now write all trees and blobs needed. all thats left is commits for basic data conversion
Scott Chacon <schacon@gmail.com>
parents: 22
diff changeset
199 parts = filenm.split('/')
ee217d3c6363 will now write all trees and blobs needed. all thats left is commits for basic data conversion
Scott Chacon <schacon@gmail.com>
parents: 22
diff changeset
200 if len(parts) > 1:
ee217d3c6363 will now write all trees and blobs needed. all thats left is commits for basic data conversion
Scott Chacon <schacon@gmail.com>
parents: 22
diff changeset
201
ee217d3c6363 will now write all trees and blobs needed. all thats left is commits for basic data conversion
Scott Chacon <schacon@gmail.com>
parents: 22
diff changeset
202 # get filename and path for leading subdir
ee217d3c6363 will now write all trees and blobs needed. all thats left is commits for basic data conversion
Scott Chacon <schacon@gmail.com>
parents: 22
diff changeset
203 filepath = parts[-1:][0]
ee217d3c6363 will now write all trees and blobs needed. all thats left is commits for basic data conversion
Scott Chacon <schacon@gmail.com>
parents: 22
diff changeset
204 dirpath = "/".join([v for v in parts[0:-1]]) + '/'
ee217d3c6363 will now write all trees and blobs needed. all thats left is commits for basic data conversion
Scott Chacon <schacon@gmail.com>
parents: 22
diff changeset
205
ee217d3c6363 will now write all trees and blobs needed. all thats left is commits for basic data conversion
Scott Chacon <schacon@gmail.com>
parents: 22
diff changeset
206 # get subdir name and path for parent dir
ee217d3c6363 will now write all trees and blobs needed. all thats left is commits for basic data conversion
Scott Chacon <schacon@gmail.com>
parents: 22
diff changeset
207 parentsub = parts[-2:][0]
ee217d3c6363 will now write all trees and blobs needed. all thats left is commits for basic data conversion
Scott Chacon <schacon@gmail.com>
parents: 22
diff changeset
208 parentpath = "/".join([v for v in parts[0:-2]]) + '/'
ee217d3c6363 will now write all trees and blobs needed. all thats left is commits for basic data conversion
Scott Chacon <schacon@gmail.com>
parents: 22
diff changeset
209
ee217d3c6363 will now write all trees and blobs needed. all thats left is commits for basic data conversion
Scott Chacon <schacon@gmail.com>
parents: 22
diff changeset
210 # set file entry
ee217d3c6363 will now write all trees and blobs needed. all thats left is commits for basic data conversion
Scott Chacon <schacon@gmail.com>
parents: 22
diff changeset
211 fileentry = ['blob', filepath, blob_sha, is_exec, is_link]
ee217d3c6363 will now write all trees and blobs needed. all thats left is commits for basic data conversion
Scott Chacon <schacon@gmail.com>
parents: 22
diff changeset
212 if dirpath not in trees:
ee217d3c6363 will now write all trees and blobs needed. all thats left is commits for basic data conversion
Scott Chacon <schacon@gmail.com>
parents: 22
diff changeset
213 trees[dirpath] = []
ee217d3c6363 will now write all trees and blobs needed. all thats left is commits for basic data conversion
Scott Chacon <schacon@gmail.com>
parents: 22
diff changeset
214 trees[dirpath].append(fileentry)
ee217d3c6363 will now write all trees and blobs needed. all thats left is commits for basic data conversion
Scott Chacon <schacon@gmail.com>
parents: 22
diff changeset
215
ee217d3c6363 will now write all trees and blobs needed. all thats left is commits for basic data conversion
Scott Chacon <schacon@gmail.com>
parents: 22
diff changeset
216 # set directory entry
ee217d3c6363 will now write all trees and blobs needed. all thats left is commits for basic data conversion
Scott Chacon <schacon@gmail.com>
parents: 22
diff changeset
217 treeentry = ['tree', parentsub + '/', dirpath]
ee217d3c6363 will now write all trees and blobs needed. all thats left is commits for basic data conversion
Scott Chacon <schacon@gmail.com>
parents: 22
diff changeset
218 if parentpath not in trees:
ee217d3c6363 will now write all trees and blobs needed. all thats left is commits for basic data conversion
Scott Chacon <schacon@gmail.com>
parents: 22
diff changeset
219 trees[parentpath] = []
ee217d3c6363 will now write all trees and blobs needed. all thats left is commits for basic data conversion
Scott Chacon <schacon@gmail.com>
parents: 22
diff changeset
220 if treeentry not in trees[parentpath]:
ee217d3c6363 will now write all trees and blobs needed. all thats left is commits for basic data conversion
Scott Chacon <schacon@gmail.com>
parents: 22
diff changeset
221 trees[parentpath].append( treeentry )
ee217d3c6363 will now write all trees and blobs needed. all thats left is commits for basic data conversion
Scott Chacon <schacon@gmail.com>
parents: 22
diff changeset
222 else:
ee217d3c6363 will now write all trees and blobs needed. all thats left is commits for basic data conversion
Scott Chacon <schacon@gmail.com>
parents: 22
diff changeset
223 fileentry = ['blob', parts[0], blob_sha, is_exec, is_link]
ee217d3c6363 will now write all trees and blobs needed. all thats left is commits for basic data conversion
Scott Chacon <schacon@gmail.com>
parents: 22
diff changeset
224 if '/' not in trees:
ee217d3c6363 will now write all trees and blobs needed. all thats left is commits for basic data conversion
Scott Chacon <schacon@gmail.com>
parents: 22
diff changeset
225 trees['/'] = []
ee217d3c6363 will now write all trees and blobs needed. all thats left is commits for basic data conversion
Scott Chacon <schacon@gmail.com>
parents: 22
diff changeset
226 trees['/'].append(fileentry)
ee217d3c6363 will now write all trees and blobs needed. all thats left is commits for basic data conversion
Scott Chacon <schacon@gmail.com>
parents: 22
diff changeset
227
ee217d3c6363 will now write all trees and blobs needed. all thats left is commits for basic data conversion
Scott Chacon <schacon@gmail.com>
parents: 22
diff changeset
228 # sort by tree depth, so we write the deepest trees first
ee217d3c6363 will now write all trees and blobs needed. all thats left is commits for basic data conversion
Scott Chacon <schacon@gmail.com>
parents: 22
diff changeset
229 dirs = trees.keys()
ee217d3c6363 will now write all trees and blobs needed. all thats left is commits for basic data conversion
Scott Chacon <schacon@gmail.com>
parents: 22
diff changeset
230 dirs.sort(lambda a, b: len(b.split('/'))-len(a.split('/')))
ee217d3c6363 will now write all trees and blobs needed. all thats left is commits for basic data conversion
Scott Chacon <schacon@gmail.com>
parents: 22
diff changeset
231
ee217d3c6363 will now write all trees and blobs needed. all thats left is commits for basic data conversion
Scott Chacon <schacon@gmail.com>
parents: 22
diff changeset
232 # write all the trees
ee217d3c6363 will now write all trees and blobs needed. all thats left is commits for basic data conversion
Scott Chacon <schacon@gmail.com>
parents: 22
diff changeset
233 tree_sha = None
ee217d3c6363 will now write all trees and blobs needed. all thats left is commits for basic data conversion
Scott Chacon <schacon@gmail.com>
parents: 22
diff changeset
234 tree_shas = {}
ee217d3c6363 will now write all trees and blobs needed. all thats left is commits for basic data conversion
Scott Chacon <schacon@gmail.com>
parents: 22
diff changeset
235 for dirnm in dirs:
ee217d3c6363 will now write all trees and blobs needed. all thats left is commits for basic data conversion
Scott Chacon <schacon@gmail.com>
parents: 22
diff changeset
236 tree_data = []
ee217d3c6363 will now write all trees and blobs needed. all thats left is commits for basic data conversion
Scott Chacon <schacon@gmail.com>
parents: 22
diff changeset
237 for entry in trees[dirnm]:
ee217d3c6363 will now write all trees and blobs needed. all thats left is commits for basic data conversion
Scott Chacon <schacon@gmail.com>
parents: 22
diff changeset
238 # replace tree path with tree SHA
ee217d3c6363 will now write all trees and blobs needed. all thats left is commits for basic data conversion
Scott Chacon <schacon@gmail.com>
parents: 22
diff changeset
239 if entry[0] == 'tree':
ee217d3c6363 will now write all trees and blobs needed. all thats left is commits for basic data conversion
Scott Chacon <schacon@gmail.com>
parents: 22
diff changeset
240 sha = tree_shas[entry[2]]
ee217d3c6363 will now write all trees and blobs needed. all thats left is commits for basic data conversion
Scott Chacon <schacon@gmail.com>
parents: 22
diff changeset
241 entry[2] = sha
ee217d3c6363 will now write all trees and blobs needed. all thats left is commits for basic data conversion
Scott Chacon <schacon@gmail.com>
parents: 22
diff changeset
242 tree_data.append(entry)
ee217d3c6363 will now write all trees and blobs needed. all thats left is commits for basic data conversion
Scott Chacon <schacon@gmail.com>
parents: 22
diff changeset
243 tree_sha = self.git.write_tree_array(tree_data) # writing new trees to git
ee217d3c6363 will now write all trees and blobs needed. all thats left is commits for basic data conversion
Scott Chacon <schacon@gmail.com>
parents: 22
diff changeset
244 tree_shas[dirnm] = tree_sha
ee217d3c6363 will now write all trees and blobs needed. all thats left is commits for basic data conversion
Scott Chacon <schacon@gmail.com>
parents: 22
diff changeset
245 return tree_sha # should be the last root tree sha
ee217d3c6363 will now write all trees and blobs needed. all thats left is commits for basic data conversion
Scott Chacon <schacon@gmail.com>
parents: 22
diff changeset
246
13
01f28d40cb6a checks out the HEAD node from a clone
Scott Chacon <schacon@gmail.com>
parents: 12
diff changeset
247 def remote_head(self, remote_name):
01f28d40cb6a checks out the HEAD node from a clone
Scott Chacon <schacon@gmail.com>
parents: 12
diff changeset
248 for head, sha in self.git.remote_refs(remote_name).iteritems():
01f28d40cb6a checks out the HEAD node from a clone
Scott Chacon <schacon@gmail.com>
parents: 12
diff changeset
249 if head == 'HEAD':
21
13b9a020e382 gpush coming along. will now write blobs it doesn't have yet to git repo.
Scott Chacon <schacon@gmail.com>
parents: 19
diff changeset
250 return self.map_hg_get(sha)
13
01f28d40cb6a checks out the HEAD node from a clone
Scott Chacon <schacon@gmail.com>
parents: 12
diff changeset
251 return None
19
2be9c0bd88af Warn, but don't fail when bookmarks is not enabled.
Augie Fackler <durin42@gmail.com>
parents: 17
diff changeset
252
17
ace0f6ed65a1 setting up for upload-pack functionality
Scott Chacon <schacon@gmail.com>
parents: 16
diff changeset
253 def upload_pack(self, remote_name):
26
a1a5391bc3c3 edit ssh command to quote the path, also convert tags properly on fetch
Scott Chacon <schacon@gmail.com>
parents: 25
diff changeset
254 git_url = self.remote_name_to_url(remote_name)
a1a5391bc3c3 edit ssh command to quote the path, also convert tags properly on fetch
Scott Chacon <schacon@gmail.com>
parents: 25
diff changeset
255 client, path = self.get_transport_and_path(git_url)
a1a5391bc3c3 edit ssh command to quote the path, also convert tags properly on fetch
Scott Chacon <schacon@gmail.com>
parents: 25
diff changeset
256 genpack = self.generate_pack_contents
a1a5391bc3c3 edit ssh command to quote the path, also convert tags properly on fetch
Scott Chacon <schacon@gmail.com>
parents: 25
diff changeset
257 try:
a1a5391bc3c3 edit ssh command to quote the path, also convert tags properly on fetch
Scott Chacon <schacon@gmail.com>
parents: 25
diff changeset
258 client.send_pack(path, genpack)
a1a5391bc3c3 edit ssh command to quote the path, also convert tags properly on fetch
Scott Chacon <schacon@gmail.com>
parents: 25
diff changeset
259 # TODO : self.git.set_remote_refs(refs, remote_name)
a1a5391bc3c3 edit ssh command to quote the path, also convert tags properly on fetch
Scott Chacon <schacon@gmail.com>
parents: 25
diff changeset
260 except:
a1a5391bc3c3 edit ssh command to quote the path, also convert tags properly on fetch
Scott Chacon <schacon@gmail.com>
parents: 25
diff changeset
261 raise
a1a5391bc3c3 edit ssh command to quote the path, also convert tags properly on fetch
Scott Chacon <schacon@gmail.com>
parents: 25
diff changeset
262
a1a5391bc3c3 edit ssh command to quote the path, also convert tags properly on fetch
Scott Chacon <schacon@gmail.com>
parents: 25
diff changeset
263 def generate_pack_contents(self, want, have, none):
a1a5391bc3c3 edit ssh command to quote the path, also convert tags properly on fetch
Scott Chacon <schacon@gmail.com>
parents: 25
diff changeset
264 print "WANT: " + str(want)
a1a5391bc3c3 edit ssh command to quote the path, also convert tags properly on fetch
Scott Chacon <schacon@gmail.com>
parents: 25
diff changeset
265 print "HAVE: " + str(have)
a1a5391bc3c3 edit ssh command to quote the path, also convert tags properly on fetch
Scott Chacon <schacon@gmail.com>
parents: 25
diff changeset
266 print "NONE: " + str(none)
a1a5391bc3c3 edit ssh command to quote the path, also convert tags properly on fetch
Scott Chacon <schacon@gmail.com>
parents: 25
diff changeset
267
12
227b11d75844 updates bookmarks and beginnings of seperate remotes support
Scott Chacon <schacon@gmail.com>
parents: 11
diff changeset
268 def fetch_pack(self, remote_name):
227b11d75844 updates bookmarks and beginnings of seperate remotes support
Scott Chacon <schacon@gmail.com>
parents: 11
diff changeset
269 git_url = self.remote_name_to_url(remote_name)
5
d6c443a91b18 refactored the git handling stuff out into another class
Scott Chacon <schacon@gmail.com>
parents:
diff changeset
270 client, path = self.get_transport_and_path(git_url)
d6c443a91b18 refactored the git handling stuff out into another class
Scott Chacon <schacon@gmail.com>
parents:
diff changeset
271 graphwalker = SimpleFetchGraphWalker(self.git.heads().values(), self.git.get_parents)
d6c443a91b18 refactored the git handling stuff out into another class
Scott Chacon <schacon@gmail.com>
parents:
diff changeset
272 f, commit = self.git.object_store.add_pack()
d6c443a91b18 refactored the git handling stuff out into another class
Scott Chacon <schacon@gmail.com>
parents:
diff changeset
273 try:
d6c443a91b18 refactored the git handling stuff out into another class
Scott Chacon <schacon@gmail.com>
parents:
diff changeset
274 determine_wants = self.git.object_store.determine_wants_all
d6c443a91b18 refactored the git handling stuff out into another class
Scott Chacon <schacon@gmail.com>
parents:
diff changeset
275 refs = client.fetch_pack(path, determine_wants, graphwalker, f.write, sys.stdout.write)
d6c443a91b18 refactored the git handling stuff out into another class
Scott Chacon <schacon@gmail.com>
parents:
diff changeset
276 f.close()
d6c443a91b18 refactored the git handling stuff out into another class
Scott Chacon <schacon@gmail.com>
parents:
diff changeset
277 commit()
12
227b11d75844 updates bookmarks and beginnings of seperate remotes support
Scott Chacon <schacon@gmail.com>
parents: 11
diff changeset
278 self.git.set_remote_refs(refs, remote_name)
5
d6c443a91b18 refactored the git handling stuff out into another class
Scott Chacon <schacon@gmail.com>
parents:
diff changeset
279 except:
d6c443a91b18 refactored the git handling stuff out into another class
Scott Chacon <schacon@gmail.com>
parents:
diff changeset
280 f.close()
19
2be9c0bd88af Warn, but don't fail when bookmarks is not enabled.
Augie Fackler <durin42@gmail.com>
parents: 17
diff changeset
281 raise
5
d6c443a91b18 refactored the git handling stuff out into another class
Scott Chacon <schacon@gmail.com>
parents:
diff changeset
282
12
227b11d75844 updates bookmarks and beginnings of seperate remotes support
Scott Chacon <schacon@gmail.com>
parents: 11
diff changeset
283 def import_git_objects(self, remote_name):
5
d6c443a91b18 refactored the git handling stuff out into another class
Scott Chacon <schacon@gmail.com>
parents:
diff changeset
284 self.ui.status(_("importing Git objects into Hg\n"))
d6c443a91b18 refactored the git handling stuff out into another class
Scott Chacon <schacon@gmail.com>
parents:
diff changeset
285 # import heads as remote references
d6c443a91b18 refactored the git handling stuff out into another class
Scott Chacon <schacon@gmail.com>
parents:
diff changeset
286 todo = []
d6c443a91b18 refactored the git handling stuff out into another class
Scott Chacon <schacon@gmail.com>
parents:
diff changeset
287 done = set()
9
7e776864b301 sorts the commits topologically before converting
Scott Chacon <schacon@gmail.com>
parents: 8
diff changeset
288 convert_list = {}
19
2be9c0bd88af Warn, but don't fail when bookmarks is not enabled.
Augie Fackler <durin42@gmail.com>
parents: 17
diff changeset
289
6
c77197123d95 importing basic, mostly stubbed changesets
Scott Chacon <schacon@gmail.com>
parents: 5
diff changeset
290 # get a list of all the head shas
12
227b11d75844 updates bookmarks and beginnings of seperate remotes support
Scott Chacon <schacon@gmail.com>
parents: 11
diff changeset
291 for head, sha in self.git.remote_refs(remote_name).iteritems():
5
d6c443a91b18 refactored the git handling stuff out into another class
Scott Chacon <schacon@gmail.com>
parents:
diff changeset
292 todo.append(sha)
19
2be9c0bd88af Warn, but don't fail when bookmarks is not enabled.
Augie Fackler <durin42@gmail.com>
parents: 17
diff changeset
293
6
c77197123d95 importing basic, mostly stubbed changesets
Scott Chacon <schacon@gmail.com>
parents: 5
diff changeset
294 # traverse the heads getting a list of all the unique commits
c77197123d95 importing basic, mostly stubbed changesets
Scott Chacon <schacon@gmail.com>
parents: 5
diff changeset
295 # TODO : stop when we hit a SHA we've already imported
5
d6c443a91b18 refactored the git handling stuff out into another class
Scott Chacon <schacon@gmail.com>
parents:
diff changeset
296 while todo:
d6c443a91b18 refactored the git handling stuff out into another class
Scott Chacon <schacon@gmail.com>
parents:
diff changeset
297 sha = todo.pop()
d6c443a91b18 refactored the git handling stuff out into another class
Scott Chacon <schacon@gmail.com>
parents:
diff changeset
298 assert isinstance(sha, str)
d6c443a91b18 refactored the git handling stuff out into another class
Scott Chacon <schacon@gmail.com>
parents:
diff changeset
299 if sha in done:
d6c443a91b18 refactored the git handling stuff out into another class
Scott Chacon <schacon@gmail.com>
parents:
diff changeset
300 continue
d6c443a91b18 refactored the git handling stuff out into another class
Scott Chacon <schacon@gmail.com>
parents:
diff changeset
301 done.add(sha)
26
a1a5391bc3c3 edit ssh command to quote the path, also convert tags properly on fetch
Scott Chacon <schacon@gmail.com>
parents: 25
diff changeset
302 try:
a1a5391bc3c3 edit ssh command to quote the path, also convert tags properly on fetch
Scott Chacon <schacon@gmail.com>
parents: 25
diff changeset
303 commit = self.git.commit(sha)
a1a5391bc3c3 edit ssh command to quote the path, also convert tags properly on fetch
Scott Chacon <schacon@gmail.com>
parents: 25
diff changeset
304 convert_list[sha] = commit
a1a5391bc3c3 edit ssh command to quote the path, also convert tags properly on fetch
Scott Chacon <schacon@gmail.com>
parents: 25
diff changeset
305 todo.extend([p for p in commit.parents if p not in done])
a1a5391bc3c3 edit ssh command to quote the path, also convert tags properly on fetch
Scott Chacon <schacon@gmail.com>
parents: 25
diff changeset
306 except:
a1a5391bc3c3 edit ssh command to quote the path, also convert tags properly on fetch
Scott Chacon <schacon@gmail.com>
parents: 25
diff changeset
307 print "Cannot import tags yet" # TODO
19
2be9c0bd88af Warn, but don't fail when bookmarks is not enabled.
Augie Fackler <durin42@gmail.com>
parents: 17
diff changeset
308
2be9c0bd88af Warn, but don't fail when bookmarks is not enabled.
Augie Fackler <durin42@gmail.com>
parents: 17
diff changeset
309 # sort the commits
9
7e776864b301 sorts the commits topologically before converting
Scott Chacon <schacon@gmail.com>
parents: 8
diff changeset
310 commits = TopoSort(convert_list).items()
19
2be9c0bd88af Warn, but don't fail when bookmarks is not enabled.
Augie Fackler <durin42@gmail.com>
parents: 17
diff changeset
311
6
c77197123d95 importing basic, mostly stubbed changesets
Scott Chacon <schacon@gmail.com>
parents: 5
diff changeset
312 # import each of the commits, oldest first
9
7e776864b301 sorts the commits topologically before converting
Scott Chacon <schacon@gmail.com>
parents: 8
diff changeset
313 for csha in commits:
7e776864b301 sorts the commits topologically before converting
Scott Chacon <schacon@gmail.com>
parents: 8
diff changeset
314 commit = convert_list[csha]
5
d6c443a91b18 refactored the git handling stuff out into another class
Scott Chacon <schacon@gmail.com>
parents:
diff changeset
315 self.import_git_commit(commit)
19
2be9c0bd88af Warn, but don't fail when bookmarks is not enabled.
Augie Fackler <durin42@gmail.com>
parents: 17
diff changeset
316
13
01f28d40cb6a checks out the HEAD node from a clone
Scott Chacon <schacon@gmail.com>
parents: 12
diff changeset
317 # update Hg bookmarks
12
227b11d75844 updates bookmarks and beginnings of seperate remotes support
Scott Chacon <schacon@gmail.com>
parents: 11
diff changeset
318 bms = {}
227b11d75844 updates bookmarks and beginnings of seperate remotes support
Scott Chacon <schacon@gmail.com>
parents: 11
diff changeset
319 for head, sha in self.git.remote_refs(remote_name).iteritems():
21
13b9a020e382 gpush coming along. will now write blobs it doesn't have yet to git repo.
Scott Chacon <schacon@gmail.com>
parents: 19
diff changeset
320 hgsha = hex_to_sha(self.map_hg_get(sha))
13
01f28d40cb6a checks out the HEAD node from a clone
Scott Chacon <schacon@gmail.com>
parents: 12
diff changeset
321 if not head == 'HEAD':
19
2be9c0bd88af Warn, but don't fail when bookmarks is not enabled.
Augie Fackler <durin42@gmail.com>
parents: 17
diff changeset
322 bms[remote_name + '/' + head] = hgsha
29
2a5c0bf0fef5 Another way of fixing no-bookmark issue, along with updated test.
Augie Fackler <durin42@gmail.com>
parents: 28
diff changeset
323 try:
2a5c0bf0fef5 Another way of fixing no-bookmark issue, along with updated test.
Augie Fackler <durin42@gmail.com>
parents: 28
diff changeset
324 bookmarks.write(self.repo, bms)
2a5c0bf0fef5 Another way of fixing no-bookmark issue, along with updated test.
Augie Fackler <durin42@gmail.com>
parents: 28
diff changeset
325 except AttributeError:
2a5c0bf0fef5 Another way of fixing no-bookmark issue, along with updated test.
Augie Fackler <durin42@gmail.com>
parents: 28
diff changeset
326 self.repo.ui.warn('creating bookmarks failed, do you have'
2a5c0bf0fef5 Another way of fixing no-bookmark issue, along with updated test.
Augie Fackler <durin42@gmail.com>
parents: 28
diff changeset
327 ' bookmarks enabled?\n')
5
d6c443a91b18 refactored the git handling stuff out into another class
Scott Chacon <schacon@gmail.com>
parents:
diff changeset
328
d6c443a91b18 refactored the git handling stuff out into another class
Scott Chacon <schacon@gmail.com>
parents:
diff changeset
329 def import_git_commit(self, commit):
8
2548735d24ef will now more or less correctly determine a changelist from a git commit
Scott Chacon <schacon@gmail.com>
parents: 7
diff changeset
330 print "importing: " + commit.id
24
41f4e0a85d15 fully converts hg changeset/manifest/files to git commits/trees/blobs
Scott Chacon <schacon@gmail.com>
parents: 23
diff changeset
331 # TODO : look for HG metadata in the message and use it
41f4e0a85d15 fully converts hg changeset/manifest/files to git commits/trees/blobs
Scott Chacon <schacon@gmail.com>
parents: 23
diff changeset
332
10
66860f141788 update todo file and removed outdated TODO comments
Scott Chacon <schacon@gmail.com>
parents: 9
diff changeset
333 # TODO : (?) have to handle merge contexts at some point (two parent files, etc)
6
c77197123d95 importing basic, mostly stubbed changesets
Scott Chacon <schacon@gmail.com>
parents: 5
diff changeset
334 def getfilectx(repo, memctx, f):
8
2548735d24ef will now more or less correctly determine a changelist from a git commit
Scott Chacon <schacon@gmail.com>
parents: 7
diff changeset
335 (e, sha, data) = self.git.get_file(commit, f)
2548735d24ef will now more or less correctly determine a changelist from a git commit
Scott Chacon <schacon@gmail.com>
parents: 7
diff changeset
336 e = '' # TODO : make this a real mode
6
c77197123d95 importing basic, mostly stubbed changesets
Scott Chacon <schacon@gmail.com>
parents: 5
diff changeset
337 return context.memfilectx(f, data, 'l' in e, 'x' in e, None)
19
2be9c0bd88af Warn, but don't fail when bookmarks is not enabled.
Augie Fackler <durin42@gmail.com>
parents: 17
diff changeset
338
6
c77197123d95 importing basic, mostly stubbed changesets
Scott Chacon <schacon@gmail.com>
parents: 5
diff changeset
339 p1 = "0" * 40
c77197123d95 importing basic, mostly stubbed changesets
Scott Chacon <schacon@gmail.com>
parents: 5
diff changeset
340 p2 = "0" * 40
7
89992b6d2eef mapping parents properly now
Scott Chacon <schacon@gmail.com>
parents: 6
diff changeset
341 if len(commit.parents) > 0:
89992b6d2eef mapping parents properly now
Scott Chacon <schacon@gmail.com>
parents: 6
diff changeset
342 sha = commit.parents[0]
21
13b9a020e382 gpush coming along. will now write blobs it doesn't have yet to git repo.
Scott Chacon <schacon@gmail.com>
parents: 19
diff changeset
343 p1 = self.map_hg_get(sha)
7
89992b6d2eef mapping parents properly now
Scott Chacon <schacon@gmail.com>
parents: 6
diff changeset
344 if len(commit.parents) > 1:
89992b6d2eef mapping parents properly now
Scott Chacon <schacon@gmail.com>
parents: 6
diff changeset
345 sha = commit.parents[1]
21
13b9a020e382 gpush coming along. will now write blobs it doesn't have yet to git repo.
Scott Chacon <schacon@gmail.com>
parents: 19
diff changeset
346 p2 = self.map_hg_get(sha)
7
89992b6d2eef mapping parents properly now
Scott Chacon <schacon@gmail.com>
parents: 6
diff changeset
347 if len(commit.parents) > 2:
89992b6d2eef mapping parents properly now
Scott Chacon <schacon@gmail.com>
parents: 6
diff changeset
348 # TODO : map extra parents to the extras file
89992b6d2eef mapping parents properly now
Scott Chacon <schacon@gmail.com>
parents: 6
diff changeset
349 pass
6
c77197123d95 importing basic, mostly stubbed changesets
Scott Chacon <schacon@gmail.com>
parents: 5
diff changeset
350
8
2548735d24ef will now more or less correctly determine a changelist from a git commit
Scott Chacon <schacon@gmail.com>
parents: 7
diff changeset
351 files = self.git.get_files_changed(commit)
9
7e776864b301 sorts the commits topologically before converting
Scott Chacon <schacon@gmail.com>
parents: 8
diff changeset
352 #print files
6
c77197123d95 importing basic, mostly stubbed changesets
Scott Chacon <schacon@gmail.com>
parents: 5
diff changeset
353
c77197123d95 importing basic, mostly stubbed changesets
Scott Chacon <schacon@gmail.com>
parents: 5
diff changeset
354 # get a list of the changed, added, removed files
7
89992b6d2eef mapping parents properly now
Scott Chacon <schacon@gmail.com>
parents: 6
diff changeset
355 extra = {}
6
c77197123d95 importing basic, mostly stubbed changesets
Scott Chacon <schacon@gmail.com>
parents: 5
diff changeset
356 text = commit.message
7
89992b6d2eef mapping parents properly now
Scott Chacon <schacon@gmail.com>
parents: 6
diff changeset
357 date = datetime.datetime.fromtimestamp(commit.author_time).strftime("%Y-%m-%d %H:%M:%S")
6
c77197123d95 importing basic, mostly stubbed changesets
Scott Chacon <schacon@gmail.com>
parents: 5
diff changeset
358 ctx = context.memctx(self.repo, (p1, p2), text, files, getfilectx,
c77197123d95 importing basic, mostly stubbed changesets
Scott Chacon <schacon@gmail.com>
parents: 5
diff changeset
359 commit.author, date, extra)
c77197123d95 importing basic, mostly stubbed changesets
Scott Chacon <schacon@gmail.com>
parents: 5
diff changeset
360 a = self.repo.commitctx(ctx)
7
89992b6d2eef mapping parents properly now
Scott Chacon <schacon@gmail.com>
parents: 6
diff changeset
361
89992b6d2eef mapping parents properly now
Scott Chacon <schacon@gmail.com>
parents: 6
diff changeset
362 # get changeset id
89992b6d2eef mapping parents properly now
Scott Chacon <schacon@gmail.com>
parents: 6
diff changeset
363 p2 = hex(self.repo.changelog.tip())
89992b6d2eef mapping parents properly now
Scott Chacon <schacon@gmail.com>
parents: 6
diff changeset
364 # save changeset to mapping file
89992b6d2eef mapping parents properly now
Scott Chacon <schacon@gmail.com>
parents: 6
diff changeset
365 gitsha = commit.id
21
13b9a020e382 gpush coming along. will now write blobs it doesn't have yet to git repo.
Scott Chacon <schacon@gmail.com>
parents: 19
diff changeset
366 self.map_set(gitsha, p2)
19
2be9c0bd88af Warn, but don't fail when bookmarks is not enabled.
Augie Fackler <durin42@gmail.com>
parents: 17
diff changeset
367
6
c77197123d95 importing basic, mostly stubbed changesets
Scott Chacon <schacon@gmail.com>
parents: 5
diff changeset
368 def getfilectx(self, source, repo, memctx, f):
c77197123d95 importing basic, mostly stubbed changesets
Scott Chacon <schacon@gmail.com>
parents: 5
diff changeset
369 v = files[f]
c77197123d95 importing basic, mostly stubbed changesets
Scott Chacon <schacon@gmail.com>
parents: 5
diff changeset
370 data = source.getfile(f, v)
c77197123d95 importing basic, mostly stubbed changesets
Scott Chacon <schacon@gmail.com>
parents: 5
diff changeset
371 e = source.getmode(f, v)
c77197123d95 importing basic, mostly stubbed changesets
Scott Chacon <schacon@gmail.com>
parents: 5
diff changeset
372 return context.memfilectx(f, data, 'l' in e, 'x' in e, copies.get(f))
5
d6c443a91b18 refactored the git handling stuff out into another class
Scott Chacon <schacon@gmail.com>
parents:
diff changeset
373
d6c443a91b18 refactored the git handling stuff out into another class
Scott Chacon <schacon@gmail.com>
parents:
diff changeset
374 def check_bookmarks(self):
d6c443a91b18 refactored the git handling stuff out into another class
Scott Chacon <schacon@gmail.com>
parents:
diff changeset
375 if self.ui.config('extensions', 'hgext.bookmarks') is not None:
d6c443a91b18 refactored the git handling stuff out into another class
Scott Chacon <schacon@gmail.com>
parents:
diff changeset
376 print "YOU NEED TO SETUP BOOKMARKS"
d6c443a91b18 refactored the git handling stuff out into another class
Scott Chacon <schacon@gmail.com>
parents:
diff changeset
377
d6c443a91b18 refactored the git handling stuff out into another class
Scott Chacon <schacon@gmail.com>
parents:
diff changeset
378 def get_transport_and_path(self, uri):
d6c443a91b18 refactored the git handling stuff out into another class
Scott Chacon <schacon@gmail.com>
parents:
diff changeset
379 from dulwich.client import TCPGitClient, SSHGitClient, SubprocessGitClient
26
a1a5391bc3c3 edit ssh command to quote the path, also convert tags properly on fetch
Scott Chacon <schacon@gmail.com>
parents: 25
diff changeset
380 for handler, transport in (("git://", TCPGitClient), ("git@", SSHGitClient)):
5
d6c443a91b18 refactored the git handling stuff out into another class
Scott Chacon <schacon@gmail.com>
parents:
diff changeset
381 if uri.startswith(handler):
26
a1a5391bc3c3 edit ssh command to quote the path, also convert tags properly on fetch
Scott Chacon <schacon@gmail.com>
parents: 25
diff changeset
382 if handler == 'git@':
28
b258ef16ae37 Fix non-ssh URI parsing.
Augie Fackler <durin42@gmail.com>
parents: 26
diff changeset
383 host, path = uri[len(handler):].split(":", 1)
26
a1a5391bc3c3 edit ssh command to quote the path, also convert tags properly on fetch
Scott Chacon <schacon@gmail.com>
parents: 25
diff changeset
384 host = 'git@' + host
28
b258ef16ae37 Fix non-ssh URI parsing.
Augie Fackler <durin42@gmail.com>
parents: 26
diff changeset
385 else:
b258ef16ae37 Fix non-ssh URI parsing.
Augie Fackler <durin42@gmail.com>
parents: 26
diff changeset
386 host, path = uri[len(handler):].split('/', 1)
26
a1a5391bc3c3 edit ssh command to quote the path, also convert tags properly on fetch
Scott Chacon <schacon@gmail.com>
parents: 25
diff changeset
387 return transport(host), '/' + path
5
d6c443a91b18 refactored the git handling stuff out into another class
Scott Chacon <schacon@gmail.com>
parents:
diff changeset
388 # if its not git or git+ssh, try a local url..
d6c443a91b18 refactored the git handling stuff out into another class
Scott Chacon <schacon@gmail.com>
parents:
diff changeset
389 return SubprocessGitClient(), uri
9
7e776864b301 sorts the commits topologically before converting
Scott Chacon <schacon@gmail.com>
parents: 8
diff changeset
390
26
a1a5391bc3c3 edit ssh command to quote the path, also convert tags properly on fetch
Scott Chacon <schacon@gmail.com>
parents: 25
diff changeset
391 ''
9
7e776864b301 sorts the commits topologically before converting
Scott Chacon <schacon@gmail.com>
parents: 8
diff changeset
392 """
7e776864b301 sorts the commits topologically before converting
Scott Chacon <schacon@gmail.com>
parents: 8
diff changeset
393 Tarjan's algorithm and topological sorting implementation in Python
7e776864b301 sorts the commits topologically before converting
Scott Chacon <schacon@gmail.com>
parents: 8
diff changeset
394 by Paul Harrison
7e776864b301 sorts the commits topologically before converting
Scott Chacon <schacon@gmail.com>
parents: 8
diff changeset
395 Public domain, do with it as you will
7e776864b301 sorts the commits topologically before converting
Scott Chacon <schacon@gmail.com>
parents: 8
diff changeset
396 """
7e776864b301 sorts the commits topologically before converting
Scott Chacon <schacon@gmail.com>
parents: 8
diff changeset
397 class TopoSort(object):
19
2be9c0bd88af Warn, but don't fail when bookmarks is not enabled.
Augie Fackler <durin42@gmail.com>
parents: 17
diff changeset
398
9
7e776864b301 sorts the commits topologically before converting
Scott Chacon <schacon@gmail.com>
parents: 8
diff changeset
399 def __init__(self, commitdict):
7e776864b301 sorts the commits topologically before converting
Scott Chacon <schacon@gmail.com>
parents: 8
diff changeset
400 self._sorted = self.robust_topological_sort(commitdict)
7e776864b301 sorts the commits topologically before converting
Scott Chacon <schacon@gmail.com>
parents: 8
diff changeset
401 self._shas = []
7e776864b301 sorts the commits topologically before converting
Scott Chacon <schacon@gmail.com>
parents: 8
diff changeset
402 for level in self._sorted:
11
f2826f7b1ae5 sped up large imports significantly by caching parsed trees and sha_to_hexes
Scott Chacon <schacon@gmail.com>
parents: 10
diff changeset
403 for sha in level:
f2826f7b1ae5 sped up large imports significantly by caching parsed trees and sha_to_hexes
Scott Chacon <schacon@gmail.com>
parents: 10
diff changeset
404 self._shas.append(sha)
19
2be9c0bd88af Warn, but don't fail when bookmarks is not enabled.
Augie Fackler <durin42@gmail.com>
parents: 17
diff changeset
405
9
7e776864b301 sorts the commits topologically before converting
Scott Chacon <schacon@gmail.com>
parents: 8
diff changeset
406 def items(self):
7e776864b301 sorts the commits topologically before converting
Scott Chacon <schacon@gmail.com>
parents: 8
diff changeset
407 self._shas.reverse()
7e776864b301 sorts the commits topologically before converting
Scott Chacon <schacon@gmail.com>
parents: 8
diff changeset
408 return self._shas
19
2be9c0bd88af Warn, but don't fail when bookmarks is not enabled.
Augie Fackler <durin42@gmail.com>
parents: 17
diff changeset
409
9
7e776864b301 sorts the commits topologically before converting
Scott Chacon <schacon@gmail.com>
parents: 8
diff changeset
410 def strongly_connected_components(self, graph):
7e776864b301 sorts the commits topologically before converting
Scott Chacon <schacon@gmail.com>
parents: 8
diff changeset
411 """ Find the strongly connected components in a graph using
7e776864b301 sorts the commits topologically before converting
Scott Chacon <schacon@gmail.com>
parents: 8
diff changeset
412 Tarjan's algorithm.
7e776864b301 sorts the commits topologically before converting
Scott Chacon <schacon@gmail.com>
parents: 8
diff changeset
413
7e776864b301 sorts the commits topologically before converting
Scott Chacon <schacon@gmail.com>
parents: 8
diff changeset
414 graph should be a dictionary mapping node names to
7e776864b301 sorts the commits topologically before converting
Scott Chacon <schacon@gmail.com>
parents: 8
diff changeset
415 lists of successor nodes.
7e776864b301 sorts the commits topologically before converting
Scott Chacon <schacon@gmail.com>
parents: 8
diff changeset
416 """
7e776864b301 sorts the commits topologically before converting
Scott Chacon <schacon@gmail.com>
parents: 8
diff changeset
417
7e776864b301 sorts the commits topologically before converting
Scott Chacon <schacon@gmail.com>
parents: 8
diff changeset
418 result = [ ]
7e776864b301 sorts the commits topologically before converting
Scott Chacon <schacon@gmail.com>
parents: 8
diff changeset
419 stack = [ ]
7e776864b301 sorts the commits topologically before converting
Scott Chacon <schacon@gmail.com>
parents: 8
diff changeset
420 low = { }
7e776864b301 sorts the commits topologically before converting
Scott Chacon <schacon@gmail.com>
parents: 8
diff changeset
421
7e776864b301 sorts the commits topologically before converting
Scott Chacon <schacon@gmail.com>
parents: 8
diff changeset
422 def visit(node):
7e776864b301 sorts the commits topologically before converting
Scott Chacon <schacon@gmail.com>
parents: 8
diff changeset
423 if node in low: return
7e776864b301 sorts the commits topologically before converting
Scott Chacon <schacon@gmail.com>
parents: 8
diff changeset
424
7e776864b301 sorts the commits topologically before converting
Scott Chacon <schacon@gmail.com>
parents: 8
diff changeset
425 num = len(low)
7e776864b301 sorts the commits topologically before converting
Scott Chacon <schacon@gmail.com>
parents: 8
diff changeset
426 low[node] = num
7e776864b301 sorts the commits topologically before converting
Scott Chacon <schacon@gmail.com>
parents: 8
diff changeset
427 stack_pos = len(stack)
7e776864b301 sorts the commits topologically before converting
Scott Chacon <schacon@gmail.com>
parents: 8
diff changeset
428 stack.append(node)
7e776864b301 sorts the commits topologically before converting
Scott Chacon <schacon@gmail.com>
parents: 8
diff changeset
429
7e776864b301 sorts the commits topologically before converting
Scott Chacon <schacon@gmail.com>
parents: 8
diff changeset
430 for successor in graph[node].parents:
7e776864b301 sorts the commits topologically before converting
Scott Chacon <schacon@gmail.com>
parents: 8
diff changeset
431 visit(successor)
7e776864b301 sorts the commits topologically before converting
Scott Chacon <schacon@gmail.com>
parents: 8
diff changeset
432 low[node] = min(low[node], low[successor])
7e776864b301 sorts the commits topologically before converting
Scott Chacon <schacon@gmail.com>
parents: 8
diff changeset
433
7e776864b301 sorts the commits topologically before converting
Scott Chacon <schacon@gmail.com>
parents: 8
diff changeset
434 if num == low[node]:
7e776864b301 sorts the commits topologically before converting
Scott Chacon <schacon@gmail.com>
parents: 8
diff changeset
435 component = tuple(stack[stack_pos:])
7e776864b301 sorts the commits topologically before converting
Scott Chacon <schacon@gmail.com>
parents: 8
diff changeset
436 del stack[stack_pos:]
7e776864b301 sorts the commits topologically before converting
Scott Chacon <schacon@gmail.com>
parents: 8
diff changeset
437 result.append(component)
7e776864b301 sorts the commits topologically before converting
Scott Chacon <schacon@gmail.com>
parents: 8
diff changeset
438 for item in component:
7e776864b301 sorts the commits topologically before converting
Scott Chacon <schacon@gmail.com>
parents: 8
diff changeset
439 low[item] = len(graph)
7e776864b301 sorts the commits topologically before converting
Scott Chacon <schacon@gmail.com>
parents: 8
diff changeset
440
7e776864b301 sorts the commits topologically before converting
Scott Chacon <schacon@gmail.com>
parents: 8
diff changeset
441 for node in graph:
7e776864b301 sorts the commits topologically before converting
Scott Chacon <schacon@gmail.com>
parents: 8
diff changeset
442 visit(node)
7e776864b301 sorts the commits topologically before converting
Scott Chacon <schacon@gmail.com>
parents: 8
diff changeset
443
7e776864b301 sorts the commits topologically before converting
Scott Chacon <schacon@gmail.com>
parents: 8
diff changeset
444 return result
7e776864b301 sorts the commits topologically before converting
Scott Chacon <schacon@gmail.com>
parents: 8
diff changeset
445
7e776864b301 sorts the commits topologically before converting
Scott Chacon <schacon@gmail.com>
parents: 8
diff changeset
446
7e776864b301 sorts the commits topologically before converting
Scott Chacon <schacon@gmail.com>
parents: 8
diff changeset
447 def topological_sort(self, graph):
7e776864b301 sorts the commits topologically before converting
Scott Chacon <schacon@gmail.com>
parents: 8
diff changeset
448 count = { }
7e776864b301 sorts the commits topologically before converting
Scott Chacon <schacon@gmail.com>
parents: 8
diff changeset
449 for node in graph:
7e776864b301 sorts the commits topologically before converting
Scott Chacon <schacon@gmail.com>
parents: 8
diff changeset
450 count[node] = 0
7e776864b301 sorts the commits topologically before converting
Scott Chacon <schacon@gmail.com>
parents: 8
diff changeset
451 for node in graph:
7e776864b301 sorts the commits topologically before converting
Scott Chacon <schacon@gmail.com>
parents: 8
diff changeset
452 for successor in graph[node]:
7e776864b301 sorts the commits topologically before converting
Scott Chacon <schacon@gmail.com>
parents: 8
diff changeset
453 count[successor] += 1
7e776864b301 sorts the commits topologically before converting
Scott Chacon <schacon@gmail.com>
parents: 8
diff changeset
454
7e776864b301 sorts the commits topologically before converting
Scott Chacon <schacon@gmail.com>
parents: 8
diff changeset
455 ready = [ node for node in graph if count[node] == 0 ]
7e776864b301 sorts the commits topologically before converting
Scott Chacon <schacon@gmail.com>
parents: 8
diff changeset
456
7e776864b301 sorts the commits topologically before converting
Scott Chacon <schacon@gmail.com>
parents: 8
diff changeset
457 result = [ ]
7e776864b301 sorts the commits topologically before converting
Scott Chacon <schacon@gmail.com>
parents: 8
diff changeset
458 while ready:
7e776864b301 sorts the commits topologically before converting
Scott Chacon <schacon@gmail.com>
parents: 8
diff changeset
459 node = ready.pop(-1)
7e776864b301 sorts the commits topologically before converting
Scott Chacon <schacon@gmail.com>
parents: 8
diff changeset
460 result.append(node)
7e776864b301 sorts the commits topologically before converting
Scott Chacon <schacon@gmail.com>
parents: 8
diff changeset
461
7e776864b301 sorts the commits topologically before converting
Scott Chacon <schacon@gmail.com>
parents: 8
diff changeset
462 for successor in graph[node]:
7e776864b301 sorts the commits topologically before converting
Scott Chacon <schacon@gmail.com>
parents: 8
diff changeset
463 count[successor] -= 1
7e776864b301 sorts the commits topologically before converting
Scott Chacon <schacon@gmail.com>
parents: 8
diff changeset
464 if count[successor] == 0:
7e776864b301 sorts the commits topologically before converting
Scott Chacon <schacon@gmail.com>
parents: 8
diff changeset
465 ready.append(successor)
7e776864b301 sorts the commits topologically before converting
Scott Chacon <schacon@gmail.com>
parents: 8
diff changeset
466
7e776864b301 sorts the commits topologically before converting
Scott Chacon <schacon@gmail.com>
parents: 8
diff changeset
467 return result
7e776864b301 sorts the commits topologically before converting
Scott Chacon <schacon@gmail.com>
parents: 8
diff changeset
468
7e776864b301 sorts the commits topologically before converting
Scott Chacon <schacon@gmail.com>
parents: 8
diff changeset
469
7e776864b301 sorts the commits topologically before converting
Scott Chacon <schacon@gmail.com>
parents: 8
diff changeset
470 def robust_topological_sort(self, graph):
7e776864b301 sorts the commits topologically before converting
Scott Chacon <schacon@gmail.com>
parents: 8
diff changeset
471 """ First identify strongly connected components,
7e776864b301 sorts the commits topologically before converting
Scott Chacon <schacon@gmail.com>
parents: 8
diff changeset
472 then perform a topological sort on these components. """
7e776864b301 sorts the commits topologically before converting
Scott Chacon <schacon@gmail.com>
parents: 8
diff changeset
473
7e776864b301 sorts the commits topologically before converting
Scott Chacon <schacon@gmail.com>
parents: 8
diff changeset
474 components = self.strongly_connected_components(graph)
7e776864b301 sorts the commits topologically before converting
Scott Chacon <schacon@gmail.com>
parents: 8
diff changeset
475
7e776864b301 sorts the commits topologically before converting
Scott Chacon <schacon@gmail.com>
parents: 8
diff changeset
476 node_component = { }
7e776864b301 sorts the commits topologically before converting
Scott Chacon <schacon@gmail.com>
parents: 8
diff changeset
477 for component in components:
7e776864b301 sorts the commits topologically before converting
Scott Chacon <schacon@gmail.com>
parents: 8
diff changeset
478 for node in component:
7e776864b301 sorts the commits topologically before converting
Scott Chacon <schacon@gmail.com>
parents: 8
diff changeset
479 node_component[node] = component
7e776864b301 sorts the commits topologically before converting
Scott Chacon <schacon@gmail.com>
parents: 8
diff changeset
480
7e776864b301 sorts the commits topologically before converting
Scott Chacon <schacon@gmail.com>
parents: 8
diff changeset
481 component_graph = { }
7e776864b301 sorts the commits topologically before converting
Scott Chacon <schacon@gmail.com>
parents: 8
diff changeset
482 for component in components:
7e776864b301 sorts the commits topologically before converting
Scott Chacon <schacon@gmail.com>
parents: 8
diff changeset
483 component_graph[component] = [ ]
7e776864b301 sorts the commits topologically before converting
Scott Chacon <schacon@gmail.com>
parents: 8
diff changeset
484
7e776864b301 sorts the commits topologically before converting
Scott Chacon <schacon@gmail.com>
parents: 8
diff changeset
485 for node in graph:
7e776864b301 sorts the commits topologically before converting
Scott Chacon <schacon@gmail.com>
parents: 8
diff changeset
486 node_c = node_component[node]
7e776864b301 sorts the commits topologically before converting
Scott Chacon <schacon@gmail.com>
parents: 8
diff changeset
487 for successor in graph[node].parents:
7e776864b301 sorts the commits topologically before converting
Scott Chacon <schacon@gmail.com>
parents: 8
diff changeset
488 successor_c = node_component[successor]
7e776864b301 sorts the commits topologically before converting
Scott Chacon <schacon@gmail.com>
parents: 8
diff changeset
489 if node_c != successor_c:
19
2be9c0bd88af Warn, but don't fail when bookmarks is not enabled.
Augie Fackler <durin42@gmail.com>
parents: 17
diff changeset
490 component_graph[node_c].append(successor_c)
9
7e776864b301 sorts the commits topologically before converting
Scott Chacon <schacon@gmail.com>
parents: 8
diff changeset
491
7e776864b301 sorts the commits topologically before converting
Scott Chacon <schacon@gmail.com>
parents: 8
diff changeset
492 return self.topological_sort(component_graph)