///| Conversion functions between GitHub API types and bit hub types
///|
/// Describes what changed between a local Issue and a GitHub GhIssue
pub struct SyncDiff {
title_changed : Bool
body_changed : Bool
state_changed : Bool
labels_changed : Bool
assignees_changed : Bool
has_changes : Bool
}
///|
/// Convert a GitHub API issue to a local Issue
pub fn gh_issue_to_issue(gh : GhIssue, existing_id? : String = "") -> Issue {
let created_at = parse_iso8601_to_unix(gh.created_at)
let updated_at = parse_iso8601_to_unix(gh.updated_at)
let author = gh.user
let state : IssueState = if gh.state == "closed" {
IssueState::Closed
} else {
IssueState::Open
}
let id = if existing_id != "" {
existing_id
} else {
generate_entity_id("issue", author, created_at, gh.title + "\n" + gh.body)
}
Issue::new(
id,
gh.title,
gh.body,
author,
created_at,
updated_at,
state,
labels=gh.labels,
assignees=gh.assignees,
)
}
///|
/// Compare a local Issue with a GitHub GhIssue and return a SyncDiff
pub fn issue_diff_for_github(
current : Issue,
_link : SyncLink,
gh : GhIssue,
) -> SyncDiff {
let gh_state : IssueState = if gh.state == "closed" {
IssueState::Closed
} else {
IssueState::Open
}
let title_changed = current.title != gh.title
let body_changed = current.body != gh.body
let state_changed = current.state != gh_state
let labels_changed = !string_arrays_equal(current.labels, gh.labels)
let assignees_changed = !string_arrays_equal(current.assignees, gh.assignees)
let has_changes = title_changed ||
body_changed ||
state_changed ||
labels_changed ||
assignees_changed
{
title_changed,
body_changed,
state_changed,
labels_changed,
assignees_changed,
has_changes,
}
}
///|
/// Convert a GitHub API pull request to a local PullRequest
pub fn gh_pr_to_pull_request(
gh : GhPullRequest,
existing_id? : String = "",
) -> PullRequest {
let created_at = parse_iso8601_to_unix(gh.created_at)
let updated_at = parse_iso8601_to_unix(gh.updated_at)
let state = match gh.state {
"merged" => PrState::Merged
"closed" => PrState::Closed
_ => PrState::Open
}
let id = if existing_id != "" {
existing_id
} else {
generate_entity_id("pr", gh.user, created_at, gh.title + "\n" + gh.body)
}
let source_branch = "refs/heads/" + gh.head_ref
let target_branch = "refs/heads/" + gh.base_ref
let source_repo : String? = if gh.head_repo.length() > 0 {
Some(gh.head_repo)
} else {
None
}
PullRequest::new(
id,
gh.title,
gh.body,
source_branch,
@bit.ObjectId::zero(),
target_branch,
@bit.ObjectId::zero(),
gh.user,
created_at,
updated_at,
state,
gh.labels,
source_repo~,
source_ref=Some(source_branch),
)
}
///|
/// Compare a local PullRequest with a GitHub GhPullRequest and return a SyncDiff
pub fn pr_diff_for_github(
current : PullRequest,
_link : SyncLink,
gh : GhPullRequest,
) -> SyncDiff {
let gh_state : PrState = match gh.state {
"merged" => PrState::Merged
"closed" => PrState::Closed
_ => PrState::Open
}
let title_changed = current.title != gh.title
let body_changed = current.body != gh.body
let state_changed = current.state != gh_state
let labels_changed = !string_arrays_equal(current.labels, gh.labels)
let has_changes = title_changed ||
body_changed ||
state_changed ||
labels_changed
{
title_changed,
body_changed,
state_changed,
labels_changed,
assignees_changed: false,
has_changes,
}
}
///|
fn string_arrays_equal(a : Array[String], b : Array[String]) -> Bool {
if a.length() != b.length() {
return false
}
let sorted_a = a.copy()
let sorted_b = b.copy()
sorted_a.sort_by(fn(x, y) { x.compare(y) })
sorted_b.sort_by(fn(x, y) { x.compare(y) })
for i = 0; i < sorted_a.length(); i = i + 1 {
if sorted_a[i] != sorted_b[i] {
return false
}
}
true
}