Page Menu
Home
c4science
Search
Configure Global Search
Log In
Files
F98213689
DifferentialRevisionViewController.php
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Subscribers
None
File Metadata
Details
File Info
Storage
Attached
Created
Sat, Jan 11, 03:06
Size
31 KB
Mime Type
text/x-php
Expires
Mon, Jan 13, 03:06 (2 d)
Engine
blob
Format
Raw Data
Handle
23532628
Attached To
rPH Phabricator
DifferentialRevisionViewController.php
View Options
<?php
final
class
DifferentialRevisionViewController
extends
DifferentialController
{
private
$revisionID
;
public
function
shouldAllowPublic
()
{
return
true
;
}
public
function
handleRequest
(
AphrontRequest
$request
)
{
$viewer
=
$this
->
getViewer
();
$this
->
revisionID
=
$request
->
getURIData
(
'id'
);
$viewer_is_anonymous
=
!
$viewer
->
isLoggedIn
();
$revision
=
id
(
new
DifferentialRevisionQuery
())
->
withIDs
(
array
(
$this
->
revisionID
))
->
setViewer
(
$viewer
)
->
needRelationships
(
true
)
->
needReviewerStatus
(
true
)
->
needReviewerAuthority
(
true
)
->
executeOne
();
if
(!
$revision
)
{
return
new
Aphront404Response
();
}
$diffs
=
id
(
new
DifferentialDiffQuery
())
->
setViewer
(
$viewer
)
->
withRevisionIDs
(
array
(
$this
->
revisionID
))
->
execute
();
$diffs
=
array_reverse
(
$diffs
,
$preserve_keys
=
true
);
if
(!
$diffs
)
{
throw
new
Exception
(
pht
(
'This revision has no diffs. Something has gone quite wrong.'
));
}
$revision
->
attachActiveDiff
(
last
(
$diffs
));
$diff_vs
=
$request
->
getInt
(
'vs'
);
$target_id
=
$request
->
getInt
(
'id'
);
$target
=
idx
(
$diffs
,
$target_id
,
end
(
$diffs
));
$target_manual
=
$target
;
if
(!
$target_id
)
{
foreach
(
$diffs
as
$diff
)
{
if
(
$diff
->
getCreationMethod
()
!=
'commit'
)
{
$target_manual
=
$diff
;
}
}
}
if
(
empty
(
$diffs
[
$diff_vs
]))
{
$diff_vs
=
null
;
}
$repository
=
null
;
$repository_phid
=
$target
->
getRepositoryPHID
();
if
(
$repository_phid
)
{
if
(
$repository_phid
==
$revision
->
getRepositoryPHID
())
{
$repository
=
$revision
->
getRepository
();
}
else
{
$repository
=
id
(
new
PhabricatorRepositoryQuery
())
->
setViewer
(
$viewer
)
->
withPHIDs
(
array
(
$repository_phid
))
->
executeOne
();
}
}
list
(
$changesets
,
$vs_map
,
$vs_changesets
,
$rendering_references
)
=
$this
->
loadChangesetsAndVsMap
(
$target
,
idx
(
$diffs
,
$diff_vs
),
$repository
);
if
(
$request
->
getExists
(
'download'
))
{
return
$this
->
buildRawDiffResponse
(
$revision
,
$changesets
,
$vs_changesets
,
$vs_map
,
$repository
);
}
$map
=
$vs_map
;
if
(!
$map
)
{
$map
=
array_fill_keys
(
array_keys
(
$changesets
),
0
);
}
$old_ids
=
array
();
$new_ids
=
array
();
foreach
(
$map
as
$id
=>
$vs
)
{
if
(
$vs
<=
0
)
{
$old_ids
[]
=
$id
;
$new_ids
[]
=
$id
;
}
else
{
$new_ids
[]
=
$id
;
$new_ids
[]
=
$vs
;
}
}
$this
->
loadDiffProperties
(
$diffs
);
$props
=
$target_manual
->
getDiffProperties
();
$object_phids
=
array_merge
(
$revision
->
getReviewers
(),
$revision
->
getCCPHIDs
(),
$revision
->
loadCommitPHIDs
(),
array
(
$revision
->
getAuthorPHID
(),
$viewer
->
getPHID
(),
));
foreach
(
$revision
->
getAttached
()
as
$type
=>
$phids
)
{
foreach
(
$phids
as
$phid
=>
$info
)
{
$object_phids
[]
=
$phid
;
}
}
$field_list
=
PhabricatorCustomField
::
getObjectFields
(
$revision
,
PhabricatorCustomField
::
ROLE_VIEW
);
$field_list
->
setViewer
(
$viewer
);
$field_list
->
readFieldsFromStorage
(
$revision
);
$warning_handle_map
=
array
();
foreach
(
$field_list
->
getFields
()
as
$key
=>
$field
)
{
$req
=
$field
->
getRequiredHandlePHIDsForRevisionHeaderWarnings
();
foreach
(
$req
as
$phid
)
{
$warning_handle_map
[
$key
][]
=
$phid
;
$object_phids
[]
=
$phid
;
}
}
$handles
=
$this
->
loadViewerHandles
(
$object_phids
);
$request_uri
=
$request
->
getRequestURI
();
$limit
=
100
;
$large
=
$request
->
getStr
(
'large'
);
if
(
count
(
$changesets
)
>
$limit
&&
!
$large
)
{
$count
=
count
(
$changesets
);
$warning
=
new
PHUIInfoView
();
$warning
->
setTitle
(
pht
(
'Very Large Diff'
));
$warning
->
setSeverity
(
PHUIInfoView
::
SEVERITY_WARNING
);
$warning
->
appendChild
(
hsprintf
(
'%s <strong>%s</strong>'
,
pht
(
'This diff is very large and affects %s files. '
.
'You may load each file individually or '
,
new
PhutilNumber
(
$count
)),
phutil_tag
(
'a'
,
array
(
'class'
=>
'button grey'
,
'href'
=>
$request_uri
->
alter
(
'large'
,
'true'
)
->
setFragment
(
'toc'
),
),
pht
(
'Show All Files Inline'
))));
$warning
=
$warning
->
render
();
$old
=
array_select_keys
(
$changesets
,
$old_ids
);
$new
=
array_select_keys
(
$changesets
,
$new_ids
);
$query
=
id
(
new
DifferentialInlineCommentQuery
())
->
setViewer
(
$viewer
)
->
needHidden
(
true
)
->
withRevisionPHIDs
(
array
(
$revision
->
getPHID
()));
$inlines
=
$query
->
execute
();
$inlines
=
$query
->
adjustInlinesForChangesets
(
$inlines
,
$old
,
$new
,
$revision
);
$visible_changesets
=
array
();
foreach
(
$inlines
as
$inline
)
{
$changeset_id
=
$inline
->
getChangesetID
();
if
(
isset
(
$changesets
[
$changeset_id
]))
{
$visible_changesets
[
$changeset_id
]
=
$changesets
[
$changeset_id
];
}
}
}
else
{
$warning
=
null
;
$visible_changesets
=
$changesets
;
}
$commit_hashes
=
mpull
(
$diffs
,
'getSourceControlBaseRevision'
);
$local_commits
=
idx
(
$props
,
'local:commits'
,
array
());
foreach
(
$local_commits
as
$local_commit
)
{
$commit_hashes
[]
=
idx
(
$local_commit
,
'tree'
);
$commit_hashes
[]
=
idx
(
$local_commit
,
'local'
);
}
$commit_hashes
=
array_unique
(
array_filter
(
$commit_hashes
));
if
(
$commit_hashes
)
{
$commits_for_links
=
id
(
new
DiffusionCommitQuery
())
->
setViewer
(
$viewer
)
->
withIdentifiers
(
$commit_hashes
)
->
execute
();
$commits_for_links
=
mpull
(
$commits_for_links
,
null
,
'getCommitIdentifier'
);
}
else
{
$commits_for_links
=
array
();
}
$header
=
$this
->
buildHeader
(
$revision
);
$subheader
=
$this
->
buildSubheaderView
(
$revision
);
$details
=
$this
->
buildDetails
(
$revision
,
$field_list
);
$curtain
=
$this
->
buildCurtain
(
$revision
);
$whitespace
=
$request
->
getStr
(
'whitespace'
,
DifferentialChangesetParser
::
WHITESPACE_IGNORE_MOST
);
$repository
=
$revision
->
getRepository
();
if
(
$repository
)
{
$symbol_indexes
=
$this
->
buildSymbolIndexes
(
$repository
,
$visible_changesets
);
}
else
{
$symbol_indexes
=
array
();
}
$revision_warnings
=
$this
->
buildRevisionWarnings
(
$revision
,
$field_list
,
$warning_handle_map
,
$handles
);
$info_view
=
null
;
if
(
$revision_warnings
)
{
$info_view
=
id
(
new
PHUIInfoView
())
->
setSeverity
(
PHUIInfoView
::
SEVERITY_WARNING
)
->
setErrors
(
$revision_warnings
);
}
$detail_diffs
=
array_select_keys
(
$diffs
,
array
(
$diff_vs
,
$target
->
getID
()));
$detail_diffs
=
mpull
(
$detail_diffs
,
null
,
'getPHID'
);
$this
->
loadHarbormasterData
(
$detail_diffs
);
$diff_detail_box
=
$this
->
buildDiffDetailView
(
$detail_diffs
,
$revision
,
$field_list
);
$unit_box
=
$this
->
buildUnitMessagesView
(
$target
,
$revision
);
$timeline
=
$this
->
buildTransactions
(
$revision
,
$diff_vs
?
$diffs
[
$diff_vs
]
:
$target
,
$target
,
$old_ids
,
$new_ids
);
$timeline
->
setQuoteRef
(
$revision
->
getMonogram
());
$changeset_view
=
id
(
new
DifferentialChangesetListView
())
->
setChangesets
(
$changesets
)
->
setVisibleChangesets
(
$visible_changesets
)
->
setStandaloneURI
(
'/differential/changeset/'
)
->
setRawFileURIs
(
'/differential/changeset/?view=old'
,
'/differential/changeset/?view=new'
)
->
setUser
(
$viewer
)
->
setDiff
(
$target
)
->
setRenderingReferences
(
$rendering_references
)
->
setVsMap
(
$vs_map
)
->
setWhitespace
(
$whitespace
)
->
setSymbolIndexes
(
$symbol_indexes
)
->
setTitle
(
pht
(
'Diff %s'
,
$target
->
getID
()))
->
setBackground
(
PHUIObjectBoxView
::
BLUE_PROPERTY
);
if
(
$repository
)
{
$changeset_view
->
setRepository
(
$repository
);
}
if
(!
$viewer_is_anonymous
)
{
$changeset_view
->
setInlineCommentControllerURI
(
'/differential/comment/inline/edit/'
.
$revision
->
getID
().
'/'
);
}
$broken_diffs
=
$this
->
loadHistoryDiffStatus
(
$diffs
);
$history
=
id
(
new
DifferentialRevisionUpdateHistoryView
())
->
setUser
(
$viewer
)
->
setDiffs
(
$diffs
)
->
setDiffUnitStatuses
(
$broken_diffs
)
->
setSelectedVersusDiffID
(
$diff_vs
)
->
setSelectedDiffID
(
$target
->
getID
())
->
setSelectedWhitespace
(
$whitespace
)
->
setCommitsForLinks
(
$commits_for_links
);
$local_table
=
id
(
new
DifferentialLocalCommitsView
())
->
setUser
(
$viewer
)
->
setLocalCommits
(
idx
(
$props
,
'local:commits'
))
->
setCommitsForLinks
(
$commits_for_links
);
if
(
$repository
)
{
$other_revisions
=
$this
->
loadOtherRevisions
(
$changesets
,
$target
,
$repository
);
}
else
{
$other_revisions
=
array
();
}
$other_view
=
null
;
if
(
$other_revisions
)
{
$other_view
=
$this
->
renderOtherRevisions
(
$other_revisions
);
}
$toc_view
=
$this
->
buildTableOfContents
(
$changesets
,
$visible_changesets
,
$target
->
loadCoverageMap
(
$viewer
));
$tab_group
=
id
(
new
PHUITabGroupView
())
->
addTab
(
id
(
new
PHUITabView
())
->
setName
(
pht
(
'Files'
))
->
setKey
(
'files'
)
->
appendChild
(
$toc_view
))
->
addTab
(
id
(
new
PHUITabView
())
->
setName
(
pht
(
'History'
))
->
setKey
(
'history'
)
->
appendChild
(
$history
))
->
addTab
(
id
(
new
PHUITabView
())
->
setName
(
pht
(
'Commits'
))
->
setKey
(
'commits'
)
->
appendChild
(
$local_table
));
$stack_graph
=
id
(
new
DifferentialRevisionGraph
())
->
setViewer
(
$viewer
)
->
setSeedPHID
(
$revision
->
getPHID
())
->
setLoadEntireGraph
(
true
)
->
loadGraph
();
if
(!
$stack_graph
->
isEmpty
())
{
$stack_table
=
$stack_graph
->
newGraphTable
();
$parent_type
=
DifferentialRevisionDependsOnRevisionEdgeType
::
EDGECONST
;
$reachable
=
$stack_graph
->
getReachableObjects
(
$parent_type
);
foreach
(
$reachable
as
$key
=>
$reachable_revision
)
{
if
(
$reachable_revision
->
isClosed
())
{
unset
(
$reachable
[
$key
]);
}
}
if
(
$reachable
)
{
$stack_name
=
pht
(
'Stack (%s Open)'
,
phutil_count
(
$reachable
));
$stack_color
=
PHUIListItemView
::
STATUS_FAIL
;
}
else
{
$stack_name
=
pht
(
'Stack'
);
$stack_color
=
null
;
}
$tab_group
->
addTab
(
id
(
new
PHUITabView
())
->
setName
(
$stack_name
)
->
setKey
(
'stack'
)
->
setColor
(
$stack_color
)
->
appendChild
(
$stack_table
));
}
if
(
$other_view
)
{
$tab_group
->
addTab
(
id
(
new
PHUITabView
())
->
setName
(
pht
(
'Similar'
))
->
setKey
(
'similar'
)
->
appendChild
(
$other_view
));
}
$tab_view
=
id
(
new
PHUIObjectBoxView
())
->
setHeaderText
(
pht
(
'Revision Contents'
))
->
setBackground
(
PHUIObjectBoxView
::
BLUE_PROPERTY
)
->
addTabGroup
(
$tab_group
);
$signatures
=
DifferentialRequiredSignaturesField
::
loadForRevision
(
$revision
);
$missing_signatures
=
false
;
foreach
(
$signatures
as
$phid
=>
$signed
)
{
if
(!
$signed
)
{
$missing_signatures
=
true
;
}
}
$footer
=
array
();
$signature_message
=
null
;
if
(
$missing_signatures
)
{
$signature_message
=
id
(
new
PHUIInfoView
())
->
setTitle
(
pht
(
'Content Hidden'
))
->
appendChild
(
pht
(
'The content of this revision is hidden until the author has '
.
'signed all of the required legal agreements.'
));
}
else
{
$anchor
=
id
(
new
PhabricatorAnchorView
())
->
setAnchorName
(
'toc'
)
->
setNavigationMarker
(
true
);
$footer
[]
=
array
(
$anchor
,
$warning
,
$tab_view
,
$changeset_view
,
);
}
$comment_view
=
id
(
new
DifferentialRevisionEditEngine
())
->
setViewer
(
$viewer
)
->
buildEditEngineCommentView
(
$revision
);
$comment_view
->
setTransactionTimeline
(
$timeline
);
$review_warnings
=
array
();
foreach
(
$field_list
->
getFields
()
as
$field
)
{
$review_warnings
[]
=
$field
->
getWarningsForDetailView
();
}
$review_warnings
=
array_mergev
(
$review_warnings
);
if
(
$review_warnings
)
{
$warnings_view
=
id
(
new
PHUIInfoView
())
->
setSeverity
(
PHUIInfoView
::
SEVERITY_WARNING
)
->
setErrors
(
$review_warnings
);
$comment_view
->
setInfoView
(
$warnings_view
);
}
$footer
[]
=
$comment_view
;
$monogram
=
$revision
->
getMonogram
();
$operations_box
=
$this
->
buildOperationsBox
(
$revision
);
$crumbs
=
$this
->
buildApplicationCrumbs
();
$crumbs
->
addTextCrumb
(
$monogram
,
$revision
->
getURI
());
$crumbs
->
setBorder
(
true
);
$filetree_on
=
$viewer
->
compareUserSetting
(
PhabricatorShowFiletreeSetting
::
SETTINGKEY
,
PhabricatorShowFiletreeSetting
::
VALUE_ENABLE_FILETREE
);
$nav
=
null
;
if
(
$filetree_on
)
{
$collapsed_key
=
PhabricatorFiletreeVisibleSetting
::
SETTINGKEY
;
$collapsed_value
=
$viewer
->
getUserSetting
(
$collapsed_key
);
$nav
=
id
(
new
DifferentialChangesetFileTreeSideNavBuilder
())
->
setTitle
(
$monogram
)
->
setBaseURI
(
new
PhutilURI
(
$revision
->
getURI
()))
->
setCollapsed
((
bool
)
$collapsed_value
)
->
build
(
$changesets
);
}
Javelin
::
initBehavior
(
'differential-user-select'
);
Javelin
::
initBehavior
(
'differential-keyboard-navigation'
);
$view
=
id
(
new
PHUITwoColumnView
())
->
setHeader
(
$header
)
->
setSubheader
(
$subheader
)
->
setCurtain
(
$curtain
)
->
setMainColumn
(
array
(
$operations_box
,
$info_view
,
$details
,
$diff_detail_box
,
$unit_box
,
$timeline
,
$signature_message
,
))
->
setFooter
(
$footer
);
$page
=
$this
->
newPage
()
->
setTitle
(
$monogram
.
' '
.
$revision
->
getTitle
())
->
setCrumbs
(
$crumbs
)
->
setPageObjectPHIDs
(
array
(
$revision
->
getPHID
()))
->
appendChild
(
$view
);
if
(
$nav
)
{
$page
->
setNavigation
(
$nav
);
}
return
$page
;
}
private
function
buildHeader
(
DifferentialRevision
$revision
)
{
$view
=
id
(
new
PHUIHeaderView
())
->
setHeader
(
$revision
->
getTitle
(
$revision
))
->
setUser
(
$this
->
getViewer
())
->
setPolicyObject
(
$revision
)
->
setHeaderIcon
(
'fa-cog'
);
$status
=
$revision
->
getStatus
();
$status_name
=
DifferentialRevisionStatus
::
renderFullDescription
(
$status
);
$view
->
addProperty
(
PHUIHeaderView
::
PROPERTY_STATUS
,
$status_name
);
return
$view
;
}
private
function
buildSubheaderView
(
DifferentialRevision
$revision
)
{
$viewer
=
$this
->
getViewer
();
$author_phid
=
$revision
->
getAuthorPHID
();
$author
=
$viewer
->
renderHandle
(
$author_phid
)->
render
();
$date
=
phabricator_datetime
(
$revision
->
getDateCreated
(),
$viewer
);
$author
=
phutil_tag
(
'strong'
,
array
(),
$author
);
$handles
=
$viewer
->
loadHandles
(
array
(
$author_phid
));
$image_uri
=
$handles
[
$author_phid
]->
getImageURI
();
$image_href
=
$handles
[
$author_phid
]->
getURI
();
$content
=
pht
(
'Authored by %s on %s.'
,
$author
,
$date
);
return
id
(
new
PHUIHeadThingView
())
->
setImage
(
$image_uri
)
->
setImageHref
(
$image_href
)
->
setContent
(
$content
);
}
private
function
buildDetails
(
DifferentialRevision
$revision
,
$custom_fields
)
{
$viewer
=
$this
->
getViewer
();
$properties
=
id
(
new
PHUIPropertyListView
())
->
setUser
(
$viewer
);
if
(
$custom_fields
)
{
$custom_fields
->
appendFieldsToPropertyList
(
$revision
,
$viewer
,
$properties
);
}
$header
=
id
(
new
PHUIHeaderView
())
->
setHeader
(
pht
(
'Details'
));
return
id
(
new
PHUIObjectBoxView
())
->
setHeader
(
$header
)
->
setBackground
(
PHUIObjectBoxView
::
BLUE_PROPERTY
)
->
appendChild
(
$properties
);
}
private
function
buildCurtain
(
DifferentialRevision
$revision
)
{
$viewer
=
$this
->
getViewer
();
$revision_id
=
$revision
->
getID
();
$revision_phid
=
$revision
->
getPHID
();
$curtain
=
$this
->
newCurtainView
(
$revision
);
$can_edit
=
PhabricatorPolicyFilter
::
hasCapability
(
$viewer
,
$revision
,
PhabricatorPolicyCapability
::
CAN_EDIT
);
$curtain
->
addAction
(
id
(
new
PhabricatorActionView
())
->
setIcon
(
'fa-pencil'
)
->
setHref
(
"/differential/revision/edit/{$revision_id}/"
)
->
setName
(
pht
(
'Edit Revision'
))
->
setDisabled
(!
$can_edit
)
->
setWorkflow
(!
$can_edit
));
$curtain
->
addAction
(
id
(
new
PhabricatorActionView
())
->
setIcon
(
'fa-upload'
)
->
setHref
(
"/differential/revision/update/{$revision_id}/"
)
->
setName
(
pht
(
'Update Diff'
))
->
setDisabled
(!
$can_edit
)
->
setWorkflow
(!
$can_edit
));
$request_uri
=
$this
->
getRequest
()->
getRequestURI
();
$curtain
->
addAction
(
id
(
new
PhabricatorActionView
())
->
setIcon
(
'fa-download'
)
->
setName
(
pht
(
'Download Raw Diff'
))
->
setHref
(
$request_uri
->
alter
(
'download'
,
'true'
)));
$relationship_list
=
PhabricatorObjectRelationshipList
::
newForObject
(
$viewer
,
$revision
);
$revision_actions
=
array
(
DifferentialRevisionHasParentRelationship
::
RELATIONSHIPKEY
,
DifferentialRevisionHasChildRelationship
::
RELATIONSHIPKEY
,
);
$revision_submenu
=
$relationship_list
->
newActionSubmenu
(
$revision_actions
)
->
setName
(
pht
(
'Edit Related Revisions...'
))
->
setIcon
(
'fa-cog'
);
$curtain
->
addAction
(
$revision_submenu
);
$relationship_submenu
=
$relationship_list
->
newActionMenu
();
if
(
$relationship_submenu
)
{
$curtain
->
addAction
(
$relationship_submenu
);
}
return
$curtain
;
}
private
function
loadHistoryDiffStatus
(
array
$diffs
)
{
assert_instances_of
(
$diffs
,
'DifferentialDiff'
);
$diff_phids
=
mpull
(
$diffs
,
'getPHID'
);
$bad_unit_status
=
array
(
ArcanistUnitTestResult
::
RESULT_FAIL
,
ArcanistUnitTestResult
::
RESULT_BROKEN
,
);
$message
=
new
HarbormasterBuildUnitMessage
();
$target
=
new
HarbormasterBuildTarget
();
$build
=
new
HarbormasterBuild
();
$buildable
=
new
HarbormasterBuildable
();
$broken_diffs
=
queryfx_all
(
$message
->
establishConnection
(
'r'
),
'SELECT distinct a.buildablePHID
FROM %T m
JOIN %T t ON m.buildTargetPHID = t.phid
JOIN %T b ON t.buildPHID = b.phid
JOIN %T a ON b.buildablePHID = a.phid
WHERE a.buildablePHID IN (%Ls)
AND m.result in (%Ls)'
,
$message
->
getTableName
(),
$target
->
getTableName
(),
$build
->
getTableName
(),
$buildable
->
getTableName
(),
$diff_phids
,
$bad_unit_status
);
$unit_status
=
array
();
foreach
(
$broken_diffs
as
$broken
)
{
$phid
=
$broken
[
'buildablePHID'
];
$unit_status
[
$phid
]
=
DifferentialUnitStatus
::
UNIT_FAIL
;
}
return
$unit_status
;
}
private
function
loadChangesetsAndVsMap
(
DifferentialDiff
$target
,
DifferentialDiff
$diff_vs
=
null
,
PhabricatorRepository
$repository
=
null
)
{
$load_diffs
=
array
(
$target
);
if
(
$diff_vs
)
{
$load_diffs
[]
=
$diff_vs
;
}
$raw_changesets
=
id
(
new
DifferentialChangesetQuery
())
->
setViewer
(
$this
->
getRequest
()->
getUser
())
->
withDiffs
(
$load_diffs
)
->
execute
();
$changeset_groups
=
mgroup
(
$raw_changesets
,
'getDiffID'
);
$changesets
=
idx
(
$changeset_groups
,
$target
->
getID
(),
array
());
$changesets
=
mpull
(
$changesets
,
null
,
'getID'
);
$refs
=
array
();
$vs_map
=
array
();
$vs_changesets
=
array
();
if
(
$diff_vs
)
{
$vs_id
=
$diff_vs
->
getID
();
$vs_changesets_path_map
=
array
();
foreach
(
idx
(
$changeset_groups
,
$vs_id
,
array
())
as
$changeset
)
{
$path
=
$changeset
->
getAbsoluteRepositoryPath
(
$repository
,
$diff_vs
);
$vs_changesets_path_map
[
$path
]
=
$changeset
;
$vs_changesets
[
$changeset
->
getID
()]
=
$changeset
;
}
foreach
(
$changesets
as
$key
=>
$changeset
)
{
$path
=
$changeset
->
getAbsoluteRepositoryPath
(
$repository
,
$target
);
if
(
isset
(
$vs_changesets_path_map
[
$path
]))
{
$vs_map
[
$changeset
->
getID
()]
=
$vs_changesets_path_map
[
$path
]->
getID
();
$refs
[
$changeset
->
getID
()]
=
$changeset
->
getID
().
'/'
.
$vs_changesets_path_map
[
$path
]->
getID
();
unset
(
$vs_changesets_path_map
[
$path
]);
}
else
{
$refs
[
$changeset
->
getID
()]
=
$changeset
->
getID
();
}
}
foreach
(
$vs_changesets_path_map
as
$path
=>
$changeset
)
{
$changesets
[
$changeset
->
getID
()]
=
$changeset
;
$vs_map
[
$changeset
->
getID
()]
=
-
1
;
$refs
[
$changeset
->
getID
()]
=
$changeset
->
getID
().
'/-1'
;
}
}
else
{
foreach
(
$changesets
as
$changeset
)
{
$refs
[
$changeset
->
getID
()]
=
$changeset
->
getID
();
}
}
$changesets
=
msort
(
$changesets
,
'getSortKey'
);
return
array
(
$changesets
,
$vs_map
,
$vs_changesets
,
$refs
);
}
private
function
buildSymbolIndexes
(
PhabricatorRepository
$repository
,
array
$visible_changesets
)
{
assert_instances_of
(
$visible_changesets
,
'DifferentialChangeset'
);
$engine
=
PhabricatorSyntaxHighlighter
::
newEngine
();
$langs
=
$repository
->
getSymbolLanguages
();
$langs
=
nonempty
(
$langs
,
array
());
$sources
=
$repository
->
getSymbolSources
();
$sources
=
nonempty
(
$sources
,
array
());
$symbol_indexes
=
array
();
if
(
$langs
&&
$sources
)
{
$have_symbols
=
id
(
new
DiffusionSymbolQuery
())
->
existsSymbolsInRepository
(
$repository
->
getPHID
());
if
(!
$have_symbols
)
{
return
$symbol_indexes
;
}
}
$repository_phids
=
array_merge
(
array
(
$repository
->
getPHID
()),
$sources
);
$indexed_langs
=
array_fill_keys
(
$langs
,
true
);
foreach
(
$visible_changesets
as
$key
=>
$changeset
)
{
$lang
=
$engine
->
getLanguageFromFilename
(
$changeset
->
getFilename
());
if
(
empty
(
$indexed_langs
)
||
isset
(
$indexed_langs
[
$lang
]))
{
$symbol_indexes
[
$key
]
=
array
(
'lang'
=>
$lang
,
'repositories'
=>
$repository_phids
,
);
}
}
return
$symbol_indexes
;
}
private
function
loadOtherRevisions
(
array
$changesets
,
DifferentialDiff
$target
,
PhabricatorRepository
$repository
)
{
assert_instances_of
(
$changesets
,
'DifferentialChangeset'
);
$paths
=
array
();
foreach
(
$changesets
as
$changeset
)
{
$paths
[]
=
$changeset
->
getAbsoluteRepositoryPath
(
$repository
,
$target
);
}
if
(!
$paths
)
{
return
array
();
}
$path_map
=
id
(
new
DiffusionPathIDQuery
(
$paths
))->
loadPathIDs
();
if
(!
$path_map
)
{
return
array
();
}
$recent
=
(
PhabricatorTime
::
getNow
()
-
phutil_units
(
'30 days in seconds'
));
$query
=
id
(
new
DifferentialRevisionQuery
())
->
setViewer
(
$this
->
getRequest
()->
getUser
())
->
withStatus
(
DifferentialRevisionQuery
::
STATUS_OPEN
)
->
withUpdatedEpochBetween
(
$recent
,
null
)
->
setOrder
(
DifferentialRevisionQuery
::
ORDER_MODIFIED
)
->
setLimit
(
10
)
->
needFlags
(
true
)
->
needDrafts
(
true
)
->
needRelationships
(
true
);
foreach
(
$path_map
as
$path
=>
$path_id
)
{
$query
->
withPath
(
$repository
->
getID
(),
$path_id
);
}
$results
=
$query
->
execute
();
// Strip out *this* revision.
foreach
(
$results
as
$key
=>
$result
)
{
if
(
$result
->
getID
()
==
$this
->
revisionID
)
{
unset
(
$results
[
$key
]);
}
}
return
$results
;
}
private
function
renderOtherRevisions
(
array
$revisions
)
{
assert_instances_of
(
$revisions
,
'DifferentialRevision'
);
$viewer
=
$this
->
getViewer
();
$header
=
id
(
new
PHUIHeaderView
())
->
setHeader
(
pht
(
'Recent Similar Revisions'
));
$view
=
id
(
new
DifferentialRevisionListView
())
->
setRevisions
(
$revisions
)
->
setBackground
(
PHUIObjectBoxView
::
BLUE_PROPERTY
)
->
setNoBox
(
true
)
->
setUser
(
$viewer
);
$phids
=
$view
->
getRequiredHandlePHIDs
();
$handles
=
$this
->
loadViewerHandles
(
$phids
);
$view
->
setHandles
(
$handles
);
return
$view
;
}
/**
* Note this code is somewhat similar to the buildPatch method in
* @{class:DifferentialReviewRequestMail}.
*
* @return @{class:AphrontRedirectResponse}
*/
private
function
buildRawDiffResponse
(
DifferentialRevision
$revision
,
array
$changesets
,
array
$vs_changesets
,
array
$vs_map
,
PhabricatorRepository
$repository
=
null
)
{
assert_instances_of
(
$changesets
,
'DifferentialChangeset'
);
assert_instances_of
(
$vs_changesets
,
'DifferentialChangeset'
);
$viewer
=
$this
->
getViewer
();
id
(
new
DifferentialHunkQuery
())
->
setViewer
(
$viewer
)
->
withChangesets
(
$changesets
)
->
needAttachToChangesets
(
true
)
->
execute
();
$diff
=
new
DifferentialDiff
();
$diff
->
attachChangesets
(
$changesets
);
$raw_changes
=
$diff
->
buildChangesList
();
$changes
=
array
();
foreach
(
$raw_changes
as
$changedict
)
{
$changes
[]
=
ArcanistDiffChange
::
newFromDictionary
(
$changedict
);
}
$loader
=
id
(
new
PhabricatorFileBundleLoader
())
->
setViewer
(
$viewer
);
$bundle
=
ArcanistBundle
::
newFromChanges
(
$changes
);
$bundle
->
setLoadFileDataCallback
(
array
(
$loader
,
'loadFileData'
));
$vcs
=
$repository
?
$repository
->
getVersionControlSystem
()
:
null
;
switch
(
$vcs
)
{
case
PhabricatorRepositoryType
::
REPOSITORY_TYPE_GIT
:
case
PhabricatorRepositoryType
::
REPOSITORY_TYPE_MERCURIAL
:
$raw_diff
=
$bundle
->
toGitPatch
();
break
;
case
PhabricatorRepositoryType
::
REPOSITORY_TYPE_SVN
:
default
:
$raw_diff
=
$bundle
->
toUnifiedDiff
();
break
;
}
$request_uri
=
$this
->
getRequest
()->
getRequestURI
();
// this ends up being something like
// D123.diff
// or the verbose
// D123.vs123.id123.whitespaceignore-all.diff
// lame but nice to include these options
$file_name
=
ltrim
(
$request_uri
->
getPath
(),
'/'
).
'.'
;
foreach
(
$request_uri
->
getQueryParams
()
as
$key
=>
$value
)
{
if
(
$key
==
'download'
)
{
continue
;
}
$file_name
.=
$key
.
$value
.
'.'
;
}
$file_name
.=
'diff'
;
$file
=
PhabricatorFile
::
buildFromFileDataOrHash
(
$raw_diff
,
array
(
'name'
=>
$file_name
,
'ttl'
=>
(
60
*
60
*
24
),
'viewPolicy'
=>
PhabricatorPolicies
::
POLICY_NOONE
,
));
$unguarded
=
AphrontWriteGuard
::
beginScopedUnguardedWrites
();
$file
->
attachToObject
(
$revision
->
getPHID
());
unset
(
$unguarded
);
return
$file
->
getRedirectResponse
();
}
private
function
buildTransactions
(
DifferentialRevision
$revision
,
DifferentialDiff
$left_diff
,
DifferentialDiff
$right_diff
,
array
$old_ids
,
array
$new_ids
)
{
$timeline
=
$this
->
buildTransactionTimeline
(
$revision
,
new
DifferentialTransactionQuery
(),
$engine
=
null
,
array
(
'left'
=>
$left_diff
->
getID
(),
'right'
=>
$right_diff
->
getID
(),
'old'
=>
implode
(
','
,
$old_ids
),
'new'
=>
implode
(
','
,
$new_ids
),
));
return
$timeline
;
}
private
function
buildRevisionWarnings
(
DifferentialRevision
$revision
,
PhabricatorCustomFieldList
$field_list
,
array
$warning_handle_map
,
array
$handles
)
{
$warnings
=
array
();
foreach
(
$field_list
->
getFields
()
as
$key
=>
$field
)
{
$phids
=
idx
(
$warning_handle_map
,
$key
,
array
());
$field_handles
=
array_select_keys
(
$handles
,
$phids
);
$field_warnings
=
$field
->
getWarningsForRevisionHeader
(
$field_handles
);
foreach
(
$field_warnings
as
$warning
)
{
$warnings
[]
=
$warning
;
}
}
return
$warnings
;
}
private
function
buildDiffDetailView
(
array
$diffs
,
DifferentialRevision
$revision
,
PhabricatorCustomFieldList
$field_list
)
{
$viewer
=
$this
->
getViewer
();
$fields
=
array
();
foreach
(
$field_list
->
getFields
()
as
$field
)
{
if
(
$field
->
shouldAppearInDiffPropertyView
())
{
$fields
[]
=
$field
;
}
}
if
(!
$fields
)
{
return
null
;
}
$property_lists
=
array
();
foreach
(
$this
->
getDiffTabLabels
(
$diffs
)
as
$tab
)
{
list
(
$label
,
$diff
)
=
$tab
;
$property_lists
[]
=
array
(
$label
,
$this
->
buildDiffPropertyList
(
$diff
,
$revision
,
$fields
),
);
}
$tab_group
=
id
(
new
PHUITabGroupView
())
->
setHideSingleTab
(
true
);
foreach
(
$property_lists
as
$key
=>
$property_list
)
{
list
(
$tab_name
,
$list_view
)
=
$property_list
;
$tab
=
id
(
new
PHUITabView
())
->
setKey
(
$key
)
->
setName
(
$tab_name
)
->
appendChild
(
$list_view
);
$tab_group
->
addTab
(
$tab
);
$tab_group
->
selectTab
(
$key
);
}
return
id
(
new
PHUIObjectBoxView
())
->
setHeaderText
(
pht
(
'Diff Detail'
))
->
setBackground
(
PHUIObjectBoxView
::
BLUE_PROPERTY
)
->
setUser
(
$viewer
)
->
addTabGroup
(
$tab_group
);
}
private
function
buildDiffPropertyList
(
DifferentialDiff
$diff
,
DifferentialRevision
$revision
,
array
$fields
)
{
$viewer
=
$this
->
getViewer
();
$view
=
id
(
new
PHUIPropertyListView
())
->
setUser
(
$viewer
)
->
setObject
(
$diff
);
foreach
(
$fields
as
$field
)
{
$label
=
$field
->
renderDiffPropertyViewLabel
(
$diff
);
$value
=
$field
->
renderDiffPropertyViewValue
(
$diff
);
if
(
$value
!==
null
)
{
$view
->
addProperty
(
$label
,
$value
);
}
}
return
$view
;
}
private
function
buildOperationsBox
(
DifferentialRevision
$revision
)
{
$viewer
=
$this
->
getViewer
();
// Save a query if we can't possibly have pending operations.
$repository
=
$revision
->
getRepository
();
if
(!
$repository
||
!
$repository
->
canPerformAutomation
())
{
return
null
;
}
$operations
=
id
(
new
DrydockRepositoryOperationQuery
())
->
setViewer
(
$viewer
)
->
withObjectPHIDs
(
array
(
$revision
->
getPHID
()))
->
withIsDismissed
(
false
)
->
withOperationTypes
(
array
(
DrydockLandRepositoryOperation
::
OPCONST
,
))
->
execute
();
if
(!
$operations
)
{
return
null
;
}
$state_fail
=
DrydockRepositoryOperation
::
STATE_FAIL
;
// We're going to show the oldest operation which hasn't failed, or the
// most recent failure if they're all failures.
$operations
=
msort
(
$operations
,
'getID'
);
foreach
(
$operations
as
$operation
)
{
if
(
$operation
->
getOperationState
()
!=
$state_fail
)
{
break
;
}
}
// If we found a completed operation, don't render anything. We don't want
// to show an older error after the thing worked properly.
if
(
$operation
->
isDone
())
{
return
null
;
}
$box_view
=
id
(
new
PHUIObjectBoxView
())
->
setHeaderText
(
pht
(
'Active Operations'
))
->
setBackground
(
PHUIObjectBoxView
::
BLUE_PROPERTY
);
return
id
(
new
DrydockRepositoryOperationStatusView
())
->
setUser
(
$viewer
)
->
setBoxView
(
$box_view
)
->
setOperation
(
$operation
);
}
private
function
buildUnitMessagesView
(
$diff
,
DifferentialRevision
$revision
)
{
$viewer
=
$this
->
getViewer
();
if
(!
$diff
->
getBuildable
())
{
return
null
;
}
if
(!
$diff
->
getUnitMessages
())
{
return
null
;
}
$interesting_messages
=
array
();
foreach
(
$diff
->
getUnitMessages
()
as
$message
)
{
switch
(
$message
->
getResult
())
{
case
ArcanistUnitTestResult
::
RESULT_PASS
:
case
ArcanistUnitTestResult
::
RESULT_SKIP
:
break
;
default
:
$interesting_messages
[]
=
$message
;
break
;
}
}
if
(!
$interesting_messages
)
{
return
null
;
}
$excuse
=
null
;
if
(
$diff
->
hasDiffProperty
(
'arc:unit-excuse'
))
{
$excuse
=
$diff
->
getProperty
(
'arc:unit-excuse'
);
}
return
id
(
new
HarbormasterUnitSummaryView
())
->
setUser
(
$viewer
)
->
setExcuse
(
$excuse
)
->
setBuildable
(
$diff
->
getBuildable
())
->
setUnitMessages
(
$diff
->
getUnitMessages
())
->
setLimit
(
5
)
->
setShowViewAll
(
true
);
}
}
Event Timeline
Log In to Comment