summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bztogl/common.py85
-rwxr-xr-xbztogl/phabtogl.py403
-rw-r--r--bztogl/template.py16
3 files changed, 423 insertions, 81 deletions
diff --git a/bztogl/common.py b/bztogl/common.py
index 098988f..920caa4 100644
--- a/bztogl/common.py
+++ b/bztogl/common.py
@@ -16,6 +16,10 @@ class GitLab:
16 self.target_project = target_project 16 self.target_project = target_project
17 self.automate = automate 17 self.automate = automate
18 self.all_users = None 18 self.all_users = None
19 self.all_users_map = {}
20 self.project = None
21 self.milestones = {}
22 self.labels = {}
19 23
20 def connect(self): 24 def connect(self):
21 print("Connecting to %s" % self.gl_url) 25 print("Connecting to %s" % self.gl_url)
@@ -29,7 +33,9 @@ class GitLab:
29 " provided".format(self.target_project)) 33 " provided".format(self.target_project))
30 34
31 def get_project(self): 35 def get_project(self):
32 return self.gl.projects.get(self.target_project) 36 if not self.project:
37 self.project = self.gl.projects.get(self.target_project)
38 return self.project
33 39
34 def create_issue(self, id, summary, description, labels, 40 def create_issue(self, id, summary, description, labels,
35 milestone, creation_time, sudo=None): 41 milestone, creation_time, sudo=None):
@@ -41,24 +47,91 @@ class GitLab:
41 } 47 }
42 48
43 if milestone: 49 if milestone:
44 payload['milestone_id'] = milestone.id 50 if not milestone in self.milestones:
51 try:
52 gl_milestone = self.get_project().milestones.create({'title': milestone})
53 except:
54 print("milestone %s already exists" % (milestone))
55 gl_milestones = self.get_project().milestones.list(search=milestone)
56 gl_milestone = gl_milestones[0]
57 self.milestones[milestone] = gl_milestone
58 gl_milestone = self.milestones[milestone]
59 payload['milestone_id'] = gl_milestone.id
60
61 if labels:
62 for label in labels:
63 if not label in self.labels:
64 try:
65 self.get_project().labels.create({'name': label, 'color': '#428BCA'})
66 except:
67 print("label %s already exists" % (label))
68 self.labels[label] = True
45 69
46 return self.get_project().issues.create(payload, sudo=sudo) 70 return self.get_project().issues.create(payload, sudo=sudo)
47 71
72 def create_mergerequest(self, id, summary, description, labels,
73 milestone, sudo=None):
74 payload = {
75 'title': summary,
76 'description': description,
77 'labels': labels,
78 'source_branch': "phab-" + str(id),
79 'target_branch': 'master'
80 }
81
82 if milestone:
83 if not milestone in self.milestones:
84 try:
85 gl_milestone = self.get_project().milestones.create({'title': milestone})
86 except:
87 print("milestone %s already exists" % (milestone))
88 gl_milestones = self.get_project().milestones.list(search=milestone)
89 gl_milestone = gl_milestones[0]
90 self.milestones[milestone] = gl_milestone
91 gl_milestone = self.milestones[milestone]
92 payload['milestone_id'] = gl_milestone.id
93
94 if labels:
95 for label in labels:
96 if not label in self.labels:
97 try:
98 self.get_project().labels.create({'name': label, 'color': '#428BCA'})
99 except:
100 print("label %s already exists" % (label))
101 self.labels[label] = True
102
103 return self.get_project().mergerequests.create(payload, sudo=sudo)
104
105 def create_user(self, user_id):
106 return self.gl.users.create({'email': '{}@localhost'.format(user_id),
107 'reset_password': 'true',
108 'username': user_id,
109 'name': user_id})
110
48 def get_all_users(self): 111 def get_all_users(self):
49 if self.all_users is None: 112 if self.all_users is None:
50 self.all_users = self.gl.users.list(all=True) 113 self.all_users = self.gl.users.list(all=True)
114 for user in self.all_users:
115 print("adding user to cache %s" % (user.attributes['username']))
116 self.all_users_map[user.attributes['username']] = user
51 117
52 return self.all_users 118 return self.all_users
53 119
120 def find_issue(self, title, creation_time):
121 return self.get_project().issues.list(search=title, created_after=creation_time)
122
123 def find_patch(self, title, creation_time):
124 return self.get_project().mergerequests.list(search=title)
125
54 def find_user(self, user_id): 126 def find_user(self, user_id):
55 return self.gl.users.get(user_id) 127 return self.gl.users.get(user_id)
56 128
57 def find_user_by_nick(self, nickname): 129 def find_user_by_nick(self, nickname):
58 for user in self.get_all_users(): 130 if self.all_users == None:
59 if user.attributes['username'] == nickname: 131 self.get_all_users()
60 return user
61 132
133 if nickname in self.all_users_map:
134 return self.all_users_map[nickname]
62 return None 135 return None
63 136
64 def remove_project(self, project): 137 def remove_project(self, project):
@@ -117,7 +190,7 @@ class GitLab:
117 import_status = self.get_import_status(project) 190 import_status = self.get_import_status(project)
118 191
119 def upload_file(self, filename, f): 192 def upload_file(self, filename, f):
120 url = "{}api/v3/projects/{}/uploads".format(self.gl_url, 193 url = "{}api/v4/projects/{}/uploads".format(self.gl_url,
121 self.get_project().id) 194 self.get_project().id)
122 self.gl.session.headers = {"PRIVATE-TOKEN": self.token} 195 self.gl.session.headers = {"PRIVATE-TOKEN": self.token}
123 ret = self.gl.session.post(url, files={ 196 ret = self.gl.session.post(url, files={
diff --git a/bztogl/phabtogl.py b/bztogl/phabtogl.py
index 3b5111b..6c179f6 100755
--- a/bztogl/phabtogl.py
+++ b/bztogl/phabtogl.py
@@ -5,6 +5,7 @@ import json
5import os 5import os
6import re 6import re
7import sys 7import sys
8import time
8 9
9import phabricator 10import phabricator
10 11
@@ -15,14 +16,6 @@ from . import common
15 16
16ON_WINDOWS = os.name == 'nt' 17ON_WINDOWS = os.name == 'nt'
17 18
18KEYWORD_MAP = {
19 "Pitivi tasks for newcomers": "4. Newcomers",
20 "translations": "8. Translation",
21 "titles editor": "title clips",
22 "bundles": "binaries"
23}
24
25
26MIGR_TEMPLATE = """# GitLab Migration Automatic Message 19MIGR_TEMPLATE = """# GitLab Migration Automatic Message
27 20
28This bug has been migrated to freedesltop.org's GitLab instance and has been closed \ 21This bug has been migrated to freedesltop.org's GitLab instance and has been closed \
@@ -74,7 +67,7 @@ class PhabGitLab(common.GitLab):
74 automate) 67 automate)
75 self.close_tasks = close_tasks 68 self.close_tasks = close_tasks
76 69
77 def import_from_phab(self, phab, start_at): 70 def import_tasks_from_phab(self, phab, start_at):
78 """Imports project tasks from phabricator""" 71 """Imports project tasks from phabricator"""
79 72
80 if self.target_project: 73 if self.target_project:
@@ -82,7 +75,7 @@ class PhabGitLab(common.GitLab):
82 else: 75 else:
83 projname = self.project 76 projname = self.project
84 77
85 for _id, task in sorted(phab.tasks.items()): 78 for _id, task in phab.tasks.items():
86 if start_at and _id < start_at: 79 if start_at and _id < start_at:
87 continue 80 continue
88 81
@@ -90,45 +83,55 @@ class PhabGitLab(common.GitLab):
90 template.render_issue_description( 83 template.render_issue_description(
91 None, task, phab.escape_markdown( 84 None, task, phab.escape_markdown(
92 task["description"]), phab.users, 85 task["description"]), phab.users,
93 importing_address=os.path.join(phab.phabricator_uri, "T"), 86 task['uri'],
94 bug_url_function=phab.task_url) 87 bug_url_function=phab.task_url)
95 88
96 labels = ['phabricator'] 89 labels = ['phabricator']
90 milestone = None
97 for project in task.projects.values(): 91 for project in task.projects.values():
98 if project["name"] != projname: 92 if project['fields']['milestone']:
99 # FIXME - Find a way to generically strip what should be 93 if project['fields']['parent']['phid'] in phab.used_projects:
100 # stripped. 94 milestone = project['fields']["name"]
101 label = KEYWORD_MAP.get(project["name"], project["name"]) 95 elif project['fields']["name"] != projname:
102 for to_strip in ["pitivi_", "pitivi", "ptv_", "ptv", 96 labels.append(project['fields']["name"])
103 "Pitivi", " "]: 97
104 label = label.strip(to_strip) 98 labels.append(task['priority'])
105 labels.append(label)
106 99
107 if not task["title"]: 100 if not task["title"]:
108 print("WARNING task %s doesn't have a title!" % _id) 101 print("WARNING task %s doesn't have a title!" % _id)
109 continue 102 continue
103 creation_time = datetime.datetime.fromtimestamp(
104 int(task["dateCreated"])
105 ).strftime('%Y-%m-%d %H:%M:%S')
110 106
111 # Assign bug to actual account if exists 107 # Assign bug to actual account if exists
112 phabauthor = phab.users.get(task["authorPHID"]) 108 phabauthor = phab.users.get(task["authorPHID"])
113 if phabauthor: 109 if phabauthor:
114 author = self.find_user_by_nick(phabauthor.username) 110 author = self.find_user_by_nick(phabauthor.username)
115 if author: 111 if not author:
116 author = author.id 112 try:
113 author = self.create_user(phabauthor.username)
114 except:
115 pass
116 author = phabauthor.username
117 else: 117 else:
118 author = None 118 author = None
119 119
120 phabowner = phab.users.get(task["ownerPHID"]) 120 phabowner = phab.users.get(task["ownerPHID"])
121 if phabowner: 121 if phabowner:
122 assignee = self.find_user_by_nick(phabowner.username) 122 assignee = self.find_user_by_nick(phabowner.username)
123 if not assignee:
124 try:
125 assignee = self.create_user(phabowner.username)
126 except:
127 pass
123 else: 128 else:
124 assignee = None 129 assignee = None
125 130
126 issue = self.create_issue(_id, task["title"], 131 issue = self.create_issue(_id, task["title"],
127 description, labels, 132 description, labels,
128 None, 133 milestone,
129 datetime.datetime.fromtimestamp( 134 creation_time#, sudo=author
130 int(task["dateCreated"])
131 ).strftime('%Y-%m-%d %H:%M:%S')#, sudo=author
132 ) 135 )
133 136
134 if assignee: 137 if assignee:
@@ -138,18 +141,21 @@ class PhabGitLab(common.GitLab):
138 (_id, issue.get_id(), issue.attributes['title'])) 141 (_id, issue.get_id(), issue.attributes['title']))
139 142
140 for comment in task.comments: 143 for comment in task.comments:
144 sudo = None
141 emoji, action, body = ('speech_balloon', 'said', 145 emoji, action, body = ('speech_balloon', 'said',
142 comment["comments"]) 146 comment["comments"])
143 author = phab.users[comment["authorPHID"]] 147 comment_author = comment["authorPHID"]
144 if phabowner: 148 if comment_author.startswith("PHID-APPS"):
145 sudo = self.find_user_by_nick(author.username) 149 author = comment_author.rsplit("-")[2]
146 if sudo:
147 sudo = sudo.id
148 else: 150 else:
149 sudo = None 151 author = phab.users[comment_author].display_name()
152 if phabowner:
153 sudo = self.find_user_by_nick(phab.users[comment_author].username)
154 if sudo:
155 sudo = sudo.id
150 assignee = None 156 assignee = None
151 gitlab_comment = template.render_comment( 157 gitlab_comment = template.render_comment(
152 None, emoji, author.display_name(), 158 None, emoji, author,
153 action, phab.escape_markdown(body), 159 action, phab.escape_markdown(body),
154 "", bug_url_function=phab.task_url) 160 "", bug_url_function=phab.task_url)
155 161
@@ -175,18 +181,112 @@ class PhabGitLab(common.GitLab):
175 "value": MIGR_TEMPLATE.format(issue.web_url)}]) 181 "value": MIGR_TEMPLATE.format(issue.web_url)}])
176 phab.phabricator.maniphest.update(id=_id, status='resolved') 182 phab.phabricator.maniphest.update(id=_id, status='resolved')
177 183
184 def import_revisions_from_phab(self, phab, start_at):
185 """Imports project patches from phabricator"""
186
187 if self.target_project:
188 projname = self.target_project.split("/")[1]
189 else:
190 projname = self.project
191
192 for _id, revision in phab.revisions.items():
193 if start_at and _id < start_at:
194 continue
195
196 description = \
197 template.render_issue_description(
198 None, revision, phab.escape_markdown(
199 revision["summary"]), phab.users,
200 revision['uri'],
201 bug_url_function=phab.diff_url)
202
203 labels = ['phabricator']
204 milestone = None
205 for project in revision.projects.values():
206 if project['fields']['milestone']:
207 if project['fields']['parent']['phid'] in phab.used_projects:
208 milestone = project['fields']["name"]
209 elif project['fields']["name"] != projname:
210 labels.append(project['fields']["name"])
211
212 if not revision["title"]:
213 print("WARNING revision %s doesn't have a title!" % _id)
214 continue
215 print("Creating revision %s: %s" % (revision['id'], revision['title']))
216
217 # Assign bug to actual account if exists
218 phabauthor = phab.users.get(revision["authorPHID"])
219 if phabauthor:
220 author = self.find_user_by_nick(phabauthor.username)
221 if not author:
222 try:
223 author = self.create_user(phabauthor.username)
224 except:
225 pass
226 author = phabauthor.username
227 else:
228 author = None
229
230 assignee = None
231 phabowners = revision["reviewers"]
232 if phabowners:
233 phabowner = phab.users.get(list(phabowners.values())[0])
234 if phabowner:
235 assignee = self.find_user_by_nick(phabowner.username)
236 if not assignee:
237 try:
238 assignee = self.create_user(phabowner.username)
239 except:
240 pass
241 if not assignee:
242 assignee = None
243
244 if revision.diff != "":
245 desc = description + "\n```\n" + revision.diff + "\n```"
246 else:
247 desc = description
248 mergerequest = self.create_mergerequest(_id, revision["title"],
249 desc, labels,
250 milestone#, sudo=author
251 )
252
253 if assignee:
254 mergerequest.assignee_id = assignee.id
255
256 print("Created %s - %s: %s" %
257 (_id, mergerequest.get_id(), mergerequest.attributes['title']))
258
259 state_event = 'reopen'
260 if revision.merged:
261 # mergerequest.merge()
262 if revision['commits']:
263 commits = phab.phabricator.phid.query(phids=revision['commits'])
264 commit = list(commits.values())[0]
265 info = commit['fullName']
266 for callsign in phab.callsigns:
267 msg = info.replace('r' + callsign, '', 1)
268 if msg != info:
269 mergerequest.notes.create({
270 'body': msg,
271 })
272 state_event = "close"
273 elif revision.abandoned:
274 state_event = "close"
275 mergerequest.state_event = state_event
276
277 mergerequest.save(state_event=state_event)
278
178 279
179class Task: 280class Task:
180 def __init__(self, entry, all_projects, all_tasks): 281 def __init__(self, entry, all_projects, all_tasks):
181 self.entry = entry 282 self.entry = entry
182 self.projects = {} 283 self.projects = {}
183 for phid in entry["projectPHIDs"]: 284 for phid in entry["projectPHIDs"]:
184 self.projects[phid] = all_projects.data[phid] 285 self.projects[phid] = all_projects[phid]
185 self.depends_on = [] 286 self.depends_on = []
186 for phid in self.entry["dependsOnTaskPHIDs"]: 287 for phid in self.entry["dependsOnTaskPHIDs"]:
187 if phid in all_tasks: 288 if phid in all_tasks:
188 self.depends_on.append(all_tasks[phid]["id"]) 289 self.depends_on.append(all_tasks[phid]["id"])
189
190 @property 290 @property
191 def assigned_to(self): 291 def assigned_to(self):
192 if self.entry["ownerPHID"]: 292 if self.entry["ownerPHID"]:
@@ -223,6 +323,69 @@ class Task:
223 def version(self): 323 def version(self):
224 return None 324 return None
225 325
326 @property
327 def creator(self):
328 return self.entry["authorPHID"]
329
330 def __getitem__(self, key):
331 return self.entry[key]
332
333class Revision:
334 def __init__(self, entry, all_projects, all_revisions, diff):
335 self.entry = entry
336 self.projects = {}
337 for phid in entry["auxiliary"]['phabricator:projects']:
338 self.projects[phid] = all_projects[phid]
339 self.depends_on = []
340 for phid in entry["auxiliary"]['phabricator:depends-on']:
341 if phid in all_revisions:
342 self.depends_on.append(all_revisions[phid]["id"])
343
344 self.diff = diff
345
346 @property
347 def assigned_to(self):
348 for person in self.entry["reviewers"]:
349 if not person.startswith("PHID-PROJ"):
350 return person
351 for person in self.entry["ccs"]:
352 if not person.startswith("PHID-PROJ"):
353 return person
354 return None
355
356 @property
357 def id(self):
358 return self.entry["id"]
359
360 @property
361 def merged(self):
362 return self.entry["statusName"] == "Closed"
363
364 @property
365 def abandoned(self):
366 return self.entry["statusName"] == "Abandoned"
367
368 @property
369 def creator(self):
370 return self.entry["authorPHID"]
371
372 @property
373 def comments(self):
374 return self.entry.get("comments", [])
375
376 @property
377 def blocks(self):
378 # FIXME!
379 return []
380
381 @property
382 def see_also(self):
383 return []
384
385 @property
386 def version(self):
387 return None
388
226 def __getitem__(self, key): 389 def __getitem__(self, key):
227 return self.entry[key] 390 return self.entry[key]
228 391
@@ -234,13 +397,21 @@ class Phab:
234 def __init__(self, options, gitlab): 397 def __init__(self, options, gitlab):
235 self._phabricator = None 398 self._phabricator = None
236 self.arcrc = None 399 self.arcrc = None
237 self.phabricator_uri = "https://phabricator.freedesktop.org/" 400 self.phabricator_uri = "https://phab.enlightenment.org/"
238 self.projects = options.projects 401 self.projects = options.projects
402 self.callsigns = options.callsigns
403 self.start_at = options.start_at
404 if not self.start_at:
405 self.start_at = 1
406 self.rev_start_at = options.rev_start_at
407 if not self.rev_start_at:
408 self.rev_start_at = 1
239 409
240 self.users = {} 410 self.users = {}
411 self.gitlab = gitlab
241 self.ensure_project_phids() 412 self.ensure_project_phids()
242 self.retrieve_all_tasks() 413 self.retrieve_all_tasks()
243 self.gitlab = gitlab 414 self.retrieve_all_revisions()
244 415
245 def migrate_attachment(self, fileid): 416 def migrate_attachment(self, fileid):
246 finfo = self.phabricator.file.info(id=int(fileid)) 417 finfo = self.phabricator.file.info(id=int(fileid))
@@ -274,7 +445,7 @@ class Phab:
274 445
275 # Link Tasks and Differentials 446 # Link Tasks and Differentials
276 markdown = re.sub( 447 markdown = re.sub(
277 r'\b#?([TD][0-9]+)', '[\\1](%s/\\1)' % ("https://phabricator.freedesktop.org"), 448 r'\b#?([TD][0-9]+)', '[\\1](%s/\\1)' % ("https://phab.enlightenment.org"),
278 markdown) 449 markdown)
279 450
280 # Avoid losing new lines. 451 # Avoid losing new lines.
@@ -307,6 +478,9 @@ class Phab:
307 def task_url(self, garbage, task_id): 478 def task_url(self, garbage, task_id):
308 return os.path.join(self.phabricator_uri, "T" + task_id) 479 return os.path.join(self.phabricator_uri, "T" + task_id)
309 480
481 def diff_url(self, garbage, task_id):
482 return os.path.join(self.phabricator_uri, "D" + task_id)
483
310 def retrieve_all_comments(self, ids, users): 484 def retrieve_all_comments(self, ids, users):
311 all_transactions = self.phabricator.maniphest.gettasktransactions( 485 all_transactions = self.phabricator.maniphest.gettasktransactions(
312 ids=ids) 486 ids=ids)
@@ -336,42 +510,125 @@ class Phab:
336 510
337 self.tasks = {} 511 self.tasks = {}
338 users = set() 512 users = set()
339 all_tasks = self.phabricator.maniphest.query(limit=9999999999, status="status-open", projectPHIDs=self.project_phids) 513 all_tasks = {}
340 for task in all_tasks.items(): 514 for phid in self.project_phids:
341 for phid in task[1]['projectPHIDs']: 515 phidlist = []
342 if phid in self.project_phids: 516 phidlist.append(phid)
343 task = task[1] 517 print("fetching tasks for %s (%s)" % (self.all_projects[phid]['fields']['slug'], phidlist))
344 id = int(task["id"]) 518 cur_tasks = self.phabricator.maniphest.query(limit=9999999999, order='created', projectPHIDs=phidlist)
345 ids.append(id) 519 all_tasks = {**all_tasks, **cur_tasks}
346 self.tasks[id] = Task(task, self.all_projects, all_tasks) 520 for task in sorted(all_tasks.items(), key=lambda t: int(t[1]['id'])):
347 users.add(task["authorPHID"]) 521 print("Evaluating task %s: %s" % (task[1]['id'], task[1]['title']))
348 users.update(task["ccPHIDs"]) 522 creation_time = datetime.datetime.fromtimestamp(
349 users.add(task["ownerPHID"]) 523 int(task[1]["dateCreated"])
350 524 ).strftime('%Y-%m-%d %H:%M:%S')
351 break 525
526 if self.gitlab.find_issue(task[1]["title"], creation_time):
527 print("Task already exists: %s" % task[1]["title"])
528 continue
529 skip = False
530 for projphid in task[1]['projectPHIDs']:
531 if not projphid in self.all_projects:
532 projphidlist = []
533 projphidlist.append(projphid)
534 projects = self.phabricator.project.search(limit=100, constraints=({'phids': projphidlist}))
535 self.all_projects[projphid] = projects.data[0]
536 if projects.data[0]['fields']['name'] == 'Spam':
537 skip = True
538 break
539 print("Adding additional project: %s" % (projects.data[0]['fields']['name']))
540 if skip:
541 continue
542 task = task[1]
543 id = int(task["id"])
544 if self.start_at and id >= self.start_at:
545 ids.append(id)
546 self.tasks[id] = Task(task, self.all_projects, all_tasks)
547 users.add(task["authorPHID"])
548 users.update(task["ccPHIDs"])
549 users.add(task["ownerPHID"])
550
352 551
353 self.retrieve_all_users(users) 552 self.retrieve_all_users(users)
354 self.retrieve_all_comments(ids, users) 553 self.retrieve_all_comments(ids, users)
355 554
356 def ensure_project_phids(self): 555 def retrieve_all_revisions(self):
357 self.all_projects = self.phabricator.project.query(limit=9999999999, status="status-open")
358 556
359 self.project_phids = [] 557 users = set()
360 project_map = {} 558 self.revisions = {}
361 for (phid, data) in self.all_projects.data.items(): 559 revs = {}
362 project_map[data["name"].lower()] = phid 560 all_revisions = self.phabricator.differential.query(limit=9999999999, order='created', paths=list(zip(self.callsigns, [""])))
363 for s in data["slugs"]: 561 for rev in all_revisions:
364 project_map[s.lower()] = phid 562 revs[rev['id']] = rev
563 for rev in sorted(all_revisions, key=lambda t: int(t['id'])):
564 id = int(rev["id"])
565 if self.rev_start_at and id < self.rev_start_at:
566 continue
567 print("Evaluating revision %s: %s" % (rev['id'], rev['title']), end='')
568 creation_time = datetime.datetime.fromtimestamp(
569 int(rev["dateCreated"])
570 ).strftime('%Y-%m-%d %H:%M:%S')
571
572 if self.gitlab.find_patch(rev["title"], creation_time):
573 print(" || Rev already exists--skipping")
574 continue
575
576 for projphid in rev["auxiliary"]['phabricator:projects']:
577 if not projphid in self.all_projects:
578 projphidlist = []
579 projphidlist.append(projphid)
580 projects = self.phabricator.project.search(limit=100, constraints=({'phids': projphidlist}))
581 print("Adding additional project: %s" % (projects.data[0]['fields']['name']))
582 self.all_projects[projphid] = projects.data[0]
583
584 diffid = int(rev['diffs'][0])
585 diff = self.phabricator.differential.getrawdiff(diffID=str(diffid))
586 self.revisions[id] = Revision(rev, self.all_projects, revs, diff.response)
587 users.add(rev["authorPHID"])
588 users.update(rev["ccs"])
589 users.update(rev["reviewers"])
590 print(" || Rev doesn't exist--creating")
591
592 self.retrieve_all_users(users)
365 593
594 def ensure_project_phids(self):
595 if len(self.projects) == 1:
596 projects = self.phabricator.project.search(limit=100, constraints=({'isMilestone': False, 'name': self.projects[0]}))
597 else:
598 projects = self.phabricator.project.search(limit=100, constraints=({'isMilestone': False}))
599 self.all_projects = {}
600 self.project_phids = []
601 # add base project phids
602 for project in projects.data:
603 if project['fields']["color"]['key'] != "disabled" and \
604 project['phid'] not in self.project_phids and \
605 (project['fields']['slug'] in self.projects or project['fields']['name'] in self.projects):
606 print("Adding %s" % (project['fields']['slug']))
607 self.project_phids.append(project['phid'])
608 self.all_projects[project['phid']] = project
366 try: 609 try:
367 for p in self.projects: 610 subprojects = self.phabricator.project.search(limit=100, constraints=({'isMilestone': False, 'ancestors': self.project_phids}))
368 if p not in project_map: 611 for subproject in subprojects.data:
369 print("%sProject `%s` doesn't seem to exist%s" % 612 if subproject['fields']["color"]['key'] != "disabled" and subproject['phid'] not in self.project_phids:
370 (Colors.FAIL, p, Colors.ENDC)) 613 print("Adding %s" % (subproject['fields']['slug']))
371 raise 614 self.project_phids.append(subproject['phid'])
372 self.project_phids.append(project_map[p]) 615 self.all_projects[subproject['phid']] = subproject
373 except Exception: 616 except:
374 self.die("Failed to look up projects in Phabricator") 617 pass
618
619 self.used_projects = self.all_projects
620
621 # print("Evaluating subproject list %s" % (subprojects.data))
622 # for project in self.all_projects:
623 # print("SLUG Evaluating %s" % (project["fields"]["slug"]))
624 # if project["fields"]["slug"] in self.projects:
625 # self.project_phids.append(project["phid"])
626 # if project["fields"]["parent"]:
627 # print("PARENT Evaluating %s" % (project["fields"]["parent"]["name"]))
628 # for project["fields"]["parent"]["name"] in self.projects:
629 # self.project_phids.append(project["phid"])
630
631 print("FOUND %s" % (self.project_phids))
375 632
376 def setup_login_certificate(self): 633 def setup_login_certificate(self):
377 token = input("""LOGIN TO PHABRICATOR 634 token = input("""LOGIN TO PHABRICATOR
@@ -470,6 +727,8 @@ def options():
470 '--close-tasks', help="Close phabricator tasks", action='store_true') 727 '--close-tasks', help="Close phabricator tasks", action='store_true')
471 parser.add_argument('--project', help="phab project name", dest="projects", 728 parser.add_argument('--project', help="phab project name", dest="projects",
472 required=True, action="append") 729 required=True, action="append")
730 parser.add_argument('--callsign', help="phab project callsign", dest="callsigns",
731 required=True, action="append")
473 parser.add_argument('--target-project', metavar="USERNAME/PROJECT", 732 parser.add_argument('--target-project', metavar="USERNAME/PROJECT",
474 help="project name for gitlab, like \ 733 help="project name for gitlab, like \
475 'username/project'. If not provided, \ 734 'username/project'. If not provided, \
@@ -477,6 +736,9 @@ def options():
477 parser.add_argument('--start-at', 736 parser.add_argument('--start-at',
478 help="The ID of the first task to import", 737 help="The ID of the first task to import",
479 type=int) 738 type=int)
739 parser.add_argument('--rev-start-at',
740 help="The ID of the first revision to import",
741 type=int)
480 return parser.parse_args() 742 return parser.parse_args()
481 743
482 744
@@ -495,8 +757,8 @@ def check_if_target_project_exists(target):
495def main(): 757def main():
496 args = options() 758 args = options()
497 759
498 target = PhabGitLab("https://gitlab.freedesktop.org/", 760 target = PhabGitLab("https://gitlab-prototype.s-opensource.org/",
499 "https://cgit.freedesktop.org/", 761 "https://git.enlightenment.org/",
500 args.token, args.projects[0], 762 args.token, args.projects[0],
501 args.target_project, 763 args.target_project,
502 args.automate, args.close_tasks) 764 args.automate, args.close_tasks)
@@ -511,7 +773,10 @@ def main():
511 phab = Phab(args, target) 773 phab = Phab(args, target)
512 774
513 if phab.tasks: 775 if phab.tasks:
514 target.import_from_phab(phab, args.start_at) 776 target.import_tasks_from_phab(phab, args.start_at)
777
778 if phab.revisions:
779 target.import_revisions_from_phab(phab, args.rev_start_at)
515 780
516 781
517if __name__ == '__main__': 782if __name__ == '__main__':
diff --git a/bztogl/template.py b/bztogl/template.py
index 46bbf85..0b53c84 100644
--- a/bztogl/template.py
+++ b/bztogl/template.py
@@ -9,7 +9,7 @@ from . import bt
9DESC_TEMPLATE = """## Submitted by {submitter} \n\ 9DESC_TEMPLATE = """## Submitted by {submitter} \n\
10{assigned_to} 10{assigned_to}
11**[Link to original bug (#{id})]\ 11**[Link to original bug (#{id})]\
12({link_url}{id})** \n\ 12({link_url})** \n\
13## Description 13## Description
14{body} 14{body}
15 15
@@ -91,7 +91,9 @@ def render_issue_description(
91 importing_address = "{}/show_bug.cgi?id=".format(instance_base) 91 importing_address = "{}/show_bug.cgi?id=".format(instance_base)
92 92
93 assigned_to = "" 93 assigned_to = ""
94 assignee = user_cache[bug.assigned_to] 94 assignee = None
95 if bug.assigned_to:
96 assignee = user_cache[bug.assigned_to]
95 if assignee is not None: 97 if assignee is not None:
96 assigned_to = "Assigned to **{}** \n".format(assignee.display_name()) 98 assigned_to = "Assigned to **{}** \n".format(assignee.display_name())
97 99
@@ -142,10 +144,12 @@ def render_issue_description(
142 if bug.version and bug.version not in ('master', 'unspecified'): 144 if bug.version and bug.version not in ('master', 'unspecified'):
143 body += '\n\nVersion: {}'.format(bug.version) 145 body += '\n\nVersion: {}'.format(bug.version)
144 146
145 try: 147 submitter = 'an unknown user'
146 submitter = user_cache[bug.creator].display_name() 148 if bug.creator in user_cache:
147 except AttributeError: 149 try:
148 submitter = 'an unknown user' 150 submitter = user_cache[bug.creator].display_name()
151 except AttributeError:
152 pass
149 153
150 return DESC_TEMPLATE.format( 154 return DESC_TEMPLATE.format(
151 link_url=importing_address, submitter=submitter, 155 link_url=importing_address, submitter=submitter,