Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F2893393
PhabricatorRepository.php
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Award Token
Flag For Later
Advanced/Developer...
View Handle
View Hovercard
Size
27 KB
Referenced Files
None
Subscribers
None
PhabricatorRepository.php
View Options
<?php
/**
* @task uri Repository URI Management
*/
final
class
PhabricatorRepository
extends
PhabricatorRepositoryDAO
implements
PhabricatorPolicyInterface
,
PhabricatorFlaggableInterface
,
PhabricatorMarkupInterface
{
/**
* Shortest hash we'll recognize in raw "a829f32" form.
*/
const
MINIMUM_UNQUALIFIED_HASH
=
7
;
/**
* Shortest hash we'll recognize in qualified "rXab7ef2f8" form.
*/
const
MINIMUM_QUALIFIED_HASH
=
5
;
const
TABLE_PATH
=
'repository_path'
;
const
TABLE_PATHCHANGE
=
'repository_pathchange'
;
const
TABLE_FILESYSTEM
=
'repository_filesystem'
;
const
TABLE_SUMMARY
=
'repository_summary'
;
const
TABLE_BADCOMMIT
=
'repository_badcommit'
;
const
TABLE_LINTMESSAGE
=
'repository_lintmessage'
;
const
SERVE_OFF
=
'off'
;
const
SERVE_READONLY
=
'readonly'
;
const
SERVE_READWRITE
=
'readwrite'
;
protected
$name
;
protected
$callsign
;
protected
$uuid
;
protected
$viewPolicy
;
protected
$editPolicy
;
protected
$pushPolicy
;
protected
$versionControlSystem
;
protected
$details
=
array
(
)
;
protected
$credentialPHID
;
private
$commitCount
=
self
::
ATTACHABLE
;
private
$mostRecentCommit
=
self
::
ATTACHABLE
;
public
static
function
initializeNewRepository
(
PhabricatorUser
$actor
)
{
$app
=
id
(
new
PhabricatorApplicationQuery
(
)
)
->
setViewer
(
$actor
)
->
withClasses
(
array
(
'PhabricatorApplicationDiffusion'
)
)
->
executeOne
(
)
;
$view_policy
=
$app
->
getPolicy
(
DiffusionCapabilityDefaultView
::
CAPABILITY
)
;
$edit_policy
=
$app
->
getPolicy
(
DiffusionCapabilityDefaultEdit
::
CAPABILITY
)
;
$push_policy
=
$app
->
getPolicy
(
DiffusionCapabilityDefaultPush
::
CAPABILITY
)
;
return
id
(
new
PhabricatorRepository
(
)
)
->
setViewPolicy
(
$view_policy
)
->
setEditPolicy
(
$edit_policy
)
->
setPushPolicy
(
$push_policy
)
;
}
public
function
getConfiguration
(
)
{
return
array
(
self
::
CONFIG_AUX_PHID
=>
true
,
self
::
CONFIG_SERIALIZATION
=>
array
(
'details'
=>
self
::
SERIALIZATION_JSON
,
)
,
)
+
parent
::
getConfiguration
(
)
;
}
public
function
generatePHID
(
)
{
return
PhabricatorPHID
::
generateNewPHID
(
PhabricatorRepositoryPHIDTypeRepository
::
TYPECONST
)
;
}
public
function
toDictionary
(
)
{
return
array
(
'name'
=>
$this
->
getName
(
)
,
'phid'
=>
$this
->
getPHID
(
)
,
'callsign'
=>
$this
->
getCallsign
(
)
,
'vcs'
=>
$this
->
getVersionControlSystem
(
)
,
'uri'
=>
PhabricatorEnv
::
getProductionURI
(
$this
->
getURI
(
)
)
,
'remoteURI'
=>
(string)
$this
->
getPublicRemoteURI
(
)
,
'tracking'
=>
$this
->
getDetail
(
'tracking-enabled'
)
,
'description'
=>
$this
->
getDetail
(
'description'
)
,
)
;
}
public
function
getDetail
(
$key
,
$default
=
null
)
{
return
idx
(
$this
->
details
,
$key
,
$default
)
;
}
public
function
getHumanReadableDetail
(
$key
,
$default
=
null
)
{
$value
=
$this
->
getDetail
(
$key
,
$default
)
;
switch
(
$key
)
{
case
'branch-filter'
:
case
'close-commits-filter'
:
$value
=
array_keys
(
$value
)
;
$value
=
implode
(
', '
,
$value
)
;
break
;
}
return
$value
;
}
public
function
setDetail
(
$key
,
$value
)
{
$this
->
details
[
$key
]
=
$value
;
return
$this
;
}
public
function
attachCommitCount
(
$count
)
{
$this
->
commitCount
=
$count
;
return
$this
;
}
public
function
getCommitCount
(
)
{
return
$this
->
assertAttached
(
$this
->
commitCount
)
;
}
public
function
attachMostRecentCommit
(
PhabricatorRepositoryCommit
$commit
=
null
)
{
$this
->
mostRecentCommit
=
$commit
;
return
$this
;
}
public
function
getMostRecentCommit
(
)
{
return
$this
->
assertAttached
(
$this
->
mostRecentCommit
)
;
}
public
function
getDiffusionBrowseURIForPath
(
PhabricatorUser
$user
,
$path
,
$line
=
null
,
$branch
=
null
)
{
$drequest
=
DiffusionRequest
::
newFromDictionary
(
array
(
'user'
=>
$user
,
'repository'
=>
$this
,
'path'
=>
$path
,
'branch'
=>
$branch
,
)
)
;
return
$drequest
->
generateURI
(
array
(
'action'
=>
'browse'
,
'line'
=>
$line
,
)
)
;
}
public
function
getLocalPath
(
)
{
return
$this
->
getDetail
(
'local-path'
)
;
}
public
function
getSubversionBaseURI
(
$commit
=
null
)
{
$subpath
=
$this
->
getDetail
(
'svn-subpath'
)
;
if
(
!
strlen
(
$subpath
)
)
{
$subpath
=
null
;
}
return
$this
->
getSubversionPathURI
(
$subpath
,
$commit
)
;
}
public
function
getSubversionPathURI
(
$path
=
null
,
$commit
=
null
)
{
$vcs
=
$this
->
getVersionControlSystem
(
)
;
if
(
$vcs
!=
PhabricatorRepositoryType
::
REPOSITORY_TYPE_SVN
)
{
throw
new
Exception
(
"Not a subversion repository!"
)
;
}
if
(
$this
->
isHosted
(
)
)
{
$uri
=
'file://'
.
$this
->
getLocalPath
(
)
;
}
else
{
$uri
=
$this
->
getDetail
(
'remote-uri'
)
;
}
$uri
=
rtrim
(
$uri
,
'/'
)
;
if
(
strlen
(
$path
)
)
{
$path
=
rawurlencode
(
$path
)
;
$path
=
str_replace
(
'%2F'
,
'/'
,
$path
)
;
$uri
=
$uri
.
'/'
.
ltrim
(
$path
,
'/'
)
;
}
if
(
$path
!==
null
||
$commit
!==
null
)
{
$uri
.=
'@'
;
}
if
(
$commit
!==
null
)
{
$uri
.=
$commit
;
}
return
$uri
;
}
/* -( Remote Command Execution )------------------------------------------- */
public
function
execRemoteCommand
(
$pattern
/* , $arg, ... */
)
{
$args
=
func_get_args
(
)
;
return
$this
->
newRemoteCommandFuture
(
$args
)
->
resolve
(
)
;
}
public
function
execxRemoteCommand
(
$pattern
/* , $arg, ... */
)
{
$args
=
func_get_args
(
)
;
return
$this
->
newRemoteCommandFuture
(
$args
)
->
resolvex
(
)
;
}
public
function
getRemoteCommandFuture
(
$pattern
/* , $arg, ... */
)
{
$args
=
func_get_args
(
)
;
return
$this
->
newRemoteCommandFuture
(
$args
)
;
}
public
function
passthruRemoteCommand
(
$pattern
/* , $arg, ... */
)
{
$args
=
func_get_args
(
)
;
return
$this
->
newRemoteCommandPassthru
(
$args
)
->
execute
(
)
;
}
private
function
newRemoteCommandFuture
(
array
$argv
)
{
$argv
=
$this
->
formatRemoteCommand
(
$argv
)
;
$future
=
newv
(
'ExecFuture'
,
$argv
)
;
$future
->
setEnv
(
$this
->
getRemoteCommandEnvironment
(
)
)
;
return
$future
;
}
private
function
newRemoteCommandPassthru
(
array
$argv
)
{
$argv
=
$this
->
formatRemoteCommand
(
$argv
)
;
$passthru
=
newv
(
'PhutilExecPassthru'
,
$argv
)
;
$passthru
->
setEnv
(
$this
->
getRemoteCommandEnvironment
(
)
)
;
return
$passthru
;
}
/* -( Local Command Execution )-------------------------------------------- */
public
function
execLocalCommand
(
$pattern
/* , $arg, ... */
)
{
$args
=
func_get_args
(
)
;
return
$this
->
newLocalCommandFuture
(
$args
)
->
resolve
(
)
;
}
public
function
execxLocalCommand
(
$pattern
/* , $arg, ... */
)
{
$args
=
func_get_args
(
)
;
return
$this
->
newLocalCommandFuture
(
$args
)
->
resolvex
(
)
;
}
public
function
getLocalCommandFuture
(
$pattern
/* , $arg, ... */
)
{
$args
=
func_get_args
(
)
;
return
$this
->
newLocalCommandFuture
(
$args
)
;
}
public
function
passthruLocalCommand
(
$pattern
/* , $arg, ... */
)
{
$args
=
func_get_args
(
)
;
return
$this
->
newLocalCommandPassthru
(
$args
)
->
execute
(
)
;
}
private
function
newLocalCommandFuture
(
array
$argv
)
{
$this
->
assertLocalExists
(
)
;
$argv
=
$this
->
formatLocalCommand
(
$argv
)
;
$future
=
newv
(
'ExecFuture'
,
$argv
)
;
$future
->
setEnv
(
$this
->
getLocalCommandEnvironment
(
)
)
;
if
(
$this
->
usesLocalWorkingCopy
(
)
)
{
$future
->
setCWD
(
$this
->
getLocalPath
(
)
)
;
}
return
$future
;
}
private
function
newLocalCommandPassthru
(
array
$argv
)
{
$this
->
assertLocalExists
(
)
;
$argv
=
$this
->
formatLocalCommand
(
$argv
)
;
$future
=
newv
(
'PhutilExecPassthru'
,
$argv
)
;
$future
->
setEnv
(
$this
->
getLocalCommandEnvironment
(
)
)
;
if
(
$this
->
usesLocalWorkingCopy
(
)
)
{
$future
->
setCWD
(
$this
->
getLocalPath
(
)
)
;
}
return
$future
;
}
/* -( Command Infrastructure )--------------------------------------------- */
private
function
getSSHWrapper
(
)
{
$root
=
dirname
(
phutil_get_library_root
(
'phabricator'
)
)
;
return
$root
.
'/bin/ssh-connect'
;
}
private
function
getCommonCommandEnvironment
(
)
{
$env
=
array
(
// NOTE: Force the language to "C", which overrides locale settings.
// This makes stuff print in English instead of, e.g., French, so we can
// parse the output of some commands, error messages, etc.
'LANG'
=>
'C'
,
)
;
switch
(
$this
->
getVersionControlSystem
(
)
)
{
case
PhabricatorRepositoryType
::
REPOSITORY_TYPE_SVN
:
break
;
case
PhabricatorRepositoryType
::
REPOSITORY_TYPE_GIT
:
// NOTE: See T2965. Some time after Git 1.7.5.4, Git started fataling if
// it can not read $HOME. For many users, $HOME points at /root (this
// seems to be a default result of Apache setup). Instead, explicitly
// point $HOME at a readable, empty directory so that Git looks for the
// config file it's after, fails to locate it, and moves on. This is
// really silly, but seems like the least damaging approach to
// mitigating the issue.
$root
=
dirname
(
phutil_get_library_root
(
'phabricator'
)
)
;
$env
[
'HOME'
]
=
$root
.
'/support/empty/'
;
break
;
case
PhabricatorRepositoryType
::
REPOSITORY_TYPE_MERCURIAL
:
// NOTE: This overrides certain configuration, extensions, and settings
// which make Mercurial commands do random unusual things.
$env
[
'HGPLAIN'
]
=
1
;
break
;
default
:
throw
new
Exception
(
"Unrecognized version control system."
)
;
}
return
$env
;
}
private
function
getLocalCommandEnvironment
(
)
{
return
$this
->
getCommonCommandEnvironment
(
)
;
}
private
function
getRemoteCommandEnvironment
(
)
{
$env
=
$this
->
getCommonCommandEnvironment
(
)
;
if
(
$this
->
shouldUseSSH
(
)
)
{
// NOTE: This is read by `bin/ssh-connect`, and tells it which credentials
// to use.
$env
[
'PHABRICATOR_CREDENTIAL'
]
=
$this
->
getCredentialPHID
(
)
;
switch
(
$this
->
getVersionControlSystem
(
)
)
{
case
PhabricatorRepositoryType
::
REPOSITORY_TYPE_SVN
:
// Force SVN to use `bin/ssh-connect`.
$env
[
'SVN_SSH'
]
=
$this
->
getSSHWrapper
(
)
;
break
;
case
PhabricatorRepositoryType
::
REPOSITORY_TYPE_GIT
:
// Force Git to use `bin/ssh-connect`.
$env
[
'GIT_SSH'
]
=
$this
->
getSSHWrapper
(
)
;
break
;
case
PhabricatorRepositoryType
::
REPOSITORY_TYPE_MERCURIAL
:
// We force Mercurial through `bin/ssh-connect` too, but it uses a
// command-line flag instead of an environmental variable.
break
;
default
:
throw
new
Exception
(
"Unrecognized version control system."
)
;
}
}
return
$env
;
}
private
function
formatRemoteCommand
(
array
$args
)
{
$pattern
=
$args
[
0
]
;
$args
=
array_slice
(
$args
,
1
)
;
switch
(
$this
->
getVersionControlSystem
(
)
)
{
case
PhabricatorRepositoryType
::
REPOSITORY_TYPE_SVN
:
if
(
$this
->
shouldUseHTTP
(
)
||
$this
->
shouldUseSVNProtocol
(
)
)
{
$flags
=
array
(
)
;
$flag_args
=
array
(
)
;
$flags
[
]
=
'--non-interactive'
;
$flags
[
]
=
'--no-auth-cache'
;
if
(
$this
->
shouldUseHTTP
(
)
)
{
$flags
[
]
=
'--trust-server-cert'
;
}
$credential_phid
=
$this
->
getCredentialPHID
(
)
;
if
(
$credential_phid
)
{
$key
=
PassphrasePasswordKey
::
loadFromPHID
(
$credential_phid
,
PhabricatorUser
::
getOmnipotentUser
(
)
)
;
$flags
[
]
=
'--username %P'
;
$flags
[
]
=
'--password %P'
;
$flag_args
[
]
=
$key
->
getUsernameEnvelope
(
)
;
$flag_args
[
]
=
$key
->
getPasswordEnvelope
(
)
;
}
$flags
=
implode
(
' '
,
$flags
)
;
$pattern
=
"svn {$flags} {$pattern}"
;
$args
=
array_mergev
(
array
(
$flag_args
,
$args
)
)
;
}
else
{
$pattern
=
"svn --non-interactive {$pattern}"
;
}
break
;
case
PhabricatorRepositoryType
::
REPOSITORY_TYPE_GIT
:
$pattern
=
"git {$pattern}"
;
break
;
case
PhabricatorRepositoryType
::
REPOSITORY_TYPE_MERCURIAL
:
if
(
$this
->
shouldUseSSH
(
)
)
{
$pattern
=
"hg --config ui.ssh=%s {$pattern}"
;
array_unshift
(
$args
,
$this
->
getSSHWrapper
(
)
)
;
}
else
{
$pattern
=
"hg {$pattern}"
;
}
break
;
default
:
throw
new
Exception
(
"Unrecognized version control system."
)
;
}
array_unshift
(
$args
,
$pattern
)
;
return
$args
;
}
private
function
formatLocalCommand
(
array
$args
)
{
$pattern
=
$args
[
0
]
;
$args
=
array_slice
(
$args
,
1
)
;
switch
(
$this
->
getVersionControlSystem
(
)
)
{
case
PhabricatorRepositoryType
::
REPOSITORY_TYPE_SVN
:
$pattern
=
"svn --non-interactive {$pattern}"
;
break
;
case
PhabricatorRepositoryType
::
REPOSITORY_TYPE_GIT
:
$pattern
=
"git {$pattern}"
;
break
;
case
PhabricatorRepositoryType
::
REPOSITORY_TYPE_MERCURIAL
:
$pattern
=
"hg {$pattern}"
;
break
;
default
:
throw
new
Exception
(
"Unrecognized version control system."
)
;
}
array_unshift
(
$args
,
$pattern
)
;
return
$args
;
}
public
function
getSSHLogin
(
)
{
return
$this
->
getDetail
(
'ssh-login'
)
;
}
public
function
getURI
(
)
{
return
'/diffusion/'
.
$this
->
getCallsign
(
)
.
'/'
;
}
public
function
isTracked
(
)
{
return
$this
->
getDetail
(
'tracking-enabled'
,
false
)
;
}
public
function
getDefaultBranch
(
)
{
$default
=
$this
->
getDetail
(
'default-branch'
)
;
if
(
strlen
(
$default
)
)
{
return
$default
;
}
$default_branches
=
array
(
PhabricatorRepositoryType
::
REPOSITORY_TYPE_GIT
=>
'master'
,
PhabricatorRepositoryType
::
REPOSITORY_TYPE_MERCURIAL
=>
'default'
,
)
;
return
idx
(
$default_branches
,
$this
->
getVersionControlSystem
(
)
)
;
}
public
function
getDefaultArcanistBranch
(
)
{
return
coalesce
(
$this
->
getDefaultBranch
(
)
,
'svn'
)
;
}
private
function
isBranchInFilter
(
$branch
,
$filter_key
)
{
$vcs
=
$this
->
getVersionControlSystem
(
)
;
$is_git
=
(
$vcs
==
PhabricatorRepositoryType
::
REPOSITORY_TYPE_GIT
)
;
$use_filter
=
(
$is_git
)
;
if
(
$use_filter
)
{
$filter
=
$this
->
getDetail
(
$filter_key
,
array
(
)
)
;
if
(
$filter
&&
empty
(
$filter
[
$branch
]
)
)
{
return
false
;
}
}
// By default, all branches pass.
return
true
;
}
public
function
shouldTrackBranch
(
$branch
)
{
return
$this
->
isBranchInFilter
(
$branch
,
'branch-filter'
)
;
}
public
function
shouldAutocloseBranch
(
$branch
)
{
if
(
$this
->
isImporting
(
)
)
{
return
false
;
}
if
(
$this
->
getDetail
(
'disable-autoclose'
,
false
)
)
{
return
false
;
}
return
$this
->
isBranchInFilter
(
$branch
,
'close-commits-filter'
)
;
}
public
function
shouldAutocloseCommit
(
PhabricatorRepositoryCommit
$commit
,
PhabricatorRepositoryCommitData
$data
)
{
if
(
$this
->
getDetail
(
'disable-autoclose'
,
false
)
)
{
return
false
;
}
switch
(
$this
->
getVersionControlSystem
(
)
)
{
case
PhabricatorRepositoryType
::
REPOSITORY_TYPE_SVN
:
return
true
;
case
PhabricatorRepositoryType
::
REPOSITORY_TYPE_GIT
:
break
;
case
PhabricatorRepositoryType
::
REPOSITORY_TYPE_MERCURIAL
:
return
true
;
default
:
throw
new
Exception
(
"Unrecognized version control system."
)
;
}
$branches
=
$data
->
getCommitDetail
(
'seenOnBranches'
,
array
(
)
)
;
foreach
(
$branches
as
$branch
)
{
if
(
$this
->
shouldAutocloseBranch
(
$branch
)
)
{
return
true
;
}
}
return
false
;
}
public
function
formatCommitName
(
$commit_identifier
)
{
$vcs
=
$this
->
getVersionControlSystem
(
)
;
$type_git
=
PhabricatorRepositoryType
::
REPOSITORY_TYPE_GIT
;
$type_hg
=
PhabricatorRepositoryType
::
REPOSITORY_TYPE_MERCURIAL
;
$is_git
=
(
$vcs
==
$type_git
)
;
$is_hg
=
(
$vcs
==
$type_hg
)
;
if
(
$is_git
||
$is_hg
)
{
$short_identifier
=
substr
(
$commit_identifier
,
0
,
12
)
;
}
else
{
$short_identifier
=
$commit_identifier
;
}
return
'r'
.
$this
->
getCallsign
(
)
.
$short_identifier
;
}
public
function
isImporting
(
)
{
return
(bool)
$this
->
getDetail
(
'importing'
,
false
)
;
}
/* -( Repository URI Management )------------------------------------------ */
/**
* Get the remote URI for this repository.
*
* @return string
* @task uri
*/
public
function
getRemoteURI
(
)
{
return
(string)
$this
->
getRemoteURIObject
(
)
;
}
/**
* Get the remote URI for this repository, without authentication information.
*
* @return string Repository URI.
* @task uri
*/
public
function
getPublicRemoteURI
(
)
{
$uri
=
$this
->
getRemoteURIObject
(
)
;
// Make sure we don't leak anything if this repo is using HTTP Basic Auth
// with the credentials in the URI or something zany like that.
// If repository is not accessed over SSH we remove both username and
// password.
if
(
!
$this
->
shouldUseSSH
(
)
)
{
$uri
->
setUser
(
null
)
;
$uri
->
setPass
(
null
)
;
}
return
(string)
$uri
;
}
/**
* Get the protocol for the repository's remote.
*
* @return string Protocol, like "ssh" or "git".
* @task uri
*/
public
function
getRemoteProtocol
(
)
{
$uri
=
$this
->
getRemoteURIObject
(
)
;
if
(
$uri
instanceof
PhutilGitURI
)
{
return
'ssh'
;
}
else
{
return
$uri
->
getProtocol
(
)
;
}
}
/**
* Get a parsed object representation of the repository's remote URI. This
* may be a normal URI (returned as a @{class@libphutil:PhutilURI}) or a git
* URI (returned as a @{class@libphutil:PhutilGitURI}).
*
* @return wild A @{class@libphutil:PhutilURI} or
* @{class@libphutil:PhutilGitURI}.
* @task uri
*/
public
function
getRemoteURIObject
(
)
{
$raw_uri
=
$this
->
getDetail
(
'remote-uri'
)
;
if
(
!
$raw_uri
)
{
return
new
PhutilURI
(
''
)
;
}
if
(
!
strncmp
(
$raw_uri
,
'/'
,
1
)
)
{
return
new
PhutilURI
(
'file://'
.
$raw_uri
)
;
}
$uri
=
new
PhutilURI
(
$raw_uri
)
;
if
(
$uri
->
getProtocol
(
)
)
{
if
(
$this
->
isSSHProtocol
(
$uri
->
getProtocol
(
)
)
)
{
if
(
$this
->
getSSHLogin
(
)
)
{
$uri
->
setUser
(
$this
->
getSSHLogin
(
)
)
;
}
}
return
$uri
;
}
$uri
=
new
PhutilGitURI
(
$raw_uri
)
;
if
(
$uri
->
getDomain
(
)
)
{
if
(
$this
->
getSSHLogin
(
)
)
{
$uri
->
setUser
(
$this
->
getSSHLogin
(
)
)
;
}
return
$uri
;
}
throw
new
Exception
(
"Remote URI '{$raw_uri}' could not be parsed!"
)
;
}
/**
* Determine if we should connect to the remote using SSH flags and
* credentials.
*
* @return bool True to use the SSH protocol.
* @task uri
*/
private
function
shouldUseSSH
(
)
{
if
(
$this
->
isHosted
(
)
)
{
return
false
;
}
$protocol
=
$this
->
getRemoteProtocol
(
)
;
if
(
$this
->
isSSHProtocol
(
$protocol
)
)
{
$key
=
$this
->
getDetail
(
'ssh-key'
)
;
$keyfile
=
$this
->
getDetail
(
'ssh-keyfile'
)
;
if
(
$key
||
$keyfile
)
{
return
true
;
}
}
return
false
;
}
/**
* Determine if we should connect to the remote using HTTP flags and
* credentials.
*
* @return bool True to use the HTTP protocol.
* @task uri
*/
private
function
shouldUseHTTP
(
)
{
if
(
$this
->
isHosted
(
)
)
{
return
false
;
}
$protocol
=
$this
->
getRemoteProtocol
(
)
;
return
(
$protocol
==
'http'
||
$protocol
==
'https'
)
;
}
/**
* Determine if we should connect to the remote using SVN flags and
* credentials.
*
* @return bool True to use the SVN protocol.
* @task uri
*/
private
function
shouldUseSVNProtocol
(
)
{
if
(
$this
->
isHosted
(
)
)
{
return
false
;
}
$protocol
=
$this
->
getRemoteProtocol
(
)
;
return
(
$protocol
==
'svn'
)
;
}
/**
* Determine if a protocol is SSH or SSH-like.
*
* @param string A protocol string, like "http" or "ssh".
* @return bool True if the protocol is SSH-like.
* @task uri
*/
private
function
isSSHProtocol
(
$protocol
)
{
return
(
$protocol
==
'ssh'
||
$protocol
==
'svn+ssh'
)
;
}
public
function
delete
(
)
{
$this
->
openTransaction
(
)
;
$paths
=
id
(
new
PhabricatorOwnersPath
(
)
)
->
loadAllWhere
(
'repositoryPHID = %s'
,
$this
->
getPHID
(
)
)
;
foreach
(
$paths
as
$path
)
{
$path
->
delete
(
)
;
}
$projects
=
id
(
new
PhabricatorRepositoryArcanistProject
(
)
)
->
loadAllWhere
(
'repositoryID = %d'
,
$this
->
getID
(
)
)
;
foreach
(
$projects
as
$project
)
{
// note each project deletes its PhabricatorRepositorySymbols
$project
->
delete
(
)
;
}
$commits
=
id
(
new
PhabricatorRepositoryCommit
(
)
)
->
loadAllWhere
(
'repositoryID = %d'
,
$this
->
getID
(
)
)
;
foreach
(
$commits
as
$commit
)
{
// note PhabricatorRepositoryAuditRequests and
// PhabricatorRepositoryCommitData are deleted here too.
$commit
->
delete
(
)
;
}
$mirrors
=
id
(
new
PhabricatorRepositoryMirror
(
)
)
->
loadAllWhere
(
'repositoryPHID = %s'
,
$this
->
getPHID
(
)
)
;
foreach
(
$mirrors
as
$mirror
)
{
$mirror
->
delete
(
)
;
}
$conn_w
=
$this
->
establishConnection
(
'w'
)
;
queryfx
(
$conn_w
,
'DELETE FROM %T WHERE repositoryID = %d'
,
self
::
TABLE_FILESYSTEM
,
$this
->
getID
(
)
)
;
queryfx
(
$conn_w
,
'DELETE FROM %T WHERE repositoryID = %d'
,
self
::
TABLE_PATHCHANGE
,
$this
->
getID
(
)
)
;
queryfx
(
$conn_w
,
'DELETE FROM %T WHERE repositoryID = %d'
,
self
::
TABLE_SUMMARY
,
$this
->
getID
(
)
)
;
$result
=
parent
::
delete
(
)
;
$this
->
saveTransaction
(
)
;
return
$result
;
}
public
function
isGit
(
)
{
$vcs
=
$this
->
getVersionControlSystem
(
)
;
return
(
$vcs
==
PhabricatorRepositoryType
::
REPOSITORY_TYPE_GIT
)
;
}
public
function
isSVN
(
)
{
$vcs
=
$this
->
getVersionControlSystem
(
)
;
return
(
$vcs
==
PhabricatorRepositoryType
::
REPOSITORY_TYPE_SVN
)
;
}
public
function
isHg
(
)
{
$vcs
=
$this
->
getVersionControlSystem
(
)
;
return
(
$vcs
==
PhabricatorRepositoryType
::
REPOSITORY_TYPE_MERCURIAL
)
;
}
public
function
isHosted
(
)
{
return
(bool)
$this
->
getDetail
(
'hosting-enabled'
,
false
)
;
}
public
function
setHosted
(
$enabled
)
{
return
$this
->
setDetail
(
'hosting-enabled'
,
$enabled
)
;
}
public
function
getServeOverHTTP
(
)
{
if
(
$this
->
isSVN
(
)
)
{
return
self
::
SERVE_OFF
;
}
$serve
=
$this
->
getDetail
(
'serve-over-http'
,
self
::
SERVE_OFF
)
;
return
$this
->
normalizeServeConfigSetting
(
$serve
)
;
}
public
function
setServeOverHTTP
(
$mode
)
{
return
$this
->
setDetail
(
'serve-over-http'
,
$mode
)
;
}
public
function
getServeOverSSH
(
)
{
$serve
=
$this
->
getDetail
(
'serve-over-ssh'
,
self
::
SERVE_OFF
)
;
return
$this
->
normalizeServeConfigSetting
(
$serve
)
;
}
public
function
setServeOverSSH
(
$mode
)
{
return
$this
->
setDetail
(
'serve-over-ssh'
,
$mode
)
;
}
public
static
function
getProtocolAvailabilityName
(
$constant
)
{
switch
(
$constant
)
{
case
self
::
SERVE_OFF
:
return
pht
(
'Off'
)
;
case
self
::
SERVE_READONLY
:
return
pht
(
'Read Only'
)
;
case
self
::
SERVE_READWRITE
:
return
pht
(
'Read/Write'
)
;
default
:
return
pht
(
'Unknown'
)
;
}
}
private
function
normalizeServeConfigSetting
(
$value
)
{
switch
(
$value
)
{
case
self
::
SERVE_OFF
:
case
self
::
SERVE_READONLY
:
return
$value
;
case
self
::
SERVE_READWRITE
:
if
(
$this
->
isHosted
(
)
)
{
return
self
::
SERVE_READWRITE
;
}
else
{
return
self
::
SERVE_READONLY
;
}
default
:
return
self
::
SERVE_OFF
;
}
}
/**
* Raise more useful errors when there are basic filesystem problems.
*/
private
function
assertLocalExists
(
)
{
if
(
!
$this
->
usesLocalWorkingCopy
(
)
)
{
return
;
}
$local
=
$this
->
getLocalPath
(
)
;
Filesystem
::
assertExists
(
$local
)
;
Filesystem
::
assertIsDirectory
(
$local
)
;
Filesystem
::
assertReadable
(
$local
)
;
}
/**
* Determine if the working copy is bare or not. In Git, this corresponds
* to `--bare`. In Mercurial, `--noupdate`.
*/
public
function
isWorkingCopyBare
(
)
{
switch
(
$this
->
getVersionControlSystem
(
)
)
{
case
PhabricatorRepositoryType
::
REPOSITORY_TYPE_SVN
:
case
PhabricatorRepositoryType
::
REPOSITORY_TYPE_MERCURIAL
:
return
false
;
case
PhabricatorRepositoryType
::
REPOSITORY_TYPE_GIT
:
$local
=
$this
->
getLocalPath
(
)
;
if
(
Filesystem
::
pathExists
(
$local
.
'/.git'
)
)
{
return
false
;
}
else
{
return
true
;
}
}
}
public
function
usesLocalWorkingCopy
(
)
{
switch
(
$this
->
getVersionControlSystem
(
)
)
{
case
PhabricatorRepositoryType
::
REPOSITORY_TYPE_SVN
:
return
$this
->
isHosted
(
)
;
case
PhabricatorRepositoryType
::
REPOSITORY_TYPE_GIT
:
case
PhabricatorRepositoryType
::
REPOSITORY_TYPE_MERCURIAL
:
return
true
;
}
}
public
function
canDestroyWorkingCopy
(
)
{
if
(
$this
->
isHosted
(
)
)
{
// Never destroy hosted working copies.
return
false
;
}
$default_path
=
PhabricatorEnv
::
getEnvConfig
(
'repository.default-local-path'
)
;
return
Filesystem
::
isDescendant
(
$this
->
getLocalPath
(
)
,
$default_path
)
;
}
public
function
canMirror
(
)
{
if
(
!
$this
->
isHosted
(
)
)
{
return
false
;
}
if
(
$this
->
isGit
(
)
)
{
return
true
;
}
return
false
;
}
public
function
writeStatusMessage
(
$status_type
,
$status_code
,
array
$parameters
=
array
(
)
)
{
$table
=
new
PhabricatorRepositoryStatusMessage
(
)
;
$conn_w
=
$table
->
establishConnection
(
'w'
)
;
$table_name
=
$table
->
getTableName
(
)
;
if
(
$status_code
===
null
)
{
queryfx
(
$conn_w
,
'DELETE FROM %T WHERE repositoryID = %d AND statusType = %s'
,
$table_name
,
$this
->
getID
(
)
,
$status_type
)
;
}
else
{
queryfx
(
$conn_w
,
'INSERT INTO %T
(repositoryID, statusType, statusCode, parameters, epoch)
VALUES (%d, %s, %s, %s, %d)
ON DUPLICATE KEY UPDATE
statusCode = VALUES(statusCode),
parameters = VALUES(parameters),
epoch = VALUES(epoch)'
,
$table_name
,
$this
->
getID
(
)
,
$status_type
,
$status_code
,
json_encode
(
$parameters
)
,
time
(
)
)
;
}
return
$this
;
}
/* -( PhabricatorPolicyInterface )----------------------------------------- */
public
function
getCapabilities
(
)
{
return
array
(
PhabricatorPolicyCapability
::
CAN_VIEW
,
PhabricatorPolicyCapability
::
CAN_EDIT
,
DiffusionCapabilityPush
::
CAPABILITY
,
)
;
}
public
function
getPolicy
(
$capability
)
{
switch
(
$capability
)
{
case
PhabricatorPolicyCapability
::
CAN_VIEW
:
return
$this
->
getViewPolicy
(
)
;
case
PhabricatorPolicyCapability
::
CAN_EDIT
:
return
$this
->
getEditPolicy
(
)
;
case
DiffusionCapabilityPush
::
CAPABILITY
:
return
$this
->
getPushPolicy
(
)
;
}
}
public
function
hasAutomaticCapability
(
$capability
,
PhabricatorUser
$user
)
{
return
false
;
}
public
function
describeAutomaticCapability
(
$capability
)
{
return
null
;
}
/* -( PhabricatorMarkupInterface )----------------------------------------- */
public
function
getMarkupFieldKey
(
$field
)
{
$hash
=
PhabricatorHash
::
digestForIndex
(
$this
->
getMarkupText
(
$field
)
)
;
return
"repo:{$hash}"
;
}
public
function
newMarkupEngine
(
$field
)
{
return
PhabricatorMarkupEngine
::
newMarkupEngine
(
array
(
)
)
;
}
public
function
getMarkupText
(
$field
)
{
return
$this
->
getDetail
(
'description'
)
;
}
public
function
didMarkupText
(
$field
,
$output
,
PhutilMarkupEngine
$engine
)
{
require_celerity_resource
(
'phabricator-remarkup-css'
)
;
return
phutil_tag
(
'div'
,
array
(
'class'
=>
'phabricator-remarkup'
,
)
,
$output
)
;
}
public
function
shouldUseMarkupCache
(
$field
)
{
return
true
;
}
}
File Metadata
Details
Attached
Mime Type
text/x-php
Expires
Sun, Jan 19, 18:19 (1 w, 4 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1127371
Default Alt Text
PhabricatorRepository.php (27 KB)
Attached To
Mode
rP Phorge
Attached
Detach File
Event Timeline
Log In to Comment