389 Commits
master ... bake

Author SHA1 Message Date
83bb30c02e Fix regex for safe file name to work correct for unicode 2023-02-09 15:08:15 +01:00
7209e70eee Fix undefined variable 2023-02-07 09:21:03 +01:00
21c4d6c988 Fix undefined function usage 2023-02-07 08:51:02 +01:00
c898053829 Baker: Support explicit timestamp specification
Limits the number of tasks and revisions which are to be checked,
speeding up the iteration.
2023-02-06 15:33:16 +01:00
5906c4a7e9 Use JSON format instead of python 2023-01-31 20:15:22 +01:00
9584c480ac Add utility scripts to collect updates tasks and files 2023-01-30 17:08:08 +01:00
dbb9853e4c Replace "View All Subscribers" link with text 2023-01-28 16:58:10 +01:00
a924b09c84 Ensure all meme macro are inlined 2023-01-28 13:24:06 +01:00
21d145c9dd Use the latest transaction modification time fore the hash 2023-01-27 16:13:16 +01:00
8eaab28e2e Fix wrong transaction query sued for tasks 2023-01-27 15:49:44 +01:00
d026dfa72b Fix rendering of arrays 2023-01-27 15:34:41 +01:00
3dab3e6ffb Disable remarkup cache and handle meme files properly 2023-01-25 15:41:36 +01:00
f9d454431a More correct handling of files with missing transform
Use the original file URI if the transform is not available.

The preview generation is done on-demand when one visits a URL,
which is not easy to do from a baker.
2023-01-25 09:40:59 +01:00
d1037ee999 Disable links to commit in the task's "Revisions and Commits" 2023-01-23 11:05:52 +01:00
2ae41b71ce Allow linking diffs from another revisions 2023-01-23 10:21:28 +01:00
ee2cdc66a3 Correct link to the diff id 2023-01-23 10:11:08 +01:00
8c725e1f30 Only open absolute links in the new window 2023-01-22 20:53:40 +01:00
af28ab583d Make links open in the new tab
This should allow opening links form inside baked
result shown from an iframe.
2023-01-22 17:26:02 +01:00
36c5a9da1e Correction for the previous commit 2023-01-22 15:46:58 +01:00
63443cef58 Correct links to the ghost comment navigation 2023-01-22 15:39:58 +01:00
4d0bbd65c2 Disable more links in various places 2023-01-22 10:43:29 +01:00
ab636281d4 Disable extra information link
It is not really easy to check it locally since some
real repo setup is needed. So, hope for the best.
2023-01-22 10:15:17 +01:00
ae771df2af Disable visibility of badges 2023-01-21 18:54:28 +01:00
e76e6e14c0 Remove Show Details link
It is not baked into.
2023-01-21 18:41:48 +01:00
b43fabc696 Disable links to people form comments 2023-01-21 18:33:27 +01:00
be6ca4dc7d Remove task creation crumbs 2023-01-21 18:21:24 +01:00
06ff69a03c Support rendering pages with crumbs 2023-01-21 18:18:29 +01:00
f28236b2cc Correct links to task
Also explicitly use index.html
2023-01-21 17:57:34 +01:00
895ebed023 Disable project workboard links 2023-01-21 17:47:59 +01:00
c06a59147c Implement maniphest baking 2023-01-21 17:38:01 +01:00
2d960622d3 Fix URL to the raw diff 2023-01-21 14:01:28 +01:00
d50ac79793 Tweaks to baker to use the final directory structure 2023-01-21 13:50:40 +01:00
f5633edf97 Order revisions from oldest to newest
Allows to more easily see the progress.
2023-01-17 12:49:47 +01:00
2ac637aa24 Allow git bundle to use conduit for file access
Some of the changes can not be accesses without this.

Also improved logging and skipped raw diffs if they
already exists.
2023-01-17 12:40:15 +01:00
092c2411d2 Disable buildable status
It contains not-trivial-to-find-links and it does not
bring much information because the CI/CD was never
integrated into the developer.b.o
2023-01-17 11:41:39 +01:00
b967dd64fa Print message about the initial query
Helps to see that the delay is actually expected.
2023-01-17 11:26:38 +01:00
affd4cfd0d Disable more links in the history and local commits 2023-01-17 11:21:54 +01:00
8a882018b9 Initial commit of differential baking changes
NOTE: This branch is not to be deployed as a website, but instead
to be used as a client of a cluster (to have access to the database)
and run the baking script in a unattended mode.

A lot of tweaks all over the place to make the generated HTML suitable
for use in a static HTML with remapped paths to be relative and so on.

NOTE: Because of those tweaks the file rendering and access will not
work as expected when viewed from the website: it will be 404 because
it has different means accessing files than the static HTML. It is not
possible to keep website rendering correct, but it makes it harder to
investigate what parts needs attention without running the baker.

The baking script is found in `scripts/bake/bake_differential.php`
and it receives a single argument which is a directory with the baked
files.

Covers the following aspects:
- File attachments
- Image previews
- Pastes

The user avatars are replaced with the default user avatar.
2023-01-17 10:19:43 +01:00
Anna Sirota
436e69f1d0 Fix alignment of custom badges
Reviewed By: Sergey Sharybin (sergey)
Differential Revision: https://developer.blender.org/D13741
2022-01-06 12:10:57 +01:00
5db4b6f01a Add custom icons for Blender ID badges
Reviewed By: Sergey Sharybin (sergey)
Differential Revision: https://developer.blender.org/D13535
2021-12-10 13:04:22 +01:00
5aabb434b1 Disable as Spam - admin-only option to handle spammers
This implements a convenient way to handle spam users, mimicking the steps the
admins already do manually:

Performed tasks:
* Disable Account
* Real Name -> "spam"
* Title -> ""
* Icon → ""
* Blurb → ""
* Profile Picture → default

This is disabling the account using the same functionality as the "Disable User"
button. And on top of that it replaces the account real name with "spam" and
wipe the other personal information.

Note that this doesn't delete any posts from the user.

Reviewers: sergey

https://developer.blender.org/D11904
2021-07-14 16:22:10 +02:00
eced78a591 Phabricator: Extend CONDUIT API to support xaction transactions
Example of null transactions and their expected value:

* D9:transaction 44 - "abandon"
* D22:transaction 112 - "commit"
* D22:transaction 96 - "accept"
* D1123:transaction 22872 - "rethink"

Reviewers: sergey

https://developer.blender.org/D11568
2021-06-10 16:36:21 +02:00
fb3e6ba493 Fix duplicate system users added on every update
Was a mistake in the way how key de-duplication and non-phabricator-managed
commit access was dealt with.

For now simple fix: make sure user list is unique. Proper fix would require
something more sophisticated.
2021-03-05 12:05:49 +01:00
284204e6bb Detect duplicate keys form user configuration
Apparently there are some duplicates in the phabricator
configuration, even though the interface has a check against
this.
2020-11-05 12:50:00 +01:00
1df20d771c Initialize committers variable
Prevented the check for variable collision detection from
previous commit: first time the committers property was
null.
2020-11-05 12:45:23 +01:00
6fa976f749 Make sure committers variable is never overwritten
Solves possible issue when having repositories "foo-bar" and "boo_bar".
2020-11-05 10:15:13 +01:00
8808cf8e8c Fix repositories not being properly escaped
In gitolite configuration variable which controls commit access must
not include dash.
2020-11-04 19:00:21 +01:00
f72b9824f3 Do not overwrite files if they did not change
This causes an extra file read, but the benefit is that it is easier
to compare data on the file system, quickly see what did actually change
and what did not.
2020-11-04 11:39:40 +01:00
ac94643ac7 Correct for the previous system keys refactor 2020-11-03 17:11:18 +01:00
ce3c14919d Fix for previous commit
Syntax error.

That's what one gets by typing code on one machine and testing on another.
2020-11-03 17:09:39 +01:00
c9fb4c2945 More fixes for gitolite configuration script
More usages of undefined variable.
Corrected mistake in collection of system keys.
2020-11-03 17:08:00 +01:00
57099f29d1 Fixes for gitolite synchronization script
- Typo in the variable used, caused by bad refactoring skills.
- Explicitly do pull rebase semantic.
2020-11-03 17:04:03 +01:00
acfdc33789 Fix gitolite config incrementally adding more and more new lines 2020-11-03 16:24:29 +01:00
a5efb1e8cd Initial implementation of gitolite integration script
Is based on old gitosis/gitadmin script, but it is heavily refactored
in the process of migration.
2020-11-02 16:13:24 +01:00
e0bd65be95 Support custom policy for GIT access rules
Implements following rules:
- Users
- Users of any project
- Users of all projects
- Administrators
- Signers

The 'If No Rules Match' the access is implicitly considered to
be 'DENY'.

It is not possible to control access based on the Moon phase.
2020-09-17 13:26:33 +02:00
1bcc201b0a Support custom policy for SVN access rules
Implements following rules:
- Users
- Users of any project
- Users of all projects
- Administrators
- Signers

The 'If No Rules Match' the access is implicitly considered to
be 'DENY'.

It is not possible to control access based on the Moon phase.
2020-09-17 12:38:14 +02:00
b2d7879162 Cleanup: Make variable naming more clear
Match the generator name passed via the command line.
2020-09-17 11:39:19 +02:00
775a1c2eef Remove SVN authfile generation
It is no longer needed (replaced with the auth_provider).
2020-09-17 11:37:18 +02:00
bd07cea6a6 Remove access to htpassword custom field
It is retired and is no longer in use, replaced with the auth_provider.
2020-09-17 11:35:36 +02:00
6139ce1841 Canned responses for bug reports
This shows a 'reply' icon in the markup form header. The config to add more
canned responses is `maniphest.canned-responses`.

Note: There is no validation (other than json), so the config is expected to
match the required fields ('name' and 'message')

Note: This shows at all markups, so technically it can be used for patch
review and other places where canned reponses would fit.

Differential Revision: D8034
2020-06-17 15:42:46 +02:00
c38766c17f Merge branch 'master' into blender-tweaks 2020-06-16 11:41:11 +02:00
f9637502ee Merge branch 'master' into blender-tweaks 2020-04-08 15:57:07 +02:00
Nathan Letwory
0ddfe6fcfb Fix missing duplication xaction data.
Both 'mergedinto' and 'mergedfrom' are now
realized 'transaction.search'.

Test Plan:
- Check output of 'transaction.search' for
  a task marked as duplicate of another
- Check output of 'transaction.search' for
  a task that has another task set as its
  duplicate

Differential Revision: https://developer.blender.org/D7090
2020-03-11 07:23:19 +02:00
Nathan Letwory
dc57652085 Fix subtype transaction data missing.
Test plan: change type of a task, check
with transaction.search the transaction
data exists.
2020-02-28 15:45:48 +02:00
5ba0687123 Show number of query result for advanced queries 2019-12-24 11:18:19 +01:00
fef207bf00 Fix task counter query
Was doing wrong count when multiple projects were involved.
Also pagination was not ignored as it should have.

This technically increases load on the database, so maybe
we need to upgrade server to handle real thing we want to be
displayed.
2019-12-23 18:15:35 +01:00
5ef3552549 Correct link to new addons 2019-12-23 11:52:02 +01:00
0f6ca4be21 Tweaked wording and links on the front page 2019-12-23 10:42:55 +01:00
4653348b13 Maniphest: Switch from custom type field to task subtype 2019-12-18 10:33:12 +01:00
6826284108 Maniphest: Remove blender-specific type rendering
Will be rendered using task's subtype.
2019-12-18 09:53:53 +01:00
c93fdca80d Merge branch 'master' into blender-tweaks 2019-12-17 13:02:09 +01:00
432b6d61a6 Show correct command to destroy users 2019-10-17 11:25:53 +02:00
4c2b7d7573 Merge branch 'master' into blender-tweaks 2019-10-17 11:23:01 +02:00
d8e25a6226 Correct shebang to be usable in the deployed environment 2019-10-03 15:27:02 +02:00
db6f4eaab1 Merge branch 'master' into blender-tweaks 2019-10-01 14:48:19 +02:00
4555f18c41 Add auth provider which uses Phabricator
The idea is to use it instead of a custom field approach.
2019-09-30 17:23:36 +02:00
788d8a8b98 Remove local hack preserving line breaks
This seems to be addressed by upstream nowadays.
2019-09-30 17:21:03 +02:00
55f22f74f5 Revert "Fix for missing updates of hidden properties"
More correct fix is being worked on.

Reverting to an older state, to be able to deploy other changes.

This reverts commit 8efe191897.
2019-09-30 17:17:19 +02:00
de2f7e857d Fix wrong method visibility
Was discovered by `arc unit`, caused by wrong merge conflict resolution.
2019-09-30 16:59:37 +02:00
7c869ab033 Update arc libreate
Seems there is no need to run it for extensions.

Solves error reported by `arc unit`.
2019-09-30 16:59:29 +02:00
f9c680ddc0 Merge branch 'upstream_master' into blender-tweaks 2019-09-30 10:52:47 +02:00
8efe191897 Fix for missing updates of hidden properties 2019-09-30 10:50:51 +02:00
8d6f1a6128 Proper commenting style. 2019-09-24 00:44:08 +03:00
81bae35d2f Render milestones as original getDisplayName. 2019-09-24 00:44:08 +03:00
fc5744c7f0 Show entire path for all projects. 2019-09-24 00:44:08 +03:00
7aea82d526 Clean up ancestor path implementation.
* mpull for cleaner ancestor access
* move implementation to PhabricatorProject
  * as new function getDisplayNameWithAncestorPath
  * no pht usage, since there are no localisable items
2019-09-24 00:44:08 +03:00
cb29054e66 Show ancestor path for sub-projects and milestones.
To understand better to what projects a sub-project or
milestone belongs show the entire ancestor path.

Solves part of T69306.

Differential Revision: https://developer.blender.org/D5656
2019-09-24 00:44:08 +03:00
0416648b39 Merge branch 'master' into blender-tweaks 2019-09-18 10:42:01 +02:00
01fea69352 Limit some workflow elements to moderators
Allows to streamline triaging and keeping track of reports status,
together with removing confusing elements which non-moderators can
not use anyway.
2019-09-03 15:38:59 +02:00
c7a2133639 Differential: fill author field from user account
Do it unless this information was provided by `arc diff`.
2019-09-03 14:43:43 +02:00
a162f188c2 Differential: exclude fields from commit message to follow our guidelines
Do it as a tweaks to render due to:

- Those fields are considered permanent.
- We still want to be able to specify them when creating new revisions
  (at least for subscribers/reviewers).
2019-09-03 14:36:00 +02:00
2b54804c7b Merge branch 'master' into blender-tweaks 2019-09-03 14:24:06 +02:00
a8fef30871 Merge branch 'master' into blender-tweaks 2019-09-02 10:19:50 +02:00
9dc4d903c7 Ignore disabled users for Git/SVN synchronization 2019-08-01 16:51:02 +02:00
b8b18995c5 Merge branch 'master' into blender-tweaks 2019-06-20 10:02:20 +02:00
971b397133 Merge branch 'master' into blender-tweaks 2019-06-19 10:37:08 +02:00
aee7dc94bc More fixes for MFA 2019-06-18 16:18:29 +02:00
feb8db1212 Fix non-vector sorting used on a vector 2019-06-18 10:44:00 +02:00
f9f7f005f2 Fix task count query not working 2019-06-18 09:05:19 +02:00
2321a886ae Merge branch 'master' into blender-tweaks 2019-06-18 08:29:51 +02:00
72858c6746 Wrap task count selection part to a query string 2019-06-18 08:22:30 +02:00
79ca5a3026 Update top bar to match other websites 2019-06-18 08:17:32 +02:00
3d37998174 Update diff guidelines, login and welcome text 2019-06-17 16:11:02 +02:00
ce29e40b57 Merge branch 'master' into blender-tweaks 2019-04-25 14:19:49 +02:00
ef26d6afdc Merge branch 'master' into blender-tweaks 2019-04-04 11:21:47 +02:00
dc84bc9391 Allow committing to SVN branches 2019-03-15 16:45:19 +01:00
321eb18cd7 Fix SVN rules synchronization script 2019-02-05 12:40:35 +01:00
6936b8c4f3 Ignore hidden fields in the feed 2019-02-04 15:15:43 +01:00
26f43ee9b8 Merge branch 'master' into blender-tweaks 2019-02-04 14:17:46 +01:00
e19d318af9 Merge branch 'master' into blender-tweaks 2019-01-25 15:35:33 +01:00
dfc7f764de Merge branch 'master' into blender-tweaks 2018-12-26 11:44:27 +01:00
331b4cc42c Use better suitable policy for the previous commits 2018-12-11 10:07:43 +01:00
674d537f91 Similar tweaks for priority and status 2018-12-11 10:01:28 +01:00
a442a019d9 Allow assigning task to anyone who can view the task
Matches old behavior prior to a recent update.
2018-12-11 09:58:32 +01:00
774a554405 Post-merge fix for API usage 2018-12-09 17:21:40 +01:00
90f56e07ff Attempt to fix usage of wrong class 2018-12-09 13:28:47 +01:00
4b428ffb8a Merge branch 'master' into blender-tweaks 2018-12-09 13:25:53 +01:00
bcd0caecd1 Merge branch 'master' into blender-tweaks 2018-12-04 10:29:38 +01:00
78c32afa4e Merge branch 'master' into blender-tweaks 2018-10-22 12:31:30 +02:00
f3302fe1b9 Grant fiel editing and deletion to admins 2018-08-03 11:58:08 +02:00
7eba06c43d Merge branch 'master' into blender-tweaks 2018-08-02 14:26:08 +02:00
713f8e2c6a Merge branch 'master' into blender-tweaks 2018-04-24 12:56:12 +02:00
ea0100310b Fix issue with double-slash added to maniphest URLs 2018-04-16 12:36:11 +02:00
4332bfe537 Merge branch 'master' into blender-tweaks 2018-04-16 12:29:33 +02:00
25ce2bdd92 Merge branch 'master' into blender-tweaks 2018-02-09 11:03:26 +01:00
dc17ef4f7c Merge branch 'master' into blender-tweaks 2018-01-29 09:40:46 +01:00
8097508909 Merge branch 'master' into blender-tweaks 2018-01-29 09:39:57 +01:00
8addc33734 Add state of the art fax defence into the source tree 2017-12-07 11:24:51 +01:00
990136a337 Grant profile editing to administrators 2017-12-07 09:32:02 +01:00
d14b204aae Merge branch 'master' into blender-tweaks 2017-12-06 16:58:17 +01:00
4067829d2c Fix/workaround for code review not working for logged out users 2017-10-19 07:50:39 +02:00
8bc4c8c485 Merge branch 'master' into blender-tweaks 2017-10-18 13:29:21 +02:00
bf8aec2a14 Merge branch 'master' into blender-tweaks 2017-10-02 10:51:32 +02:00
ace2787868 Fix T52676: Phabricator 'To Do' URL format and search error 2017-09-18 14:13:39 +02:00
08dde1da13 Merge branch 'master' into blender-tweaks 2017-09-08 15:50:36 +02:00
4cde7a4b06 Correct previous commit 2017-04-27 16:27:47 +02:00
42ce8a82af Fix hidden fields were isible in conduit 2017-04-27 16:16:35 +02:00
6d6e446f6f Merge branch 'github-facebook-master' into blender-tweaks 2017-04-27 16:14:16 +02:00
26bf667fec Fix unwanted caption for real now
Hopefully.
2017-03-29 13:25:16 +02:00
18b9c9b0b1 Attempt to remove Summary from differencial template 2017-03-29 12:12:47 +02:00
f78ca8833b Update generator script to the latest changes in Phabricator 2017-03-27 10:12:55 +02:00
19337de8f0 Merge branch 'master' into blender-tweaks 2017-03-20 09:28:31 +01:00
c2a4fbc98c Followup commit, allow changing task project tags 2017-03-15 16:04:22 +01:00
87c0e13efd Attempt to solve regressions in our policy rules
Users weher able to triage other's reports.
2017-03-15 12:13:18 +01:00
3442097b31 Attempt to fix arcanist diff 2017-03-14 15:31:10 +01:00
c7764ed1d0 Quick hack to restore old main page title 2017-03-14 13:58:08 +01:00
6e39022af9 Merge branch 'master' into blender-tweaks 2017-03-09 12:13:16 +01:00
d88716feba Merge branch 'blender-tweaks' of git.blender.org:phabricator into blender-tweaks 2017-01-20 14:13:04 +01:00
678347d836 Merge branch 'master' into blender-tweaks 2017-01-20 14:12:45 +01:00
890ccea846 Use separate form for addons bug 2016-12-02 09:48:16 +01:00
405525357d Fix T50155: Maniphest could provide better information on task reject
Use bug report form when reporting bug from the project page in maniphest
2016-12-02 09:39:48 +01:00
3eee2a3311 Fix typo from previous commit 2016-07-18 14:48:56 +02:00
55d1f0081d Fix links in the diff submission guidelines 2016-07-18 14:46:06 +02:00
ea73d9bf86 Fix bug accessing user manage form 2016-07-07 16:20:29 +02:00
3eab15180c Fix bugs accessing user preferences 2016-07-07 16:13:07 +02:00
2210be45fe Make it possible to create new tasks with Blender's policies 2016-07-07 12:17:07 +02:00
5bdc3dfad8 Merge branch 'master' into blender-tweaks 2016-07-01 09:16:15 +02:00
c22440fe30 Merge branch 'master' into blender-tweaks 2016-05-20 11:26:25 +02:00
b41844290b Merge branch 'master' into blender-tweaks 2016-04-06 09:39:20 +02:00
32a3440156 Merge branch 'blender-tweaks' of git.blender.org:phabricator into blender-tweaks 2016-03-15 18:25:38 +05:00
630eb3c143 Post-merge blender tweaks 2016-03-15 18:25:26 +05:00
534b628ad2 Update mobile 'home' page links
If you use phabricator with a mobile phone with small screen space
you get only the sidebar at http://developer.blender.org/.

If you the click the 'Home - Command Center' Button available for
mobile devices you get the site http://developer.blender.org/home/

But there, the short-cut links will result in a 404 page (or login,
if you are not logged in) so better make the links there absolute.

Patch by Leon (Leon95), thanks!

Reviewers: sergey

Subscribers: sergey

Projects: #phabricator, #infrastructure:_websites

Differential Revision: https://developer.blender.org/D1843
2016-03-14 11:37:40 +05:00
8a463524b4 Use own Phab install for arc
This way we can apply patches submitted to our tracker.
2016-03-14 11:36:24 +05:00
b50eefbd5b Merge branch 'master' into blender-tweaks 2016-03-05 16:19:51 +05:00
3a2ebeca11 Merge branch 'github-facebook-master' into blender-tweaks 2015-12-24 22:50:19 +05:00
95f7da61a9 Remove unneeded custom configuration options 2015-12-18 19:55:22 +05:00
0d04beb777 Switch maniphest to sue new phab forms instead of some hardcoded fields etc 2015-12-18 15:46:18 +05:00
7ab26ff7af Bring back comment about drag-drop in the re-markup edit field. 2015-12-18 15:29:49 +05:00
6800fc6103 Preserve line breaks for the instruction fields 2015-12-18 15:15:59 +05:00
9077c1f24f Merge branch 'master' into blender-tweaks
Still some work to be done bring back some removed customizations,
but they can be done using new awesome phab features.
2015-12-18 15:04:15 +05:00
2327f2af6f Show maniphest task type in the list 2015-12-17 23:06:46 +05:00
41fff9c930 Fix alignment in the maniphest list
"Assigned To" and "By" fields were too short.
2015-11-13 18:11:21 +05:00
cfcef40c65 Merge branch 'master' into blender-tweaks 2015-11-13 17:46:32 +05:00
29d158a3bc Don't show list of members in the project's details page
This only adds clutter, plus we've got dedicated page for members.
2015-11-13 17:34:41 +05:00
411cf324dd Linking to project will go to project's details page, not to the board
Board is not so much helpful to see for average users.
2015-11-13 17:30:36 +05:00
52230a803f Merge branch 'github-facebook-master' into blender-tweaks 2015-11-13 17:20:03 +05:00
ddf6f275db Show login in the user monogram
This is actually appeared handy after discussion with campbell.
2015-06-03 15:13:29 +05:00
8c65ee54d0 Make user monograms surviving cases when there's no real name 2015-06-03 14:59:41 +05:00
d07d44fcc7 Remove debug-only code from the previous commit 2015-06-03 14:34:39 +05:00
772d59f0ab Make real name more primary way of communication 2015-06-03 14:32:32 +05:00
f7da3f88f9 Fix T44841: Error when clicking Maniphest in the phabricator sidebar 2015-05-26 13:12:07 +05:00
e4f6cf9993 Attempt to fix issues with task counter returning several rows 2015-05-26 12:58:32 +05:00
dd34c93656 Put gruping back to the task counter sql 2015-05-26 12:35:44 +05:00
320ffa2308 Fix buildbot application
Was using deprecated class.
2015-05-18 15:27:46 +05:00
b5e7136f68 Update celerity map 2015-05-18 01:31:51 +05:00
e2b7664451 Use different widths for dashboard and regular maniphest task 2015-05-18 01:31:22 +05:00
725ad07e6f Attempt to make both welcome screen and maniphest task list happy with word wrapping 2015-05-18 01:27:59 +05:00
75cbd69d85 One more tweak, sorry for the trouble 2015-05-18 01:02:59 +05:00
a9a71ef011 Tweak to previous commit
Previous commit made it so task title is cropper far too soon.
Still not really ideal solution, but should be good enough for now.
2015-05-18 01:00:29 +05:00
362ba36695 Fix authorship not fitting into maniphest task in the list 2015-05-18 00:39:58 +05:00
38d687ede2 Attempt to make default repositories sorting by name 2015-05-17 23:39:55 +05:00
78cd1cf494 Remove results of wrong merge 2015-05-17 22:49:57 +05:00
0b990d42cd Add Blender Next to always visible projects 2015-05-17 22:14:53 +05:00
74571de5b6 Deduplicate some code, saved/unsaved query title is handling in getDescriptionForQuery 2015-05-17 21:47:22 +05:00
01ce61f6e2 Update text of addon patch submission 2015-05-17 21:40:14 +05:00
09c9aa078d Tweaks to the home file to make it wrap nicely 2015-05-17 21:36:00 +05:00
73441d690e Merge branch 'master' into blender-tweaks
Conflicts:
	resources/celerity/map.php
	src/applications/config/option/PhabricatorCoreConfigOptions.php
	src/applications/differential/controller/DifferentialDiffCreateController.php
	src/applications/files/storage/PhabricatorFile.php
	src/applications/maniphest/query/ManiphestTaskQuery.php
	src/applications/maniphest/query/ManiphestTaskSearchEngine.php
	src/applications/repository/query/PhabricatorRepositorySearchEngine.php
	src/applications/search/controller/PhabricatorApplicationSearchController.php
2015-05-17 21:24:32 +05:00
afdc21ee04 Merge branch 'master' into blender-tweaks
Conflicts:
	resources/celerity/map.php
2015-03-06 20:28:53 +05:00
fc317b7f28 Move extension applications to where they are expected to be 2015-03-06 20:21:53 +05:00
b3f2b7faf4 Use a bit closer to previous installation icon for buildbot application 2015-03-06 20:19:45 +05:00
7ea70dcb53 Make home page much closer to the upstream
Mainly get rid of hardcoded feed panel, this can be done with
dashboards now.
2015-03-06 19:27:42 +05:00
d0b90fdef7 Replace all favicon files with blender logo 2015-03-06 19:13:16 +05:00
3c05d31d2e Merge branch 'master' into blender-tweaks
Conflicts:
	.gitignore
	resources/celerity/map.php
	src/__phutil_library_map__.php
	src/applications/home/controller/PhabricatorHomeMainController.php
	src/applications/maniphest/controller/ManiphestSubscribeController.php
	src/applications/maniphest/event/ManiphestActionMenuEventListener.php
	src/applications/maniphest/query/ManiphestTaskQuery.php
	webroot/rsrc/css/application/base/main-menu-view.css
	webroot/rsrc/css/sprite-menu.css
2015-02-27 13:23:38 +05:00
11f5eb21af Merge branch 'master' into blender-tweaks
Conflicts:
	resources/celerity/map.php
	src/applications/differential/controller/DifferentialDiffCreateController.php
2014-11-29 18:37:00 +05:00
c90665645e Gitosis sync fixes and improvements
- Fixed some remaining issues caused by the update process.
- Support custom rules for the repositories.
  Currnetly only supports allowing users.
2014-11-10 01:38:58 +05:00
fb3c71820b Fix rebuild gitadmin using old user typeconst class 2014-11-10 01:16:32 +05:00
e533774ac0 Some post-merge tweaks, regenerated celerity map 2014-11-08 18:38:00 +05:00
647f8de9bb Merge branch 'master' into blender-tweaks
Conflicts:
	resources/celerity/map.php
	webroot/favicon.ico
	webroot/rsrc/css/application/base/main-menu-view.css
	webroot/rsrc/css/sprite-menu.css
2014-11-08 18:37:40 +05:00
599bf57cd8 Merge branch 'master' into blender-tweaks
Conflicts:
	resources/celerity/map.php
	src/applications/maniphest/controller/ManiphestTaskListController.php
2014-11-01 17:23:50 +05:00
50c506ea2d Merge branch 'master' into blender-tweaks
Conflicts:
	conf/default.conf.php
	resources/celerity/map.php
2014-10-11 20:22:36 +06:00
4cc7990b1a Attempt to fix bad url to To Do tasks in maniphest 2014-10-03 02:35:19 +06:00
4ef5fdefb2 Experiment with showing both real and login names
This way it's still easy to reference people with @ and makes
it more natural communication using real name if needed.
2014-10-03 02:32:57 +06:00
a018837214 Revert "Show real name rather than the nick name in the interface all over the place"
This reverts commit e74f0e1558.

Showing just a name makes it impossible to reference people in a comments using @.
2014-10-01 11:27:36 +06:00
e74f0e1558 Show real name rather than the nick name in the interface all over the place 2014-09-30 18:06:15 +06:00
fd882b5167 Merge branch 'master' into blender-tweaks
Conflicts:
	resources/celerity/map.php
2014-09-30 14:31:44 +06:00
15bda62b89 Fix shouldAllowPublic method redeclaration 2014-09-23 13:34:54 +06:00
5e4ce96266 Fix some more issues after the merge 2014-09-23 00:57:46 +06:00
dbd2f0d06f Fix bad conflict resolve
Also fix wrong push capability check.
2014-09-23 00:23:56 +06:00
c87e657412 Fix wrong navigation from custom query to hidden project 2014-09-22 19:29:02 +06:00
6275e3f08f Merge branch 'master' into blender-tweaks
Conflicts:
	resources/celerity/map.php
	src/__phutil_library_map__.php
2014-09-21 19:41:03 +06:00
bc2e4a2452 Always Blender Regressions project in the maniphest projects list 2014-09-14 16:14:53 +06:00
ba7d9fb724 Merge branch 'master' into blender-tweaks
Conflicts:
	resources/celerity/map.php
	src/__phutil_library_map__.php
	src/applications/diffusion/controller/DiffusionRepositoryEditMainController.php
	src/applications/project/controller/PhabricatorProjectListController.php
2014-09-14 16:12:27 +06:00
c50ab96abb tweak to hidden custom field 2014-07-28 01:39:05 +06:00
fa68c6a0fa Preserve line breaks in projects descriptions
This is slightly better fix than previous commit, but
we might totally revisit it as a part of

  https://secure.phabricator.com/D10014
2014-07-22 21:17:35 +06:00
d1b60fec48 Revert "Preserve lone breaks in projects description"
This reverts commit 87e0a26d24.
2014-07-22 20:51:24 +06:00
99a839605c Fix wrong source for projects
Also made code lcoser to master.
2014-07-22 20:31:31 +06:00
08f5b3e920 Merge branch 'master' into blender-tweaks 2014-07-22 20:20:57 +06:00
87e0a26d24 Preserve lone breaks in projects description 2014-07-22 15:12:17 +06:00
91c07e9f99 Merge branch 'master' into blender-tweaks
Conflicts:
	resources/celerity/map.php
	src/applications/maniphest/controller/ManiphestTaskEditController.php
2014-07-22 13:33:45 +06:00
9b2b75e4b4 Workaround for regular users not being able to report new tasks
This is caused by the self-locking check which fails in our usecase.
2014-07-22 13:03:23 +06:00
77c913c70a Correct key name usage in the previous commit 2014-07-20 16:48:47 +06:00
1a1bea527c Attempt to fix issue with sending new differencial revision to review 2014-07-20 16:43:32 +06:00
46f8f6d90d Pin buildbot and documentation by default 2014-07-20 03:59:29 +06:00
dbad3b6489 Quick fix for the maniphest navigation 2014-07-20 03:40:17 +06:00
1821cedbc4 Show unconfirmed project link 2014-07-20 03:14:05 +06:00
1448eafd64 Use HTTPS link to the buildbot 2014-07-20 03:11:59 +06:00
8f4047b36a Merge branch 'master' into blender-tweaks
Conflicts:
	resources/celerity/map.php
	src/applications/home/controller/PhabricatorHomeMainController.php
	src/applications/maniphest/controller/ManiphestTaskEditController.php
	src/applications/maniphest/query/ManiphestTaskQuery.php
	src/infrastructure/customfield/standard/PhabricatorStandardCustomField.php
2014-07-17 01:33:33 +06:00
2683fde42a Remove hacks around custom task status
Seems it's no longer needed since statuses are actually
configurable via UI configurator.
2014-06-06 18:12:12 +06:00
02522d877d Tweak for storage migration script to update status for archived tasks 2014-06-06 18:06:13 +06:00
769ffa2982 Restore hack which allowed importing projects.b.o passwords 2014-06-06 17:29:39 +06:00
33eed14141 Page title got lost 2014-06-06 15:33:08 +06:00
a0bd47a012 Correction to hidden custom fields 2014-06-06 15:12:55 +06:00
8c14ef97bf Get rid of custom code in home page
Seems it's no longer needes.
2014-06-06 15:03:48 +06:00
5bdfbe8250 Attempt to fix maniphest tak editing form 2014-06-06 14:50:09 +06:00
f2319c9689 Don't show archived projects in maniphest sidebar 2014-06-06 14:34:38 +06:00
c3138c6497 Merge branch 'master' into blender-tweaks
Conflicts:
	resources/celerity/map.php
	src/__phutil_library_map__.php
	src/applications/auth/application/PhabricatorApplicationAuth.php
	src/applications/base/controller/PhabricatorController.php
	src/applications/differential/customfield/DifferentialLintField.php
	src/applications/differential/customfield/DifferentialUnitField.php
	src/applications/differential/field/specification/DifferentialManiphestTasksFieldSpecification.php
	src/applications/differential/view/DifferentialRevisionUpdateHistoryView.php
	src/applications/feed/application/PhabricatorApplicationFeed.php
	src/applications/home/controller/PhabricatorHomeController.php
	src/applications/home/controller/PhabricatorHomeMainController.php
	src/applications/maniphest/constants/ManiphestTaskStatus.php
	src/applications/maniphest/controller/ManiphestController.php
	src/applications/maniphest/controller/ManiphestTaskDetailController.php
	src/applications/maniphest/controller/ManiphestTaskEditController.php
	src/applications/maniphest/controller/ManiphestTaskListController.php
	src/applications/maniphest/event/ManiphestActionMenuEventListener.php
	src/applications/maniphest/query/ManiphestTaskQuery.php
	src/applications/maniphest/query/ManiphestTaskSearchEngine.php
	src/applications/maniphest/view/ManiphestTaskProjectsView.php
	src/applications/people/storage/PhabricatorUser.php
	src/applications/project/controller/PhabricatorProjectListController.php
	src/applications/project/controller/PhabricatorProjectProfileController.php
	src/applications/search/controller/PhabricatorApplicationSearchController.php
	src/applications/settings/controller/PhabricatorSettingsMainController.php
	src/infrastructure/customfield/standard/PhabricatorStandardCustomField.php
	src/view/phui/PHUIPropertyListView.php
	webroot/rsrc/css/sprite-menu.css
2014-06-05 17:07:20 +06:00
56e8308621 SVN auth script: enable commit access to /tags folder 2014-03-27 18:18:56 +06:00
cb6a8756b6 Migration: remove files and changes from gforge migration.
These were moved to blender-migration branch.
2014-02-03 13:35:20 +01:00
e7242143a0 Merge: more tweaks to project page for when there is no description or no members. 2014-02-03 13:19:26 +01:00
c12898b63a Merge: restore project description to more prominent location again. 2014-02-03 13:07:10 +01:00
9453f29deb Merge branch 'master' into blender-tweaks
Conflicts:
	scripts/celerity_mapper.php
	src/__celerity_resource_map__.php
	src/applications/differential/controller/DifferentialDiffCreateController.php
	src/applications/diffusion/controller/DiffusionBrowseFileController.php
	src/applications/diffusion/controller/DiffusionRepositoryEditPolicyController.php
	src/applications/files/storage/PhabricatorFile.php
	src/applications/maniphest/controller/ManiphestTaskListController.php
	src/applications/project/controller/PhabricatorProjectController.php
	src/applications/project/controller/PhabricatorProjectProfileController.php
	src/applications/repository/storage/PhabricatorRepository.php
	webroot/rsrc/externals/javelin/lib/control/typeahead/source/TypeaheadSource.js
2014-02-03 15:42:43 +06:00
9093816113 Phabricator: restore reviewers and CCs field in commit messages, they are needed
for arc diff.
2014-01-24 17:58:08 +01:00
3471c1b87e Fix T37772: Tab indentation missing in Diffusion
This seems to be a specific of how browsers are dealing with
spaces/tabs. Multiple spaces works just fine, but multiple
tabs were treating as a single space which breaks indentation.

Now made it so tabs are replaced with 4 spaces. Not ideal but
still better than fully unreadable code.
2014-01-17 17:05:14 +06:00
30f0de9427 Fix T38210: phabricator file downloads not working for non-logged in users. 2014-01-15 15:53:50 +01:00
5278e94566 Further arc commit messages tweak to follow guidelines, leave out CCs,
Reviewers (not Reviewed By), Maniphest Tasks and Summary label.
2014-01-04 05:37:58 +01:00
08b1e9d764 Fix buildbot link not working after move to https, redirect instead now. 2014-01-04 05:13:51 +01:00
30427e0626 Leave reviewers and CCs out of commit message. 2014-01-04 05:13:28 +01:00
752a5b9bc3 Further tweak to bug report page descriptions. 2013-12-29 18:25:34 +01:00
a5390d5461 Improve bug report page descriptions. 2013-12-29 18:23:02 +01:00
a02fa19d5a Fixed typo in previous commit, no functional changes. 2013-12-25 17:44:36 +06:00
f88bdcd4ff Truncate file to 10 sec on display with diffusion
Displaying huge files like .po used loads of CPU power
and might have easily run out of time or memory.

Now file will be truncated after 10 sec of view generation.
2013-12-25 17:34:24 +06:00
b98f8a570c Added a way to generate login=>(email, real name) map
Also fixed a typo in custom field in user change password function.
2013-11-29 22:58:33 +06:00
644070340d Add list of all archived repositories 2013-11-28 15:39:25 +06:00
93fecfe7e9 Added list of archived repositories which RO access to them
Currently only bf-extensions, rest of the repos will arrive soon.
2013-11-28 15:19:32 +06:00
53bb3ac361 Make sure all the users have RO access to the repo 2013-11-28 15:09:37 +06:00
137df8c6d3 Make sure there's no trailing slash in svn's subpath
This gives issues with svn access file, leading to
access denied by the server.
2013-11-28 14:57:24 +06:00
9863285bf0 Fix missing project action list on mobile. 2013-11-27 20:47:30 +01:00
a392b4a14f Fix typo in svn authentification generator script 2013-11-28 00:21:59 +06:00
d03569e908 Correction for the previous commit 2013-11-27 22:20:55 +06:00
b1097e9c61 Fix for crash when pushable project have unknown users
Apparently we've got Unknown Object (Phabricator User) in
translation project now.

Not sure how it became invalid, but automated scripts
better be robust for this.
2013-11-27 22:14:07 +06:00
5bda6bf48b Attempt to make SVN happy with untrusted server certificate
Need this to fetch changes from our svn.b.o which have untrusted
issuer of the certificate.
2013-11-27 19:36:13 +06:00
a03cdacd9e Tweaks to svn access rights importer
- Make it work with repositories outside of svn.b.o.
  Useful for local debugging.

- Make it aware of svn subpath repository setting.
  So now it's possible to restrict commit rights
  to a subpath in svn repository.

- Make SVN repositories always available for
  read-only access;
2013-11-27 18:37:37 +06:00
c3fe33f5a0 Remove debug-only code from svn auth script 2013-11-27 02:25:47 +06:00
5d823ff1a7 Fix T37436: Add a method to show the bug count
Now query header will show text like:

  N total tasks for query "Foo"
2013-11-22 00:24:14 +06:00
63df9dd1f4 Undo test commit. 2013-11-21 19:10:36 +01:00
0c80c9fead Add "Open Revisions" builtin query for differential, and have links for both
code reviews and patches on welcome page.
2013-11-21 19:05:38 +01:00
b8d42a7cc6 Test commit for disabling merge commits. 2013-11-21 19:05:38 +01:00
4e7dc30fea Fix typo in method name 2013-11-21 23:17:13 +06:00
99c68b1091 Fix T37529: show up to 4 project tags for maniphest tasks instead of 2. 2013-11-19 16:14:03 +01:00
d48979091e Maniphest: order open tasks by date created and don't group by priority, to
make it more like the old bug tracker. Also makes count bugs fairly easy by
just looking at the number on the second or third page.
2013-11-17 10:21:38 +01:00
785caa5b6c Test commit for mail hooks, would prefer to do not it on live install but
that seems to be the only place it fails.
2013-11-16 04:22:04 +01:00
261d7331f4 Remove some unnecessary code from last commit. 2013-11-16 02:49:55 +01:00
28bd8409df Remove unnecessary duplicate buildbot crumb. 2013-11-16 02:44:17 +01:00
47008a157c Browse Patches pointed to a wrong project 2013-11-16 00:00:02 +06:00
fc1e8681ef Add application name in crumbs display. 2013-11-15 17:30:28 +01:00
17085b4379 Try to clarify that the select projects listed on the home page are not all
projects.
2013-11-15 17:30:28 +01:00
dd6eefcd9c Make "Active" projects the default instead of "Joined". 2013-11-15 17:30:28 +01:00
ae2b0e63d6 Further tweaks to gi ermissions script
- Seems @all didn't work, now use explicit list of repos
- Handle cases when phab user uses the same key as used for
  "system" repositories.
2013-11-15 20:19:20 +06:00
bcbae097de Another attempt to make phab sync working 2013-11-15 18:55:16 +06:00
b59dca4eeb Made it so public keys are stored in files with .pub extension
It is an attempt to solve issues with missing permissions on
pahabricator users.
2013-11-15 18:49:56 +06:00
8098798fa9 Fix T37435: clicking maniphest next button with no /query in the URL would lose
the default query and show the search form on the second page.

This was a bug in Phabricator itself, just not as likely to happen because we
have the default query as Open Tasks while they have Assigned, which is unlikely
to give more than 100 results and so there would be no next button.
2013-11-15 02:46:28 +01:00
d8d0e2c99f Fix T37447: Add a link to project list when creating tasks. 2013-11-15 00:32:18 +01:00
214233f82f Show author name in task list views.
Fixes T37451.
2013-11-15 00:04:00 +01:00
eebe82c990 Assume 4 space for tabs by default in differential. 2013-11-14 23:27:09 +01:00
5b73071d64 Removed debug-only left-over 2013-11-15 02:29:03 +06:00
cd04de7f72 Order diffusion repositories by name (so Blender is at the top). 2013-11-14 19:44:47 +01:00
cf4b1317e1 Fix T37441: Could not assign tasks to self (via the "Assigned To" box)
Issue was caused by our database having login "watch" which is
apparently an object's method in firefox.

Added workaround for this into the code.
2013-11-14 21:24:26 +06:00
10e353b090 Allow anyone to login to developer.blender.org again. 2013-11-14 12:15:23 +01:00
81bd756ec6 Also correct sheband for svn auth script 2013-11-14 13:34:55 +06:00
9527d8aafd tweak to shebang so cron is happy with it 2013-11-14 13:31:50 +06:00
e35bc58e0e Fixes for gitosis admin script
Basically, pull wasn't happening correct and it was
updating files from CWD< not from workdir.
2013-11-14 12:44:59 +06:00
bd0f9fd913 Add sculpting and websites projects to welcome page. 2013-11-13 19:53:22 +01:00
44957f7806 Get repsitory name from svn URI
Would only work for repos inside svn.b.o.
Some further checks might be needed.
2013-11-14 00:21:04 +06:00
7ff26eb95d Show message that developer.blender.org is not open yet for logins. 2013-11-13 19:10:10 +01:00
1f2471fa67 Use git repository name from uri. not from repo name 2013-11-14 00:09:40 +06:00
7a5588a408 Appeared a typo in previous commmit
Didn't notice on system where had htaccess custom field.
2013-11-13 14:37:47 +06:00
ac03ae737f Fix for recent htaccess hack broke user registration
Issue was caused by custom fields loading will set
user's profile. In case user is new, this profile
will have title and blurb set to NULL, which is
unsupported.

Solved by setting title and blurb to an empty string
if setPassword detects that this is a new user.

tested with accountadin script, need to be tested
with online registration as well.
2013-11-13 14:35:29 +06:00
f9db95f555 Add a missing translations project member. 2013-11-13 09:06:25 +01:00
2bc045a997 * Add another duplicate email
* Remove addon testing tmp code
* Make files public viewable
2013-11-13 09:03:09 +01:00
531b0fa529 Added script to generate svn auth files
This script only generates content of either svnroot-access
or svnroot-authfile (depending on command line arguments).

It's not directly usable yet and would need some magic to
make it able to pass the data to svn.b.o. But this is up to
machines setup, not to the script.
2013-11-12 23:47:17 +06:00
6b1ed4fb9b Seems we need to load custom field manully 2013-11-12 23:46:10 +06:00
645a6a9f54 Made rebuild_gitadmin only take git repositories into account 2013-11-12 22:43:01 +06:00
88cd291b0f Only allow admins to login and disable new account registration.
This is a temporary change to avoid accidental interference during import tomorrow.
2013-11-12 14:55:36 +01:00
76e4aaf429 Import unix passwords for svn access, and fix passwrod/password typo. 2013-11-12 14:29:03 +01:00
365f8ad981 Added instructions about htaccess_passowrd_hash hidden field 2013-11-12 18:10:06 +06:00
0af08f9469 Added hack to user class to set htaccess hash when setting password
Uses hash generation from gforge code. Wouldn't work correct for
imported users yet.

TODO: Imported users are to use hash from projects.b.o's database.
2013-11-12 18:02:37 +06:00
23ce658af7 Made it possible to mark custom fields as hidden
it is done using "hidden": true setting in custom
field specification.

Hidden fields will never be displayed and their
intention is to be used by autohmatization scripts.
2013-11-12 18:02:37 +06:00
0a54474f98 Better Submit Addon page. 2013-11-11 21:00:30 +01:00
93ca9ed3a8 Update docs for migration 2013-11-12 00:58:04 +06:00
d110fdccc2 Added options to disable lint and unit tests in diffusion 2013-11-12 00:53:39 +06:00
4197d983bf Fix 404 after clicking Find Owners in diffusion, since we have this application disabled. 2013-11-11 17:49:03 +01:00
d23883b799 Update design task and todo task instructions. 2013-11-09 15:46:03 +01:00
675d2ac374 Link to addon docs on submit patch page. 2013-11-09 15:25:03 +01:00
5c86735ab7 On projects pages, add Submit Patch, Add To Do, Add Design Task links. It's all
a bit hardcoded but makes the expected workflow easier to understand.
2013-11-09 15:12:40 +01:00
566274dcac Patch/diff html pages updates. 2013-11-08 22:01:38 +01:00
de2814545b Add Submit Patch, Create Design Task and Create To Do actions in Maniphest when
browsing the corresponding.
2013-11-08 21:01:07 +01:00
4ea26f22c4 Add html instructions for diff/patch, todo and design tasks. 2013-11-08 20:55:53 +01:00
458bc7f921 Update task import script to handle addons. 2013-11-07 18:30:39 +01:00
3839698e4a Remove unnecessary whitespace. 2013-11-07 16:54:39 +01:00
b403863e62 Correction to documentation, extra bachslashes 2013-11-07 20:41:56 +06:00
246b73f922 Fix type in previous commit, sorry 2013-11-07 20:39:56 +06:00
6da7f462a9 Fix for documentation 2013-11-07 20:36:43 +06:00
90874b8b00 Links which goes to different site better open pages in new tab 2013-11-07 20:33:52 +06:00
7e874a33fb Added instructions to patch submission form. 2013-11-07 20:33:51 +06:00
bbe357e5c0 Add [developer.blender.org] in mail subject instead of only [Maniphest], [Diffusion], etc.
For casual users it's important to be able to see where the message comes from.
2013-11-07 20:33:51 +06:00
428cdae3cf Further tweaks to gitosis conf rebuild script
- Pull need SSH key as well
- Repository names are ensured to be lower case
- Use verbose name for commti author
2013-11-07 20:33:51 +06:00
1c689a6b24 Correct shebang for gitx-ssh 2013-11-07 20:33:51 +06:00
55972ef2c1 Gitadmin configuration now could be commited and pushed from update script 2013-11-07 20:33:51 +06:00
966687d1ab Project pages now have a Report Bug link, and View Tasks now uses the project
filter rather than setting up a query.
2013-11-07 20:33:51 +06:00
6a86144adf Another update to migration steps. 2013-11-07 20:33:51 +06:00
57765e88c0 Update migration steps with mailhook.
This commit also tests the mailhook itself, if all goes well.
2013-11-07 20:33:51 +06:00
60cddad047 Whitespace cleanup 2013-11-07 20:33:51 +06:00
a77a33dc50 Rework gitosis config generator to use pushable settings from repository 2013-11-07 20:33:51 +06:00
405a07e638 Made 'pushable' of repository editable for non-hosted repos as well 2013-11-07 20:33:51 +06:00
75f9ce9d77 Missed this in previous 'revert changes' commit 2013-11-07 20:33:50 +06:00
259588e747 Added script which rebuilds gitadmin configuration
It generates new gitosis.conf and public key files.
Actual commit to repo would likely be done with a
wrapper script which will run in cron.
2013-11-07 20:33:50 +06:00
0e8b746fb0 Tweaks to page and mail titles
- Welcome page will now have title "Blender Foundation: Welcome",
  the same as in old projects.b.o.
- Mail will be sent from name of BF, not phabricator, seems to
  be quite logical to do.
2013-11-07 20:33:50 +06:00
753917c10c Revert changes in AphrontFormPolicyControl.php
After recent Brecht's commit they're not needed.

Euh, didn't notice policies could be edited in configuration :(
2013-11-07 20:33:50 +06:00
39f7364f25 Tweaks to maniphest
- Remove quick links to create tasks, now only
  "Report Bug" to a specified project is allowed.
- Added 'Addons' to list of 'always visible'
  in navigation bar projects.
2013-11-07 20:33:50 +06:00
8d7de5fcb6 Tasks: don't force particular policy in the code here, let it be defined by the
default policies configured for maniphest.
2013-11-07 20:33:50 +06:00
01398f762b Better looks and css for welcome.html. For reference, __celerity_resource_map__.php
was updated with this command.

./scripts/celerity_mapper.php --with-custom webroot
2013-11-07 20:33:50 +06:00
e12d2efe81 Add buildbot and developer wiki links in the menu. 2013-11-07 20:33:23 +06:00
5c7055d840 Reshuffle order of builtin queries 2013-11-07 20:33:23 +06:00
562c7aa126 Use blender.org's favicon 2013-11-07 20:33:22 +06:00
5994088e50 Tweaks to welcome and bug report pages, making them a bit prettier and hopefully
more clear.
2013-11-07 20:33:22 +06:00
9edbe22e19 Update welcome.html with correct project IDs. 2013-11-07 20:33:22 +06:00
7fabfff397 Update migration steps with info from test run of importing to developer.blender.org. 2013-11-07 20:33:22 +06:00
356a2fe0e8 Rework task submission form
- It is possible now to submit tasks to specified project.
- All the extra fields which are not interesting got us
  are now hidden.
- Default visibility is User (maybe we might want
  "Everyone" in fact)?
- Only Administrators are able to edit issues by
  default.
- Links to bug report are available from welcome page
  and from project's maniphest page.
- Added file with report bug guidelines. Currently
  just copy-pasted it from project.b.o, some style
  tweaks are welcome.
2013-11-07 20:33:22 +06:00
54193ebb15 Add link to all types of tasks within single project 2013-11-07 20:33:22 +06:00
2b4bb9cddd Highlight current task type in side menu
So now Bug,Patch,etc categories are always visible
and active one is being highlighted.
2013-11-07 20:33:22 +06:00
2758907517 Add some new duplicate email users for migration. 2013-11-07 20:33:22 +06:00
a7f641eee2 Allow public access to main page, with login button in the top right, and show
activity feed on the main page.
2013-11-07 20:33:22 +06:00
9799ceff80 More fixes for migration, in particular for setting policies on projects and tasks. 2013-11-07 20:33:22 +06:00
26e86c2171 Add missing files and minor migration tweaks. 2013-11-07 20:33:22 +06:00
f6c293fb4d Migration tweaks, and patch to temporarily disable sending mails and updating feeds
during import of data.
2013-11-07 20:33:22 +06:00
5abc5cf9f8 Lots of little fixes for import, status should be imported mostly OK now.
A dded a migration_steps.txt that outlines the steps to migrate data.

Still todo:
* Extensions/addons, skipped now, will do next week
* Hide some unnecessary transactions
* Figure out policies for tasks and projects
* Test run over all tasks to see that they work
2013-11-07 20:33:22 +06:00
41a820fdf0 Tweak appearance of projects page to show description more prominent, and
minor tweaks to closed status and welcome html margins.
2013-11-07 20:33:22 +06:00
2c8b09da21 Welcome page tweaks (links are mostly broken, but shows proposed structure). 2013-11-07 20:33:22 +06:00
a7ff526360 Migration: add system to warn users with merged accounts to use the other account,
and provide an option to change the username to their choice after login.
2013-11-07 20:33:21 +06:00
1a8148be97 Correct link to blender bug tracker 2013-11-07 20:33:21 +06:00
199dd85140 Show project and task type in query result header
This is intended to make it more clear which task
types are currently being displayed.

Needed to revoke "final" modifier from class
PhabricatorApplicationSearchController and make
it use separate method to get description for
this.
2013-11-07 20:33:21 +06:00
f6c44fdb03 Hide inactive projects and add button to show them all
For now uses stupid hardcoded list of "interesting"
projects. Might be changed to something smarter later.
2013-11-07 20:33:21 +06:00
1aade72cb1 Add extra filter level to filter tasks by type 2013-11-07 20:33:21 +06:00
121c9d308b Fix migration script error due to changed phab API. 2013-11-07 20:33:21 +06:00
d60a47ab5b Add migration/dump to gitignore so it's not commited by accident 2013-11-07 20:33:21 +06:00
8af9b8796f Fkx for syntax error, unexpected T_OBJECT_OPERATOR 2013-11-07 20:33:21 +06:00
7dd7673fb3 Added per-project categories to the side bar of maniphest
Currently adds all the projects there, and at this moment
current project is not being highlighted, it's only get
displayed on the top anchor bar.

TODO:
- We would probably wouldn't want all the projects there,
  need to add some filter there.
- Make it ore clear which project is currently active.
2013-11-07 20:33:21 +06:00
aeaf0902e1 Migration scripts in somewhat better state now, main missing part is that statuses
are not imported correctly, though there's a bunch of details to figure out.
2013-11-07 20:33:21 +06:00
498842475c Initial scripts for migration of data from gforge to phabricator.
Import of tasks is still a hacked together mess from before I figured out the
structure that we want.
2013-11-07 20:33:21 +06:00
755177508e Modify LiskDAO to support overriding ID and dates, used for import of data. 2013-11-07 20:33:21 +06:00
5b49fd93e2 Don't show edit button for tasks if editing is not allowed 2013-11-07 20:33:21 +06:00
968ea35b03 Use blender logo in header 2013-11-07 20:33:21 +06:00
97ed90b82a Fix for tiy typo in previous commit 2013-11-07 20:33:21 +06:00
ba34aa535a Move custom login form text to an html file
Also committing all the template files needed for
making phabricator closer to how our gforge looks.
2013-11-07 20:33:21 +06:00
e56041da3b Hide "Create Project" if it's not allowed for current user
Having a button which says "You are not allowed to press it"
is pretty much strange behavior. Better not to have such button
at first place.

For now it only affects Projects application. There're also
other places where we might want this change.
2013-11-07 20:33:20 +06:00
b19fbc39af Modification so we can import gforge passwords, by adding an extra md5 to the
password hash. By skipping this step on import, we keep passwords working.
2013-11-07 20:33:20 +06:00
1036d419fa Add "Archived" status for closing tasks. 2013-11-07 20:33:20 +06:00
0011789443 Added welcome.file setting
This setting operates quite the same as welcome.html
except for the difference that it points to a file
from which to get the HTML code.

It's more convenient to use file with HTML code if
one need to display rather long welcome screen.
2013-11-07 20:33:20 +06:00
ff7d71fb87 Make install_ubuntu.sh work for Debian as well 2013-11-07 20:33:20 +06:00
151 changed files with 5377 additions and 244 deletions

View File

@@ -1,5 +1,5 @@
{
"phabricator.uri": "https://secure.phabricator.com/",
"phabricator.uri": "https://developer.blender.org/",
"load": ["src/"],
"history.immutable": false
}

3
.gitignore vendored
View File

@@ -40,3 +40,6 @@
# Places for users to add custom resources.
/resources/cows/custom/*
/resources/figlet/custom/*
# blender migration files
migration/dump/

610
migration/dedup.php Normal file
View File

@@ -0,0 +1,610 @@
<?php
$migrate_dedup_users = array();
$migrate_dedup_users["midiclub"] = "midclub";
$migrate_dedup_users["trip"] = "car";
$migrate_dedup_users["thunderbolt"] = "thunderbolt16";
$migrate_dedup_users["avirnig"] = "beav";
$migrate_dedup_users["jeaninmontreal"] = "jeanm";
$migrate_dedup_users["nneo"] = "nneonneo";
$migrate_dedup_users["ebonyj"] = "jim";
$migrate_dedup_users["tnr"] = "ichem";
$migrate_dedup_users["archus"] = "rstehwien";
$migrate_dedup_users["kalysto"] = "kalar";
$migrate_dedup_users["eloe"] = "mouvanteloe";
$migrate_dedup_users["erdling"] = "eitj";
$migrate_dedup_users["cwinebrinner"] = "chuck_1027";
$migrate_dedup_users["foo"] = "mfranz";
$migrate_dedup_users["f00fbug"] = "viviowns";
$migrate_dedup_users["olavbalm"] = "olav";
$migrate_dedup_users["kapong"] = "el_kapong";
$migrate_dedup_users["thorax"] = "rofthorax";
$migrate_dedup_users["kramer3d"] = "asdfghytrewq";
$migrate_dedup_users["reevee"] = "vee";
$migrate_dedup_users["matzeb"] = "matzebraun";
$migrate_dedup_users["jmsoler"] = "jms";
$migrate_dedup_users["aqa"] = "angelito";
$migrate_dedup_users["blendorphin"] = "blenergetic";
$migrate_dedup_users["paolo"] = "jody";
$migrate_dedup_users["blendedidea"] = "chubango";
$migrate_dedup_users["ruiramos"] = "p3ctu5";
$migrate_dedup_users["head_chees"] = "vassilizaitsaf";
$migrate_dedup_users["kiernan"] = "rofthorax";
$migrate_dedup_users["olaf_arnold"] = "olafarnold";
$migrate_dedup_users["joseyanesaltos"] = "joseyanes";
$migrate_dedup_users["nicholasfrancis"] = "nicholas";
$migrate_dedup_users["briancary"] = "brinux";
$migrate_dedup_users["piotrek"] = "ccpiotr";
$migrate_dedup_users["slashdev"] = "colonel_panic";
$migrate_dedup_users["rj2004"] = "rjblender";
$migrate_dedup_users["jeffreymcgrew"] = "toast";
$migrate_dedup_users["hendersj"] = "jhenderson";
$migrate_dedup_users["pierpy"] = "pier";
$migrate_dedup_users["buschhardt"] = "ishtar";
$migrate_dedup_users["timlesher"] = "tim";
$migrate_dedup_users["tizmo"] = "timlucas";
$migrate_dedup_users["pprandin"] = "pashaweb";
$migrate_dedup_users["servivo"] = "taz";
$migrate_dedup_users["stabby"] = "xingo";
$migrate_dedup_users["jimmydietulpe"] = "jimmadietulpe";
$migrate_dedup_users["palmnet"] = "palmer";
$migrate_dedup_users["graphique-chti"] = "gcprod";
$migrate_dedup_users["dreamkatana1"] = "dreamkatana";
$migrate_dedup_users["wolverine"] = "shane";
$migrate_dedup_users["schwarz"] = "wene";
$migrate_dedup_users["justtesting"] = "levon";
$migrate_dedup_users["erwin_xnan"] = "erwin";
$migrate_dedup_users["zack"] = "krystof";
$migrate_dedup_users["fabinator31"] = "fab31";
$migrate_dedup_users["themilkman"] = "cliftonium";
$migrate_dedup_users["etiennel"] = "choupi";
$migrate_dedup_users["m_i_c_h_e_l"] = "michaels";
$migrate_dedup_users["techrolla"] = "muffinpeddler";
$migrate_dedup_users["fireflymantis"] = "twilight";
$migrate_dedup_users["pinucset0"] = "pinucset";
$migrate_dedup_users["franzrogar"] = "blender-i18n-po";
$migrate_dedup_users["pinucset1"] = "pinucset";
$migrate_dedup_users["pinucset3"] = "pinucset";
$migrate_dedup_users["threeddream"] = "x-axis";
$migrate_dedup_users["mudbot"] = "laurence";
$migrate_dedup_users["ligeyx"] = "ligey";
$migrate_dedup_users["dreas"] = "dre";
$migrate_dedup_users["joorvapl"] = "joorva";
$migrate_dedup_users["voyage"] = "xenithi";
$migrate_dedup_users["azter"] = "azterix";
$migrate_dedup_users["lapinbleu"] = "simeon";
$migrate_dedup_users["emmanuel_t"] = "emmanuel";
$migrate_dedup_users["cricket"] = "gku";
$migrate_dedup_users["justanumber"] = "mad4linux";
$migrate_dedup_users["johnnyen"] = "johnny";
$migrate_dedup_users["leiota"] = "marcopolo";
$migrate_dedup_users["blackstorm"] = "ikbendirk";
$migrate_dedup_users["richie"] = "ligey";
$migrate_dedup_users["mrcarnivore2"] = "mrcarnivore";
$migrate_dedup_users["muddym1nd"] = "muddymind";
$migrate_dedup_users["eumesmo"] = "vasco_da_gama";
$migrate_dedup_users["ph-kby"] = "olav";
$migrate_dedup_users["piotrek_"] = "ccpiotr";
$migrate_dedup_users["joaquin"] = "prospero";
$migrate_dedup_users["konrad_haenel"] = "konrad8ha";
$migrate_dedup_users["benstabler"] = "lightning";
$migrate_dedup_users["gustav"] = "draknoid";
$migrate_dedup_users["slikdigit"] = "bassamk";
$migrate_dedup_users["karlerlandsen"] = "lethalsidep";
$migrate_dedup_users["djwillmsoh"] = "djw1";
$migrate_dedup_users["aschmitz"] = "root_42";
$migrate_dedup_users["malfunc"] = "mcq";
$migrate_dedup_users["m_jack"] = "jack";
$migrate_dedup_users["davey"] = "madcow";
$migrate_dedup_users["iraytrace"] = "butler";
$migrate_dedup_users["duser"] = "mslechols";
$migrate_dedup_users["akito"] = "ton";
$migrate_dedup_users["jochenschmitt"] = "s4504kr";
$migrate_dedup_users["digikiller"] = "ace1";
$migrate_dedup_users["shzhc"] = "zzzz";
$migrate_dedup_users["cyrilbrulebois"] = "kibi";
$migrate_dedup_users["themushroom"] = "draknoid";
$migrate_dedup_users["zinkmaster"] = "mariolink";
$migrate_dedup_users["ashsid"] = "ash";
$migrate_dedup_users["novato"] = "jimenez";
$migrate_dedup_users["jadie_p"] = "jadie";
$migrate_dedup_users["neshshah007"] = "neshrai";
$migrate_dedup_users["ryanshow"] = "tankcoder";
$migrate_dedup_users["squarelinesq"] = "squareline";
$migrate_dedup_users["virginijus"] = "ernestas1994";
$migrate_dedup_users["renderdemon"] = "pnio";
$migrate_dedup_users["kwab"] = "kobi";
$migrate_dedup_users["peterjonckheere"] = "jonckheerep";
$migrate_dedup_users["vidar"] = "vidarino";
$migrate_dedup_users["sapjohannes"] = "johannesje";
$migrate_dedup_users["youri"] = "ayers";
$migrate_dedup_users["theamiman"] = "amiman";
$migrate_dedup_users["chrisg_ksi"] = "red_planet";
$migrate_dedup_users["blenderorgfan"] = "franciscosilva";
$migrate_dedup_users["ericd"] = "ericdrayer";
$migrate_dedup_users["asdfghjkl2"] = "asdfghjkl";
$migrate_dedup_users["quorn"] = "alienit";
$migrate_dedup_users["daan221"] = "phoenix221";
$migrate_dedup_users["user"] = "mslechols";
$migrate_dedup_users["pyb"] = "lomperillo";
$migrate_dedup_users["g56"] = "gwald";
$migrate_dedup_users["ausland"] = "vots";
$migrate_dedup_users["quillinan"] = "orinoco";
$migrate_dedup_users["t3tsuj1n"] = "bootsheoz";
$migrate_dedup_users["molflesh"] = "melflash";
$migrate_dedup_users["rickta59"] = "aerobicsboy";
$migrate_dedup_users["nolopoly"] = "lopoly";
$migrate_dedup_users["jeel"] = "jl57";
$migrate_dedup_users["brianmccumber2"] = "brianmccumber";
$migrate_dedup_users["mouette"] = "moutte";
$migrate_dedup_users["wout"] = "wonderingwout";
$migrate_dedup_users["fatfinger"] = "mattyc";
$migrate_dedup_users["nathangull"] = "nateg";
$migrate_dedup_users["tampadave"] = "dkmweeks";
$migrate_dedup_users["sausages"] = "lethargic";
$migrate_dedup_users["chris3d"] = "chrisbd";
$migrate_dedup_users["kaito"] = "ton";
$migrate_dedup_users["akirasan"] = "akira_b";
$migrate_dedup_users["fiddle"] = "rayf";
$migrate_dedup_users["bald"] = "manu";
$migrate_dedup_users["mistermelquin"] = "melquin";
$migrate_dedup_users["kofish"] = "kingdomoffish";
$migrate_dedup_users["onanj"] = "orangee";
$migrate_dedup_users["jasoncarrier"] = "jason";
$migrate_dedup_users["joelgodin"] = "jenniferblender";
$migrate_dedup_users["oranj"] = "orangee";
$migrate_dedup_users["schdeb"] = "schmidtcristian";
$migrate_dedup_users["bastian"] = "angerb";
$migrate_dedup_users["patko"] = "patco";
$migrate_dedup_users["arakyd666"] = "arakyd";
$migrate_dedup_users["karimf"] = "rim-k";
$migrate_dedup_users["nletwory"] = "jestertestest";
$migrate_dedup_users["mansoorhyder"] = "mansoor";
$migrate_dedup_users["rocketmagnet"] = "steventr";
$migrate_dedup_users["thekernal"] = "kernal";
$migrate_dedup_users["satom"] = "satriatomat";
$migrate_dedup_users["a624"] = "a623";
$migrate_dedup_users["jldavilacasares"] = "muki";
$migrate_dedup_users["segersj"] = "segers";
$migrate_dedup_users["hoisan49"] = "hoisan";
$migrate_dedup_users["j_bessette"] = "linuxpimp20";
$migrate_dedup_users["andreas999"] = "andreas";
$migrate_dedup_users["dusan"] = "dsc512";
$migrate_dedup_users["dx-mon"] = "mantr100";
$migrate_dedup_users["ilislab"] = "ids";
$migrate_dedup_users["rben"] = "raybenjamin";
$migrate_dedup_users["sphere"] = "dysonsphere";
$migrate_dedup_users["highlife22"] = "highlife";
$migrate_dedup_users["yonarw"] = "yona";
$migrate_dedup_users["kryptic89"] = "kryptic";
$migrate_dedup_users["axelp"] = "axel";
$migrate_dedup_users["perebalsach"] = "fog22";
$migrate_dedup_users["alogerson"] = "gerson";
$migrate_dedup_users["cotejrp"] = "cotejrp1";
$migrate_dedup_users["tak"] = "carlosjamesr";
$migrate_dedup_users["ziddy"] = "anishchandran";
$migrate_dedup_users["asdgz"] = "blenderiseur";
$migrate_dedup_users["cdated"] = "cdated257";
$migrate_dedup_users["jayrkalugin"] = "jayr";
$migrate_dedup_users["zeemzoet"] = "johannesje";
$migrate_dedup_users["duo"] = "ambyra";
$migrate_dedup_users["philb"] = "chewbacca";
$migrate_dedup_users["tzi"] = "izt";
$migrate_dedup_users["squirrelthetire"] = "squirrel-tire";
$migrate_dedup_users["anwyn"] = "sugarshark";
$migrate_dedup_users["a2z"] = "a2zaa";
$migrate_dedup_users["fxrex"] = "femi";
$migrate_dedup_users["alethewiz"] = "mfaso68";
$migrate_dedup_users["noseferrit"] = "billybong";
$migrate_dedup_users["fcali"] = "fabz";
$migrate_dedup_users["bbirchler"] = "bblender";
$migrate_dedup_users["oslosewers"] = "oslo";
$migrate_dedup_users["wtrsltnk"] = "wtr";
$migrate_dedup_users["cspohst"] = "spohst";
$migrate_dedup_users["warhawk08"] = "warhawk1990";
$migrate_dedup_users["magick_crow"] = "magickcrow";
$migrate_dedup_users["guillaumem"] = "guillaume";
$migrate_dedup_users["jwitthuhn"] = "rahu";
$migrate_dedup_users["fmehigan"] = "frank_me";
$migrate_dedup_users["ilissys"] = "ids";
$migrate_dedup_users["supermoaaa"] = "moaaa";
$migrate_dedup_users["nwmatt"] = "mhenley";
$migrate_dedup_users["bezel"] = "xshell";
$migrate_dedup_users["rebuss"] = "studioa";
$migrate_dedup_users["geonom"] = "geoadel";
$migrate_dedup_users["seldan"] = "farakon";
$migrate_dedup_users["kuru76"] = "kcorbin";
$migrate_dedup_users["kapil"] = "kapilbedarkar";
$migrate_dedup_users["henryiii"] = "henryschreiner";
$migrate_dedup_users["pateamcarl"] = "carlhuth";
$migrate_dedup_users["kamen"] = "bigbob1993";
$migrate_dedup_users["olddemon"] = "old_demon";
$migrate_dedup_users["draklaw2"] = "draklaw";
$migrate_dedup_users["ksdlee"] = "kdlee";
$migrate_dedup_users["xource"] = "admix";
$migrate_dedup_users["invertednormal"] = "smokebox46and2";
$migrate_dedup_users["feelgoodcomics"] = "onlygoodwin";
$migrate_dedup_users["glorund"] = "undolaure";
$migrate_dedup_users["soulofsound"] = "johnnym";
$migrate_dedup_users["ghigi123"] = "ghigi";
$migrate_dedup_users["stefanvoigthpi"] = "derstefan";
$migrate_dedup_users["dblenderv"] = "default";
$migrate_dedup_users["ophiocus"] = "oneliner";
$migrate_dedup_users["colleywrks"] = "colley";
$migrate_dedup_users["fogy"] = "fog22";
$migrate_dedup_users["vidarn"] = "bida70";
$migrate_dedup_users["kevin"] = "goblender2541";
$migrate_dedup_users["tisachris"] = "warflight";
$migrate_dedup_users["personalex2"] = "personalex";
$migrate_dedup_users["polypa"] = "lile";
$migrate_dedup_users["i4dnf"] = "emilian";
$migrate_dedup_users["nitalleb"] = "singleman";
$migrate_dedup_users["tcgodoy"] = "godoy";
$migrate_dedup_users["joorva_pl"] = "joorva";
$migrate_dedup_users["sex"] = "xest";
$migrate_dedup_users["chipmunk"] = "ignatz";
$migrate_dedup_users["schalmagne"] = "chalmagne";
$migrate_dedup_users["michalziulek"] = "eneida";
$migrate_dedup_users["jeeps"] = "jeepster";
$migrate_dedup_users["yain"] = "chaos";
$migrate_dedup_users["amadio"] = "marble";
$migrate_dedup_users["javiere"] = "javierchavez";
$migrate_dedup_users["drmzperx"] = "mzperx";
$migrate_dedup_users["sebastianreaser"] = "sebastian0";
$migrate_dedup_users["idolon"] = "spadija";
$migrate_dedup_users["alanhzhcn"] = "alanhzh";
$migrate_dedup_users["jeanc"] = "jean";
$migrate_dedup_users["transblue2"] = "transblue";
$migrate_dedup_users["cesarwilfredo"] = "cesar";
$migrate_dedup_users["nspyr"] = "spiderfire";
$migrate_dedup_users["supermegamoaaa"] = "moaaa";
$migrate_dedup_users["firetiger"] = "opensolution";
$migrate_dedup_users["skarg"] = "cados";
$migrate_dedup_users["realheadcrusher"] = "danigr";
$migrate_dedup_users["kpg"] = "nihylius";
$migrate_dedup_users["tft"] = "tft67";
$migrate_dedup_users["storabbarn"] = "morre";
$migrate_dedup_users["bacurau"] = "roger_roo";
$migrate_dedup_users["alisari"] = "parasoley";
$migrate_dedup_users["skiski"] = "superrom";
$migrate_dedup_users["halfninja"] = "nickh";
$migrate_dedup_users["drell_develop"] = "drellex";
$migrate_dedup_users["highlif3"] = "highlife";
$migrate_dedup_users["broggsim1"] = "broggsim";
$migrate_dedup_users["blendermanuci"] = "yunior88";
$migrate_dedup_users["jpt9"] = "jtuttle";
$migrate_dedup_users["farrer"] = "farpro";
$migrate_dedup_users["badcheez"] = "randall";
$migrate_dedup_users["leewj_"] = "lohns";
$migrate_dedup_users["martin107"] = "martinfrances";
$migrate_dedup_users["dedpan"] = "tberghuis";
$migrate_dedup_users["whiterabbit"] = "dreamscapearts";
$migrate_dedup_users["shuvro"] = "shuvro05";
$migrate_dedup_users["anichandru"] = "anishchandran";
$migrate_dedup_users["ncaralph"] = "ralphdoctorow";
$migrate_dedup_users["nlongchamps"] = "nlong";
$migrate_dedup_users["mawi37"] = "mawi";
$migrate_dedup_users["rizla"] = "jay";
$migrate_dedup_users["jeh"] = "mirkril";
$migrate_dedup_users["b-fighter"] = "fanatic";
$migrate_dedup_users["wasamonkey"] = "wasa";
$migrate_dedup_users["nicola"] = "martin45";
$migrate_dedup_users["method-es"] = "method";
$migrate_dedup_users["pablow"] = "warhole";
$migrate_dedup_users["alanishzh"] = "alanhzh";
$migrate_dedup_users["thunder947"] = "thunder";
$migrate_dedup_users["yijimi"] = "roler";
$migrate_dedup_users["jaydenb"] = "logidude";
$migrate_dedup_users["leandropolus"] = "leandrosz";
$migrate_dedup_users["ibi002"] = "ibi001";
$migrate_dedup_users["hakanortasoz"] = "tayfax";
$migrate_dedup_users["enur"] = "rune";
$migrate_dedup_users["dsuesse"] = "qiip";
$migrate_dedup_users["bipedlaboratory"] = "redmetal";
$migrate_dedup_users["codeyhanson"] = "codey";
$migrate_dedup_users["alphonso_b"] = "alfonso_b";
$migrate_dedup_users["surreal6"] = "carlospadial";
$migrate_dedup_users["kralizek"] = "kral";
$migrate_dedup_users["kfrechet"] = "keithfr";
$migrate_dedup_users["jwedlake"] = "joshwedlake";
$migrate_dedup_users["westie630"] = "bully";
$migrate_dedup_users["fictional"] = "icefire";
$migrate_dedup_users["zelozelos"] = "zelozelos1";
$migrate_dedup_users["dragonlord"] = "acuena";
$migrate_dedup_users["mrcheese"] = "jpeg";
$migrate_dedup_users["willemverwey"] = "dandandan";
$migrate_dedup_users["jhed"] = "anton_foy";
$migrate_dedup_users["treacy1077"] = "briant";
$migrate_dedup_users["xest"] = "xembie";
$migrate_dedup_users["cyphl25"] = "jmsfreezer";
$migrate_dedup_users["wynk"] = "wynn";
$migrate_dedup_users["trock2957"] = "trock";
$migrate_dedup_users["mr_bomb"] = "carter24";
$migrate_dedup_users["nikolaus"] = "tortellini";
$migrate_dedup_users["pegasus_001"] = "pegasus001";
$migrate_dedup_users["fayte"] = "fayte220";
$migrate_dedup_users["jagang_8"] = "jagang";
$migrate_dedup_users["thetwom"] = "moe";
$migrate_dedup_users["kevlareditor"] = "klthomas";
$migrate_dedup_users["damien_deom"] = "dams";
$migrate_dedup_users["reynantem"] = "reynante";
$migrate_dedup_users["hiralm01"] = "hiralm";
$migrate_dedup_users["radix7"] = "wyldethang";
$migrate_dedup_users["puppetm"] = "puppetmaster";
$migrate_dedup_users["vimax"] = "vimaxus";
$migrate_dedup_users["mozzy69"] = "lyndon";
$migrate_dedup_users["vitranaccad"] = "thestorm74";
$migrate_dedup_users["kj12345"] = "kevinjames";
$migrate_dedup_users["foinix"] = "mrnoodle";
$migrate_dedup_users["shizu"] = "sntulix";
$migrate_dedup_users["kukulcangod23"] = "kukulcangod";
$migrate_dedup_users["piliq"] = "qpblendpolis";
$migrate_dedup_users["benvad"] = "vbenny";
$migrate_dedup_users["fgribben"] = "sharkey";
$migrate_dedup_users["makospince"] = "mako_spince";
$migrate_dedup_users["ablenderuser"] = "pancakeface";
$migrate_dedup_users["axelphi"] = "axel";
$migrate_dedup_users["josiasbh"] = "josias";
$migrate_dedup_users["mattsix"] = "majawe";
$migrate_dedup_users["duarte_ramos"] = "dphantom";
$migrate_dedup_users["killogge"] = "muraj";
$migrate_dedup_users["luka"] = "omgwtfbbq";
$migrate_dedup_users["chromemonkey"] = "brian651msp";
$migrate_dedup_users["e_d_i"] = "ide";
$migrate_dedup_users["mrhaynesy"] = "haynesy";
$migrate_dedup_users["imagineering"] = "imagineer";
$migrate_dedup_users["virgiliovasconc"] = "virgilio";
$migrate_dedup_users["blenderlb57"] = "louigi";
$migrate_dedup_users["nick65"] = "dgnicola";
$migrate_dedup_users["mmatthews"] = "mamatthews";
$migrate_dedup_users["gerwood"] = "arilian";
$migrate_dedup_users["xsidmax"] = "xsi";
$migrate_dedup_users["mix-yag"] = "aynahsim";
$migrate_dedup_users["wpthomas"] = "tallguy";
$migrate_dedup_users["bp007"] = "bender007";
$migrate_dedup_users["emach"] = "eon4blender";
$migrate_dedup_users["alfclement"] = "alfc";
$migrate_dedup_users["blenderwell"] = "goplexian";
$migrate_dedup_users["asebastianr"] = "sebastian0";
$migrate_dedup_users["joepal1976"] = "joepal";
$migrate_dedup_users["chertov"] = "lestat";
$migrate_dedup_users["djela63"] = "jerominovich";
$migrate_dedup_users["lppinto"] = "lpciper";
$migrate_dedup_users["prana"] = "nomath";
$migrate_dedup_users["sarubadoru"] = "salvador";
$migrate_dedup_users["rarebit"] = "rawstar7";
$migrate_dedup_users["hikikamori"] = "hikkikamori";
$migrate_dedup_users["mrduke"] = "drop";
$migrate_dedup_users["deetee"] = "dertee";
$migrate_dedup_users["woooooah"] = "noxwell";
$migrate_dedup_users["macoss"] = "ossmac";
$migrate_dedup_users["bunnyboy212"] = "blender_buddie";
$migrate_dedup_users["maxgrip"] = "czarek";
$migrate_dedup_users["tentonman"] = "titandtat";
$migrate_dedup_users["jabozzo"] = "bozzo";
$migrate_dedup_users["reinways"] = "reinw";
$migrate_dedup_users["petergk"] = "nihylius";
$migrate_dedup_users["zphr3000"] = "zphr";
$migrate_dedup_users["ruivo"] = "andreh";
$migrate_dedup_users["kosta"] = "kgd";
$migrate_dedup_users["delter"] = "dertee";
$migrate_dedup_users["jmiller"] = "lethargic";
$migrate_dedup_users["dealga"] = "zeffii";
$migrate_dedup_users["bogey"] = "daveh";
$migrate_dedup_users["silencebe"] = "silence";
$migrate_dedup_users["temozarela"] = "gorn";
$migrate_dedup_users["tischite"] = "greenbutton";
$migrate_dedup_users["buisson"] = "dinodino";
$migrate_dedup_users["cfox"] = "colinfox";
$migrate_dedup_users["hunkadoodle"] = "hunkadoodledoo";
$migrate_dedup_users["jlwitthuhn"] = "rahu";
$migrate_dedup_users["hvfrancesco"] = "hva";
$migrate_dedup_users["hazim-jamal"] = "hazim1";
$migrate_dedup_users["aurosutru"] = "tlm";
$migrate_dedup_users["pierrea"] = "pier2";
$migrate_dedup_users["zoon"] = "zoonpolygonikon";
$migrate_dedup_users["gruntbatch"] = "carmichael";
$migrate_dedup_users["petru"] = "virusanti";
$migrate_dedup_users["mikeh74"] = "mikeh";
$migrate_dedup_users["sugoi"] = "juntunen";
$migrate_dedup_users["bartje"] = "bartart3d";
$migrate_dedup_users["yaoyansi"] = "yaoyansi2";
$migrate_dedup_users["rafek"] = "rafek_finearts";
$migrate_dedup_users["caspern"] = "caspernilsson";
$migrate_dedup_users["lee"] = "s_random";
$migrate_dedup_users["sparky"] = "mmikkelsen";
$migrate_dedup_users["wigglyframes"] = "rene";
$migrate_dedup_users["kroni"] = "kronos";
$migrate_dedup_users["xgl_asyliax"] = "xglasyliax";
$migrate_dedup_users["blendeador"] = "luisperosio";
$migrate_dedup_users["kaos1986"] = "kaos86";
$migrate_dedup_users["adamdoyle"] = "advs89";
$migrate_dedup_users["kahenraz"] = "mistrel";
$migrate_dedup_users["ccliffe"] = "cjcliffe";
$migrate_dedup_users["nullfied"] = "xercesblue";
$migrate_dedup_users["dustyghost"] = "dustbin1_uk";
$migrate_dedup_users["claaskuhnen"] = "cekuhnendev";
$migrate_dedup_users["vercingetorix"] = "diamond_rust";
$migrate_dedup_users["plugboy"] = "centerlaw";
$migrate_dedup_users["rben13"] = "raybenjamin";
$migrate_dedup_users["deangiberson"] = "voidptr";
$migrate_dedup_users["makeitwork"] = "bboybram";
$migrate_dedup_users["iljosli"] = "jos";
$migrate_dedup_users["slowan"] = "slovan";
$migrate_dedup_users["mooonwalkercz"] = "mooonwalker";
$migrate_dedup_users["tapplek"] = "tapple";
$migrate_dedup_users["blendmond"] = "cornix";
$migrate_dedup_users["giorgiomartini"] = "tweakingknobs";
$migrate_dedup_users["davidray"] = "deadman";
$migrate_dedup_users["justthisguy"] = "nyctef";
$migrate_dedup_users["logobar"] = "freyer";
$migrate_dedup_users["zooo"] = "leon_cheung";
$migrate_dedup_users["josiasalexandre"] = "josias";
$migrate_dedup_users["tsukiko_chan"] = "tsukikochan";
$migrate_dedup_users["akira_san"] = "akira_b";
$migrate_dedup_users["walberti"] = "walbertievarist";
$migrate_dedup_users["astro"] = "tnboma";
$migrate_dedup_users["mccx"] = "mcq";
$migrate_dedup_users["daa84"] = "daa";
$migrate_dedup_users["sivert3"] = "cent";
$migrate_dedup_users["twentyone"] = "glade";
$migrate_dedup_users["endi2"] = "endi";
$migrate_dedup_users["jamesr"] = "james_r";
$migrate_dedup_users["reece"] = "reecerobinson";
$migrate_dedup_users["dustractor"] = "bpygrams";
$migrate_dedup_users["pencilhead"] = "pencil-head";
$migrate_dedup_users["toml"] = "tomol";
$migrate_dedup_users["colinm"] = "tablaman";
$migrate_dedup_users["blendphys2"] = "blendphys";
$migrate_dedup_users["xgoff"] = "zzyxz";
$migrate_dedup_users["coleingraham"] = "coledingraham";
$migrate_dedup_users["danielvmacedo"] = "skul3r";
$migrate_dedup_users["burster"] = "przemaz";
$migrate_dedup_users["tung"] = "tungster";
$migrate_dedup_users["chessie"] = "blackcatt";
$migrate_dedup_users["foxdog"] = "rubbernuke";
$migrate_dedup_users["mordachai"] = "gus";
$migrate_dedup_users["chilamlai"] = "cllai";
$migrate_dedup_users["sliders34"] = "sliders";
$migrate_dedup_users["benji852"] = "benjamin852";
$migrate_dedup_users["bebinalpha"] = "bebin";
$migrate_dedup_users["mr78"] = "alexandr";
$migrate_dedup_users["avirillion"] = "tarion";
$migrate_dedup_users["matthiasro"] = "matthias_r";
$migrate_dedup_users["debearseax"] = "seogeniuss";
$migrate_dedup_users["karja"] = "trockenfrosch";
$migrate_dedup_users["rojuinex"] = "ifrit";
$migrate_dedup_users["bernardo"] = "dados";
$migrate_dedup_users["ddeclara"] = "decden";
$migrate_dedup_users["zm_sansan"] = "sansan";
$migrate_dedup_users["useless"] = "cortot";
$migrate_dedup_users["tymnclono"] = "sooccatly";
$migrate_dedup_users["rodrigo_b"] = "rodrigob";
$migrate_dedup_users["shnurui"] = "spinster";
$migrate_dedup_users["michalisz"] = "michaliszissiou";
$migrate_dedup_users["fbbdev"] = "babboide";
$migrate_dedup_users["tjackson"] = "tjonline";
$migrate_dedup_users["ramaswamy"] = "ramaswamysriram";
$migrate_dedup_users["allrod5"] = "rodblender";
$migrate_dedup_users["qcp"] = "qpblendpolis";
$migrate_dedup_users["ftsf"] = "thesleepless";
$migrate_dedup_users["umagoo2012"] = "umagoo";
$migrate_dedup_users["raven"] = "rune";
$migrate_dedup_users["hsaito"] = "integer";
$migrate_dedup_users["paulthegreat"] = "digitalpyro";
$migrate_dedup_users["capheen"] = "dval";
$migrate_dedup_users["rskinner"] = "rws";
$migrate_dedup_users["gregstein"] = "gregorein";
$migrate_dedup_users["matty686"] = "matty";
$migrate_dedup_users["selby_rowley"] = "selby";
$migrate_dedup_users["shembolstudio"] = "natadams8";
$migrate_dedup_users["grenzfrequence"] = "goatrance";
$migrate_dedup_users["stephan"] = "schdeffan";
$migrate_dedup_users["axis33"] = "dsc512";
$migrate_dedup_users["redandfish"] = "red-fish";
$migrate_dedup_users["artsapcemedia"] = "arzpace";
$migrate_dedup_users["artspacemedia"] = "arzpace";
$migrate_dedup_users["mccmcc"] = "mcq";
$migrate_dedup_users["seocitterx"] = "mediabuy";
$migrate_dedup_users["lightning_limn"] = "lightning4";
$migrate_dedup_users["omarlakhdar"] = "archimage";
$migrate_dedup_users["regeleionescu"] = "regele";
$migrate_dedup_users["mitchell_decker"] = "michealikruhara";
$migrate_dedup_users["joselebon"] = "jl57";
$migrate_dedup_users["simonbroggi"] = "broggsim";
$migrate_dedup_users["inwadnepe"] = "ceapbatatry";
$migrate_dedup_users["ehobjman"] = "resbsp";
$migrate_dedup_users["davelassanske"] = "dolby411";
$migrate_dedup_users["jsu"] = "jansub";
$migrate_dedup_users["agricola"] = "agricola1";
$migrate_dedup_users["bartoszek"] = "bartus";
$migrate_dedup_users["captainoblivion"] = "cptoblivion";
$migrate_dedup_users["alexmcourt"] = "personalex";
$migrate_dedup_users["jmsprss"] = "xonar";
$migrate_dedup_users["awarnock"] = "salsa";
$migrate_dedup_users["mcc2"] = "mcq";
$migrate_dedup_users["psyborg042"] = "psyborg";
$migrate_dedup_users["ushiproject"] = "ushi";
$migrate_dedup_users["mrjimmy"] = "mrjimmyos";
$migrate_dedup_users["thefinalcut"] = "tlousky";
$migrate_dedup_users["startheshadow"] = "star";
$migrate_dedup_users["axredneck"] = "redneck";
$migrate_dedup_users["phimestudio"] = "phime";
$migrate_dedup_users["dwatts1"] = "dlax";
$migrate_dedup_users["rertjoi"] = "rertjwi";
$migrate_dedup_users["erdjkgh"] = "rertjwi";
$migrate_dedup_users["libertainsrg"] = "fcougar";
$migrate_dedup_users["godling72"] = "dmelchio";
$migrate_dedup_users["myclay"] = "thenewone";
$migrate_dedup_users["ecaspersen"] = "ecasper";
$migrate_dedup_users["driewiel"] = "driesiedriewiel";
$migrate_dedup_users["bhupen"] = "bhupendra";
$migrate_dedup_users["caosdoar"] = "mailoyo";
$migrate_dedup_users["polyspin"] = "butler";
$migrate_dedup_users["qalb_al_aqrab"] = "efimpetelin";
$migrate_dedup_users["fdfdfdfffd"] = "fcougar";
$migrate_dedup_users["brianlockett"] = "macrow";
$migrate_dedup_users["claude"] = "coco";
$migrate_dedup_users["mattostgard"] = "drflail";
$migrate_dedup_users["cekuhnen_new"] = "cekuhnendev";
$migrate_dedup_users["kirill_lukyanov"] = "kirill";
$migrate_dedup_users["jan-eric"] = "janeric96";
$migrate_dedup_users["daniel_h"] = "dhoughto";
$migrate_dedup_users["raphaelbarros"] = "thebigheadone";
$migrate_dedup_users["salas"] = "tychota";
$migrate_dedup_users["danieljsamson"] = "techfix";
$migrate_dedup_users["vinagrito"] = "aechemendia";
$migrate_dedup_users["lin_165"] = "b1657022405";
$migrate_dedup_users["cwebber"] = "paroneayea";
$migrate_dedup_users["harolddadomo"] = "harold";
$migrate_dedup_users["rabidsquirrel"] = "genericusername";
$migrate_dedup_users["larry3"] = "lehibou";
$migrate_dedup_users["predoe"] = "petronius3d";
$migrate_dedup_users["skoo"] = "stefano";
$migrate_dedup_users["cabergolinety"] = "azathioprinewww";
$migrate_dedup_users["prestijkorsan07"] = "prestij07";
$migrate_dedup_users["scottpetrovic"] = "slpetrov";
$migrate_dedup_users["zooly76"] = "zooly";
$migrate_dedup_users["theoryanimation"] = "davidandrade";
$migrate_dedup_users["daninsky"] = "danishit";
$migrate_dedup_users["eyesee2013"] = "eyesee";
$migrate_dedup_users["megacal"] = "cmcgaugh";
$migrate_dedup_users["const"] = "kostas100";
$migrate_dedup_users["ngaudenzi"] = "puppetmaster";
$migrate_dedup_users["mroguski"] = "kaelthas";
$migrate_dedup_users["brdf"] = "origin";
$migrate_dedup_users["davis3d"] = "davis";
$migrate_dedup_users["rldigital"] = "locatelli";
$migrate_dedup_users["tomforsythe"] = "gallifrey77203";
$migrate_dedup_users["gbrnk"] = "benoe";
$migrate_dedup_users["arekkasprzyk"] = "kasperski";
$migrate_dedup_users["imbusy1"] = "imbusy";
$migrate_dedup_users["mfoxdoggg"] = "mfoxdogg";
$migrate_dedup_users["knusk"] = "kanutus";
$migrate_dedup_users["tomekk"] = "anders211";
$migrate_dedup_users["kitsueb"] = "kitsu_eb";
$migrate_dedup_users["slugzzz"] = "tsquar3d";
$migrate_dedup_users["moore500"] = "mmoore500";
$migrate_dedup_users["verumbra"] = "sebastian0";
$migrate_dedup_users["blenderbug"] = "nikola";
$migrate_dedup_users["adailtoncomp"] = "adailton";
$migrate_dedup_users["mchs3d"] = "abtrumpet";
// disabled users who have tasks
$migrate_dedup_users["sjoerd"] = "sjoerddevries";
$migrate_dedup_users["matali"] = "mat_ali";
$migrate_dedup_users["voicelesscushio"] = "None";
$migrate_dedup_users["bigben0328"] = "None";
$migrate_dedup_users["santamouse"] = "None";
$migrate_dedup_users["andreanckaert"] = "None";
$migrate_dedup_users["yesmydear"] = "None";
$migrate_dedup_users["spacetug"] = "None";
$migrate_dedup_users["omegafold"] = "None";
// testing
$migrate_dedup_users["blendix_rename_test_a"] = "blendix";
$migrate_dedup_users["blendix_rename_test_b"] = "blendix";

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.7 KiB

After

Width:  |  Height:  |  Size: 9.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.4 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.0 KiB

After

Width:  |  Height:  |  Size: 5.4 KiB

View File

@@ -9,10 +9,10 @@ return array(
'names' => array(
'conpherence.pkg.css' => '0e3cf785',
'conpherence.pkg.js' => '020aebcf',
'core.pkg.css' => 'ba768cdb',
'core.pkg.js' => '845355f4',
'core.pkg.css' => 'f784f26b',
'core.pkg.js' => '74ad315f',
'dark-console.pkg.js' => '187792c2',
'differential.pkg.css' => '5c459f92',
'differential.pkg.css' => '32879ab6',
'differential.pkg.js' => '218fda21',
'diffusion.pkg.css' => '42c75c37',
'diffusion.pkg.js' => 'a98c0bf7',
@@ -38,9 +38,9 @@ return array(
'rsrc/css/aphront/typeahead.css' => '8779483d',
'rsrc/css/application/almanac/almanac.css' => '2e050f4f',
'rsrc/css/application/auth/auth.css' => 'c2f23d74',
'rsrc/css/application/base/main-menu-view.css' => 'bcec20f0',
'rsrc/css/application/base/main-menu-view.css' => 'eacf7e46',
'rsrc/css/application/base/notification-menu.css' => '4df1ee30',
'rsrc/css/application/base/phui-theme.css' => '35883b37',
'rsrc/css/application/base/phui-theme.css' => '63311e09',
'rsrc/css/application/base/standard-page-view.css' => 'a374f94c',
'rsrc/css/application/chatlog/chatlog.css' => 'abdc76ee',
'rsrc/css/application/conduit/conduit-api.css' => 'ce2cfc41',
@@ -67,7 +67,7 @@ return array(
'rsrc/css/application/differential/core.css' => '7300a73e',
'rsrc/css/application/differential/phui-inline-comment.css' => '9863a85e',
'rsrc/css/application/differential/revision-comment.css' => '7dbc8d1d',
'rsrc/css/application/differential/revision-history.css' => '8aa3eac5',
'rsrc/css/application/differential/revision-history.css' => '04edcc29',
'rsrc/css/application/differential/revision-list.css' => '93d2df7d',
'rsrc/css/application/differential/table-of-contents.css' => 'bba788b9',
'rsrc/css/application/diffusion/diffusion-icons.css' => '23b31a1b',
@@ -137,7 +137,7 @@ return array(
'rsrc/css/phui/object-item/phui-oi-simple-ui.css' => '6a30fa46',
'rsrc/css/phui/phui-action-list.css' => '1b0085b2',
'rsrc/css/phui/phui-action-panel.css' => '6c386cbf',
'rsrc/css/phui/phui-badge.css' => '666e25ad',
'rsrc/css/phui/phui-badge.css' => '96576409',
'rsrc/css/phui/phui-basic-nav-view.css' => '56ebd66d',
'rsrc/css/phui/phui-big-info-view.css' => '362ad37b',
'rsrc/css/phui/phui-box.css' => '5ed3b8cb',
@@ -147,14 +147,14 @@ return array(
'rsrc/css/phui/phui-comment-form.css' => '68a2d99a',
'rsrc/css/phui/phui-comment-panel.css' => 'ec4e31c0',
'rsrc/css/phui/phui-crumbs-view.css' => '614f43cf',
'rsrc/css/phui/phui-curtain-object-ref-view.css' => '12404744',
'rsrc/css/phui/phui-curtain-object-ref-view.css' => 'b43b7307',
'rsrc/css/phui/phui-curtain-view.css' => '68c5efb6',
'rsrc/css/phui/phui-document-pro.css' => 'b9613a10',
'rsrc/css/phui/phui-document-summary.css' => 'b068eed1',
'rsrc/css/phui/phui-document.css' => '52b748a5',
'rsrc/css/phui/phui-feed-story.css' => 'a0c05029',
'rsrc/css/phui/phui-fontkit.css' => '1ec937e5',
'rsrc/css/phui/phui-form-view.css' => '01b796c0',
'rsrc/css/phui/phui-form-view.css' => 'a8e0a1ab',
'rsrc/css/phui/phui-form.css' => '1f177cb7',
'rsrc/css/phui/phui-formation-view.css' => 'd2dec8ed',
'rsrc/css/phui/phui-head-thing.css' => 'd7f293df',
@@ -187,6 +187,16 @@ return array(
'rsrc/css/sprite-login.css' => '18b368a6',
'rsrc/css/sprite-tokens.css' => 'f1896dc5',
'rsrc/css/syntax/syntax-default.css' => '055fc231',
'rsrc/custom/css/phabricator-welcome-page.css' => 'a641fcc9',
'rsrc/custom/image/badges/badge_devfund_bronze.png' => '0f98ccf2',
'rsrc/custom/image/badges/badge_devfund_diamond.png' => '196d8206',
'rsrc/custom/image/badges/badge_devfund_gold.png' => 'd03e1722',
'rsrc/custom/image/badges/badge_devfund_platinum.png' => '3e517840',
'rsrc/custom/image/badges/badge_devfund_silver.png' => '73594dee',
'rsrc/custom/image/badges/badge_devfund_titanium.png' => 'e30aa898',
'rsrc/custom/image/badges/badge_sprite_fright.png' => '6f4b20e6',
'rsrc/custom/image/badges/badge_studio.png' => 'ffbdcabb',
'rsrc/custom/image/blender_logo.png' => '86dc8498',
'rsrc/externals/d3/d3.min.js' => '9d068042',
'rsrc/externals/font/fontawesome/fontawesome-webfont.eot' => '23f8c698',
'rsrc/externals/font/fontawesome/fontawesome-webfont.ttf' => '70983df0',
@@ -272,7 +282,7 @@ return array(
'rsrc/externals/javelin/lib/control/typeahead/source/TypeaheadPreloadedSource.js' => '5a79f6c3',
'rsrc/externals/javelin/lib/control/typeahead/source/TypeaheadSource.js' => '8badee71',
'rsrc/externals/javelin/lib/control/typeahead/source/TypeaheadStaticSource.js' => '80bff3af',
'rsrc/favicons/favicon-16x16.png' => '4c51a03a',
'rsrc/favicons/favicon-16x16.png' => 'b1399751',
'rsrc/favicons/mask-icon.svg' => 'db699fe1',
'rsrc/image/BFCFDA.png' => '74b5c88b',
'rsrc/image/actions/edit.png' => 'fd987dff',
@@ -490,7 +500,7 @@ return array(
'rsrc/js/core/behavior-more.js' => '506aa3f4',
'rsrc/js/core/behavior-object-selector.js' => '98ef467f',
'rsrc/js/core/behavior-oncopy.js' => 'da8f5259',
'rsrc/js/core/behavior-phabricator-remarkup-assist.js' => '54262396',
'rsrc/js/core/behavior-phabricator-remarkup-assist.js' => '99e30c81',
'rsrc/js/core/behavior-read-only-warning.js' => 'b9109f8f',
'rsrc/js/core/behavior-redirect.js' => '407ee861',
'rsrc/js/core/behavior-refresh-csrf.js' => '46116c01',
@@ -564,7 +574,7 @@ return array(
'differential-core-view-css' => '7300a73e',
'differential-revision-add-comment-css' => '7e5900d9',
'differential-revision-comment-css' => '7dbc8d1d',
'differential-revision-history-css' => '8aa3eac5',
'differential-revision-history-css' => '04edcc29',
'differential-revision-list-css' => '93d2df7d',
'differential-table-of-contents-css' => 'bba788b9',
'diffusion-css' => 'b54c77b0',
@@ -650,7 +660,7 @@ return array(
'javelin-behavior-phabricator-notification-example' => '29819b75',
'javelin-behavior-phabricator-object-selector' => '98ef467f',
'javelin-behavior-phabricator-oncopy' => 'da8f5259',
'javelin-behavior-phabricator-remarkup-assist' => '54262396',
'javelin-behavior-phabricator-remarkup-assist' => '99e30c81',
'javelin-behavior-phabricator-reveal-content' => 'b105a3a6',
'javelin-behavior-phabricator-search-typeahead' => '1cb7d027',
'javelin-behavior-phabricator-show-older-transactions' => '8b5c7d65',
@@ -790,7 +800,7 @@ return array(
'phabricator-flag-css' => '2b77be8d',
'phabricator-keyboard-shortcut' => '1a844c06',
'phabricator-keyboard-shortcut-manager' => '81debc48',
'phabricator-main-menu-view' => 'bcec20f0',
'phabricator-main-menu-view' => 'eacf7e46',
'phabricator-nav-view-css' => '423f92cc',
'phabricator-notification' => 'a9b91e3f',
'phabricator-notification-css' => '30240bd2',
@@ -808,6 +818,7 @@ return array(
'phabricator-title' => '43bc9360',
'phabricator-tooltip' => '83754533',
'phabricator-ui-example-css' => 'b4795059',
'phabricator-welcome-page' => 'a641fcc9',
'phabricator-zindex-css' => 'ac3bfcd4',
'phame-css' => 'bb442327',
'pholio-css' => '88ef5ef1',
@@ -820,7 +831,7 @@ return array(
'phrequent-css' => 'bd79cc67',
'phriction-document-css' => '03380da0',
'phui-action-panel-css' => '6c386cbf',
'phui-badge-view-css' => '666e25ad',
'phui-badge-view-css' => '96576409',
'phui-basic-nav-view-css' => '56ebd66d',
'phui-big-info-view-css' => '362ad37b',
'phui-box-css' => '5ed3b8cb',
@@ -837,7 +848,7 @@ return array(
'phui-comment-form-css' => '68a2d99a',
'phui-comment-panel-css' => 'ec4e31c0',
'phui-crumbs-view-css' => '614f43cf',
'phui-curtain-object-ref-view-css' => '12404744',
'phui-curtain-object-ref-view-css' => 'b43b7307',
'phui-curtain-view-css' => '68c5efb6',
'phui-document-summary-view-css' => 'b068eed1',
'phui-document-view-css' => '52b748a5',
@@ -846,7 +857,7 @@ return array(
'phui-font-icon-base-css' => '303c9b87',
'phui-fontkit-css' => '1ec937e5',
'phui-form-css' => '1f177cb7',
'phui-form-view-css' => '01b796c0',
'phui-form-view-css' => 'a8e0a1ab',
'phui-formation-view-css' => 'd2dec8ed',
'phui-head-thing-view-css' => 'd7f293df',
'phui-header-view-css' => '36c86a58',
@@ -877,7 +888,7 @@ return array(
'phui-spacing-css' => 'b05cadc3',
'phui-status-list-view-css' => 'e5ff8be0',
'phui-tag-view-css' => '8519160a',
'phui-theme-css' => '35883b37',
'phui-theme-css' => '63311e09',
'phui-timeline-view-css' => '2d32d7a9',
'phui-two-column-view-css' => 'f96d319f',
'phui-workboard-color-css' => 'e86de308',
@@ -1411,17 +1422,6 @@ return array(
'541f81c3' => array(
'javelin-install',
),
54262396 => array(
'javelin-behavior',
'javelin-stratcom',
'javelin-dom',
'phabricator-phtize',
'phabricator-textareautils',
'javelin-workflow',
'javelin-vector',
'phuix-autocomplete',
'javelin-mask',
),
'548567f6' => array(
'syntax-default-css',
),
@@ -1809,6 +1809,17 @@ return array(
'javelin-request',
'javelin-router',
),
'99e30c81' => array(
'javelin-behavior',
'javelin-stratcom',
'javelin-dom',
'phabricator-phtize',
'phabricator-textareautils',
'javelin-workflow',
'javelin-vector',
'phuix-autocomplete',
'javelin-mask',
),
'9aae2b66' => array(
'javelin-install',
'javelin-util',
@@ -2034,9 +2045,6 @@ return array(
'phabricator-drag-and-drop-file-upload',
'javelin-workboard-board',
),
'bcec20f0' => array(
'phui-theme-css',
),
'c03f2fb4' => array(
'javelin-install',
),
@@ -2164,6 +2172,9 @@ return array(
'javelin-install',
'javelin-event',
),
'eacf7e46' => array(
'phui-theme-css',
),
'ebe83a6b' => array(
'javelin-install',
),

View File

@@ -7,6 +7,7 @@ $status_map = array(
3 => 'invalid',
4 => 'duplicate',
5 => 'spite',
123450 => 'archived',
);
$conn_w = id(new ManiphestTask())->establishConnection('w');

View File

@@ -0,0 +1,172 @@
#!/usr/local/bin/php
<?php
#
# ***** BEGIN GPL LICENSE BLOCK *****
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software Foundation,
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#
# The Original Code is Copyright (C) 2019, Blender Foundation
# All rights reserved.
#
# Contributor(s): Sergey Sharybin.
#
# ***** END GPL LICENSE BLOCK *****
#
# This scripts implements external AuthBasicProvider which can be used
# to authentificate users using Phabricator's database.
#
# Example configuration:
#
# .htaccess file:
#
# AuthType Basic
# AuthName "Please Enter Password"
# AuthBasicProvider external
# AuthExternal phabricator
# Require valid-user
#
# It is also required to have the following provider registered in the
# configuration. There are two ways to do it:
#
# 1. Separate conf file in /etc/apache2/conf-enabled
# Create a file (say, authz_external_phabricator.conf) with the following
# content:
#
# DefineExternalAuth phabricator pipe /path/to/auth_provider.php
#
# This method allows to use provider in any VHOST.
#
# Downside: from local tests .htaccess file picks the provider nicely,
# but attempts to specifu the provider in virtual host configuration
# resulted in issues (seems to be different initialization order between
# global config in those files and virtual hosts).
#
# 2. Define provider in the virtual host definition:
#
# <IfModule mod_authnz_external.c>
# AddExternalAuth phabricator /path/to/auth_provider.php
# SetExternalAuthMethod phabricator pipe
# </IfModule>
#
# This method allowed to use this auth provider for SVN DAV.
$IS_DEBUG = false;
$PHABRICATOR_ROOT = dirname(dirname(dirname(__FILE__)));
require_once $PHABRICATOR_ROOT.'/scripts/__init_script__.php';
function initLogging() {
global $IS_DEBUG;
global $argv;
for ($i = 1; $i < count($argv); ++$i) {
if ($argv[$i] == '--debug') {
$IS_DEBUG = true;
}
}
}
function debugLog(string $text) {
global $IS_DEBUG;
if (!$IS_DEBUG) {
return;
}
print("${text}\n");
}
function removeSingleTrailingNewline(string $string) {
if ($string === '') {
return $string;
}
$length = strlen($string);
if ($string[$length - 1] == "\n") {
return substr($string, 0, -1);
}
return $string;
}
class AuthRequest {
public $user_name;
public $password;
static function fromStdin() {
$auth_request = new AuthRequest();
$stdin = fopen('php://stdin', 'r');
$auth_request->user_name = removeSingleTrailingNewline(fgets($stdin));
$auth_request->password = removeSingleTrailingNewline(fgets($stdin));
return $auth_request;
}
};
function getUserForAuthRequest(AuthRequest $auth_request) {
if ($auth_request->user_name === '') {
return null;
}
$username_or_email = $auth_request->user_name;
$user = id(new PhabricatorUser())->loadOneWhere(
'username = %s',
$username_or_email);
if (!$user) {
$user = PhabricatorUser::loadOneWithEmailAddress(
$username_or_email);
}
return $user;
}
function createContentSourceForAuth() {
return PhabricatorContentSource::newForSource(
PhabricatorUnitTestContentSource::SOURCECONST);
}
function isValidAuth(AuthRequest $auth_request) {
debugLog("Begin authentification check for user '$auth_request->user_name'");
$user = getUserForAuthRequest($auth_request);
if (!$user) {
debugLog("No PhabricatorUser() object found for requested user.");
return false;
}
$content_source = createContentSourceForAuth();
$envelope = new PhutilOpaqueEnvelope($auth_request->password);
$engine = id(new PhabricatorAuthPasswordEngine())
->setViewer($user)
->setContentSource($content_source)
->setPasswordType(PhabricatorAuthPassword::PASSWORD_TYPE_ACCOUNT)
->setObject($user);
if (!$engine->isValidPassword($envelope)) {
debugLog('Engine reported invalid password.');
return false;
}
debugLog('Authentirfication passed.');
return true;
}
function main() {
initLogging();
$auth_request = AuthRequest::fromStdin();
if (!isValidAuth($auth_request)) {
exit(1);
}
exit(0);
}
main();
?>

576
scripts/bake/bake.php Normal file
View File

@@ -0,0 +1,576 @@
#!/usr/local/bin/php
<?php
/////////////////////////////////////////////////////////////////////////////////
// Bootstrap.
$PHABRICATOR_ROOT = dirname(dirname(dirname(__FILE__)));
require_once $PHABRICATOR_ROOT.'/scripts/__init_script__.php';
/////////////////////////////////////////////////////////////////////////////////
// Command line.
$argc = count($argv);
if ($argc < 3 || $argc > 4) {
print("Usage: $argv[0] <conduit_token_file> <output_directory> [timestamp]\n");
die;
}
$CONDUIT_TOKEN_FILE = $argv[1];
$OUTPUT_DIR = $argv[2];
$TIMESTAMP = ($argc == 4) ? (int)$argv[3] : 0;
/////////////////////////////////////////////////////////////////////////////////
// Global configuration.
$HOST = 'phabricator.local';
/////////////////////////////////////////////////////////////////////////////////
// Utilities.
// Create an instance of the AphrontApplicationConfiguration configured with all
// invariant settings (settings which do not change between handlers of different
// revisions).
function CreateApplicationConfiguration() {
global $HOST;
$application_configuration = new AphrontApplicationConfiguration();
$application_configuration->setHost($HOST);
return $application_configuration;
}
/////////////////////////////////////////////////////////////////////////////////
// Global state.
$site = id(new PhabricatorPlatformSite());
$viewer = PhabricatorUser::getOmnipotentUser();
$application_configuration = CreateApplicationConfiguration();
$differential_application = id(new PhabricatorDifferentialApplication());
$revision_controller = id(new DifferentialRevisionViewController())
->setCurrentApplication($differential_application);
$maniphest_application = id(new PhabricatorManiphestApplication());
$maniphest_controller = id(new ManiphestTaskDetailController())
->setCurrentApplication($maniphest_application);
$differential_routing_map = id(new AphrontRoutingMap())
->setSite($site)
->setApplication($differential_application)
->setRoutes($differential_application->getRoutes());
$maniphest_routing_map = id(new AphrontRoutingMap())
->setSite($site)
->setApplication($maniphest_application)
->setRoutes($maniphest_application->getRoutes());
$conduit = id(new ConduitClient('https://developer.blender.org/api/'))
->setConduitToken(trim(file_get_contents($CONDUIT_TOKEN_FILE)));
/////////////////////////////////////////////////////////////////////////////////
// Baking utilities.
function EnsureDirectoryOrDie($dir) {
if (!is_dir($dir)) {
if (!mkdir($dir, 0777, true)) {
print("Error creating output durectory $dir\n");
die;
}
}
}
function RenderElement($element) {
if (is_array($element)) {
$html = '';
foreach ($element as $child) {
$html .= RenderElement($child);
}
return $html;
}
return $element->render();
}
function RenderResponseToHTML($response) {
$html = '';
$crumbs = $response->getCrumbs();
if ($crumbs) {
$html .= $crumbs->render();
}
foreach ($response->renderChildren() as $child) {
$html .= RenderElement($child);
}
return $html;
}
/////////////////////////////////////////////////////////////////////////////////
// Revision baking.
class RevisionInfo {
public $title = '';
public $page_title = '';
public $last_diff_id = 0;
public $hash = '';
public static function ReadFromFile($file_name) {
$info = new RevisionInfo();
if (!file_exists($file_name)) {
return $info;
}
$json = json_decode(file_get_contents($file_name));
foreach ($json as $key => $value) {
$info->{$key} = $value;
}
return $info;
}
public function SaveToFile($file_name) {
$json_str = json_encode(get_object_vars($this));
file_put_contents($file_name, $json_str);
}
};
function GetRevisionOutputDirectory($revision) {
global $OUTPUT_DIR;
$id = $revision->getID();
return PathJoin(array($OUTPUT_DIR, 'differential', SubpathFromId($id)));
}
function EnsureRevisionOutputDirectory($revision) {
$dir = GetRevisionOutputDirectory($revision);
EnsureDirectoryOrDie($dir);
EnsureDirectoryOrDie(PathJoin(array($dir, 'raw_diff')));
return $dir;
}
function GetRevisionInfoFilename($revision) {
$revision_dir = GetRevisionOutputDirectory($revision);
return PathJoin(array($revision_dir, 'info.json'));
}
function GetRevisionHTMLFilename($revision, $diff_id) {
$revision_id = $revision->getID();
$revision_dir = GetRevisionOutputDirectory($revision);
$file_name = "D{$revision_id}.id{$diff_id}.html";
return PathJoin(array($revision_dir, $file_name));
}
function GetRevisionRawDiffFilename($revision, $diff_id) {
$revision_id = $revision->getID();
$revision_dir = GetRevisionOutputDirectory($revision);
$file_name = "D{$revision_id}.id{$diff_id}.diff";
return PathJoin(array($revision_dir, 'raw_diff', $file_name));
}
function RenderDifferentialToResponse($revision, $diff_id) {
global $application_configuration;
global $revision_controller;
global $differential_routing_map;
global $viewer;
$revision_id = $revision->getID();
$path = '/D' . $revision_id;
$route_result = $differential_routing_map->routePath($path);
$uri_data = $route_result->getURIData();
$application_configuration->setPath($path);
$request_data = array(
'id' => $diff_id,
);
$request = $application_configuration->buildRequest()
->setUser($viewer)
->setRequestData($request_data)
->setURIMap($uri_data);
$response = id($revision_controller)
->setRequest($request)
->handleRequest($request);
return $response;
}
function StoreRawDiff($revision, $diff_id) {
global $viewer;
global $conduit;
$diff = id(new DifferentialDiffQuery())
->setViewer($viewer)
->withIDs(array($diff_id))
->needChangesets(true)
->executeOne();
$raw_changes = $diff->buildChangesList();
$changes = array();
foreach ($raw_changes as $changedict) {
$changes[] = ArcanistDiffChange::newFromDictionary($changedict);
}
$bundle = ArcanistBundle::newFromChanges($changes);
$bundle->setConduit($conduit);
$raw_diff = $bundle->toGitPatch();
$output_file = GetRevisionRawDiffFilename($revision, $diff_id);
file_put_contents($output_file, $raw_diff);
}
function GetRevisionHash($revision) {
global $viewer;
$xaction = id(new DifferentialTransactionQuery())
->setViewer($viewer)
->withObjectPHIDs(array($revision->getPHID()))
->setOrder('updated')
->setLimit(1)
->executeOne();
$digest = '';
$digest .= $revision->getDateModified();
if ($xaction) {
$digest .= '_' . $xaction->getPHID();
$digest .= '_' . $xaction->getDateModified();
}
return $digest;
}
function NeedBakeRevision($info, $revision, $diff_id) {
if (!file_exists(GetRevisionHTMLFilename($revision, $diff_id))) {
return true;
}
if (!file_exists(GetRevisionRawDiffFilename($revision, $diff_id))) {
return true;
}
if ($info->last_diff_id < $diff_id) {
return true;
}
if ($revision->getTitle() != $info->title) {
return true;
}
if (GetRevisionHash($revision) != $info->hash) {
return true;
}
return false;
}
function BakeRevision($revision, $diff_id) {
$revision_id = $revision->getID();
printf('Baking D' . $revision_id . '?id=' . $diff_id . ' ...' . "\n");
$info_file_name = GetRevisionInfoFilename($revision);
$info = RevisionInfo::ReadFromFile($info_file_name);
if (!NeedBakeRevision($info, $revision, $diff_id)) {
print(' ... ignoring: up to date' . "\n");
return;
}
$response = RenderDifferentialToResponse($revision, $diff_id);
$html = RenderResponseToHTML($response);
$html_file_name = GetRevisionHTMLFIlename($revision, $diff_id);
file_put_contents($html_file_name, $html);
StoreRawDiff($revision, $diff_id);
$info->title = $revision->getTitle();
$info->page_title = $response->getTitle();
$info->hash = GetRevisionHash($revision);
$info->last_diff_id = max($info->last_diff_id, $diff_id);
$info->SaveToFile($info_file_name);
}
function GetAllRevisions() {
global $viewer;
return id(new DifferentialRevisionQuery())
->setViewer($viewer)
->needDiffIDs(true)
->setOrder('oldest')
->execute();
}
function GetModifiedRevisionsSince($timestamp) {
if (!$timestamp) {
return GetAllRevisions();
}
global $viewer;
$xactions = id(new DifferentialTransactionQuery())
->setViewer($viewer)
->setOrder('oldest')
->withUpdatedEpochAfter($timestamp)
->execute();
$revision_ids_set = array();
foreach ($xactions as $xaction_id => $xaction) {
$revision = $xaction->getObject();
$revision_id = $revision->getID();
$revision_ids_set[$revision_id] = 1;
}
$updated_revision_ids = array_keys($revision_ids_set);
return id(new DifferentialRevisionQuery())
->setViewer($viewer)
->needDiffIDs(true)
->setOrder('oldest')
->withIDs($updated_revision_ids)
->execute();
}
/////////////////////////////////////////////////////////////////////////////////
// Task baking.
class TaskInfo {
public $title = '';
public $page_title = '';
public $hash = '';
public static function ReadFromFile($file_name) {
$info = new TaskInfo();
if (!file_exists($file_name)) {
return $info;
}
$json = json_decode(file_get_contents($file_name));
foreach ($json as $key => $value) {
$info->{$key} = $value;
}
return $info;
}
public function SaveToFile($file_name) {
$json_str = json_encode(get_object_vars($this));
file_put_contents($file_name, $json_str);
}
};
function GetTaskOutputDirectory($task) {
global $OUTPUT_DIR;
$id = $task->getID();
return PathJoin(array($OUTPUT_DIR, 'maniphest', SubpathFromId($id)));
}
function EnsureTaskOutputDirectory($task) {
$dir = GetTaskOutputDirectory($task);
EnsureDirectoryOrDie($dir);
return $dir;
}
function GetTaskInfoFilename($task) {
$task_dir = GetTaskOutputDirectory($task);
return PathJoin(array($task_dir, 'info.json'));
}
function GetTaskHTMLFilename($task) {
$task_id = $task->getID();
$task_dir = GetTaskOutputDirectory($task);
$file_name = "index.html";
return PathJoin(array($task_dir, $file_name));
}
function RenderTaskToResponse($task) {
global $application_configuration;
global $maniphest_routing_map;
global $viewer;
global $maniphest_controller;
$task_id = $task->getID();
$path = '/T' . $task_id;
$route_result = $maniphest_routing_map->routePath($path);
$uri_data = $route_result->getURIData();
$application_configuration->setPath($path);
$request_data = array(
);
$request = $application_configuration->buildRequest()
->setUser($viewer)
->setRequestData($request_data)
->setURIMap($uri_data);
$response = id($maniphest_controller)
->setRequest($request)
->handleRequest($request);
return $response;
}
function GetTaskHash($task) {
global $viewer;
$xaction = id(new ManiphestTransactionQuery())
->setViewer($viewer)
->withObjectPHIDs(array($task->getPHID()))
->setOrder('updated')
->setLimit(1)
->executeOne();
$digest = '';
$digest .= $task->getDateModified();
if ($xaction) {
$digest .= '_' . $xaction->getPHID();
$digest .= '_' . $xaction->getDateModified();
}
return $digest;
}
function NeedBakeTask($info, $task) {
if (!file_exists(GetTaskHTMLFilename($task))) {
return true;
}
if ($task->getTitle() != $info->title) {
return true;
}
if (GetTaskHash($task) != $info->hash) {
return true;
}
return false;
}
function BakeTask($task) {
$task_id = $task->getID();
printf('Baking T' . $task_id . ' ...' . "\n");
$info_file_name = GetTaskInfoFilename($task);
$info = TaskInfo::ReadFromFile($info_file_name);
if (!NeedBakeTask($info, $task)) {
print(' ... ignoring: up to date' . "\n");
return;
}
$response = RenderTaskToResponse($task);
$html = RenderResponseToHTML($response);
$html_file_name = GetTaskHTMLFIlename($task);
file_put_contents($html_file_name, $html);
$info->title = $task->getTitle();
$info->page_title = $response->getTitle();
$info->hash = GetTaskHash($task);
$info->SaveToFile($info_file_name);
}
function GetAllTasks() {
global $viewer;
return id(new ManiphestTaskQuery())
->setViewer($viewer)
->setOrder('oldest')
->execute();
}
function GetModifiedTasksSinze($timestamp) {
if (!$timestamp) {
return GetAllTasks();
}
global $viewer;
$xactions = id(new ManiphestTransactionQuery())
->setViewer($viewer)
->setOrder('updated')
->withUpdatedEpochAfter($timestamp)
->execute();
$task_ids_set = array();
foreach ($xactions as $xaction_id => $xaction) {
$task = $xaction->getObject();
$task_id = $task->getID();
$task_ids_set[$task_id] = 1;
}
$updated_task_ids = array_keys($task_ids_set);
return id(new ManiphestTaskQuery())
->setViewer($viewer)
->setOrder('oldest')
->withIDs($updated_task_ids)
->execute();
}
/////////////////////////////////////////////////////////////////////////////////
// Baking main loop.
print('Querying differential revisions from the database ... ' . "\n");
$revisions = GetModifiedRevisionsSince($TIMESTAMP);
foreach ($revisions as $revision_id => $revision) {
EnsureRevisionOutputDirectory($revision);
foreach ($revision->getDiffIDs() as $diff_id) {
BakeRevision($revision, $diff_id);
}
}
print("\n");
print('Querying maniphest tasks from the database ... ' . "\n");
$tasks = GetModifiedTasksSinze($TIMESTAMP);
foreach ($tasks as $task_id => $task) {
EnsureTaskOutputDirectory($task);
BakeTask($task);
}
?>

View File

@@ -0,0 +1,49 @@
#!/usr/local/bin/php
<?php
$PHABRICATOR_ROOT = dirname(dirname(dirname(__FILE__)));
require_once $PHABRICATOR_ROOT.'/scripts/__init_script__.php';
if (count($argv) != 2) {
print("Usage: $argv[0] timestamp\n");
die;
}
$TIMESTAMP = $argv[1];
$viewer = PhabricatorUser::getOmnipotentUser();
$xactions = id(new ManiphestTransactionQuery())
->setViewer($viewer)
->setOrder('updated')
->withUpdatedEpochAfter($TIMESTAMP)
->execute();
$tasks = array();
foreach ($xactions as $xaction_id => $xaction) {
$task = $xaction->getObject();
$task_id = $task->getID();
$tasks[$task_id] = 1;
}
$task_ids = array_keys($tasks);
sort($task_ids);
$handle = fopen("tasks.json", "w");
fwrite($handle, "[\n");
$is_first = true;
foreach ($task_ids as $task_id ) {
if (!$is_first) {
fwrite($handle, ",\n");
}
fwrite($handle, " {$task_id}");
$is_first = false;
}
fwrite($handle, "\n]\n");
fclose($handle);
?>

View File

@@ -0,0 +1,32 @@
#!/usr/local/bin/php
<?php
$PHABRICATOR_ROOT = dirname(dirname(dirname(__FILE__)));
require_once $PHABRICATOR_ROOT.'/scripts/__init_script__.php';
$viewer = PhabricatorUser::getOmnipotentUser();
# print("Querying all files...\n");
$files = id(new PhabricatorFileQuery())
->setViewer($viewer)
->setOrder('oldest')
->execute();
# print("Looping over the files\n");
print("ids = (\n");
foreach ($files as $file_id => $file) {
$authorPHID = $file->getAuthorPHID();
if (!$authorPHID) {
$name = $file->getName();
if (substr($name, 0, 8) != 'preview-') {
$prev_file = $file;
continue;
}
}
print($file->getID() . ",\n");
}
print(")\n");
?>

6
scripts/gitadmin/gitx-ssh Executable file
View File

@@ -0,0 +1,6 @@
#!/usr/local/bin/bash
set -e
set -u
ssh -i $SSH_KEYFILE $@

View File

@@ -0,0 +1,443 @@
#!/usr/local/bin/php
<?php
$root = dirname(dirname(dirname(__FILE__)));
require_once $root.'/scripts/__init_script__.php';
function escape_name($name) {
return preg_replace('/[^A-Za-z0-9\-]/', '_', $name);
}
function startswith($string, $prefix) {
return substr($string, 0, strlen($prefix)) == $prefix;
}
function endswith($string, $suffix) {
$suffix_length = strlen($suffix);
return substr($string, strlen($string) - $suffix_length,
$suffix_length) == $suffix;
}
function write_ini_file($array, $file) {
$res = array();
foreach ($array as $key => $val) {
if (is_array($val)) {
$res[] = "[$key]";
foreach ($val as $skey => $sval) {
$res[] = "$skey = $sval";
}
$res[] = '';
} else {
$res[] = "$key = $val";
}
}
file_put_contents($file, implode("\n", $res));
}
function getProjectMembersPHIDs($viewer, $project_phid) {
$project = id(new PhabricatorProjectQuery())
->setViewer($viewer)
->needMembers(true)
->withPHIDs(array($project_phid))
->executeOne();
return $project->getMemberPHIDs();
}
// Get user's heys and put them to the configuration
function handleSingleUserPHID(
$keydir, $viewer, $userPHID, $system_keys, &$used_keys) {
$user = id(new PhabricatorPeopleQuery())
->setViewer($viewer)
->withPHIDs(array($userPHID))
->executeOne();
if (!$user) {
return array();
}
if ($user->getIsDisabled()) {
return array();
}
$keys = id(new PhabricatorAuthSSHKey())->loadAllWhere(
'objectPHID = %s',
$user->getPHID());
$members = array();
foreach ($keys as $key) {
$full_key_content =
$key->getKeyType().' '.
$key->getKeyBody().' '.
$key->getKeyComment()."\n";
if (array_key_exists($full_key_content, $system_keys)) {
$members[] = $system_keys[$full_key_content];
} else {
$escaped_key_name = escape_name($key->getName());
$member = 'PHAB_'.$user->getUserName().
'_'.$escaped_key_name.
'_'.$key->getID();
$members[] = $member;
if (!array_key_exists($member, $used_keys)) {
$used_keys[$member] = true;
file_put_contents("$keydir/$member.pub", $full_key_content);
}
}
}
return $members;
}
function handleUsersPolicyRule(
$keydir, $viewer, $rule, $system_keys, &$used_keys) {
$members = array();
foreach ($rule['value'] as $userPHID) {
$members = array_merge($members,
handleSingleUserPHID($keydir, $viewer, $userPHID,
$system_keys, $used_keys));
}
return $members;
}
function handleProjectsPolicyRule(
$keydir, $viewer, $rule, $system_keys, &$used_keys) {
$members = array();
foreach ($rule['value'] as $projectPHID) {
$memberPHIDs = getProjectMembersPHIDs($viewer, $projectPHID);
foreach ($memberPHIDs as $userPHID) {
$members = array_merge($members,
handleSingleUserPHID($keydir, $viewer, $userPHID,
$system_keys, $used_keys));
}
}
return $members;
}
function handleProjectsAllPolicyRule(
$keydir, $viewer, $rule, $system_keys, &$used_keys) {
$is_first_project = true;
$allowed_members_phids = array();
foreach ($rule['value'] as $project_phid) {
$memberPHIDs = getProjectMembersPHIDs($viewer, $project_phid);
if ($is_first_project) {
$allowed_members_phids = $memberPHIDs;
$is_first_project = false;
} else {
$allowed_members_phids = array_intersect(
$allowed_members_phids, $memberPHIDs);
}
}
$members = array();
foreach ($allowed_members_phids as $userPHID) {
$members = array_merge($members,
handleSingleUserPHID($keydir, $viewer, $userPHID,
$system_keys, $used_keys));
}
return $members;
}
function handleAdministratorsPolicyRule(
$keydir, $viewer, $rule, $system_keys, &$used_keys) {
$administrators = id(new PhabricatorPeopleQuery())
->setViewer($viewer)
->withIsAdmin(true)
->execute();
$members = array();
foreach ($administrators as $administrator) {
$members = array_merge($members,
handleSingleUserPHID($keydir, $viewer, $administrator->getPHID(),
$system_keys, $used_keys));
}
return $members;
}
function handleLegalpadSingleDocument(
$keydir, $viewer, $document, $system_keys, &$used_keys) {
if ($document->getSignatureType() !=
LegalpadDocument::SIGNATURE_TYPE_INDIVIDUAL) {
return array();
}
$members = array();
foreach ($document->getSignatures() as $signature) {
if ($signature->getSignatureType() !=
LegalpadDocument::SIGNATURE_TYPE_INDIVIDUAL) {
continue;
}
$members = array_merge($members,
handleSingleUserPHID($keydir, $viewer, $signature->getSignerPHID(),
$system_keys, $used_keys));
}
return $members;
}
function handleLegalpadSignaturePolicyRule(
$keydir, $viewer, $rule, $system_keys, &$used_keys) {
$documents = id(new LegalpadDocumentQuery())
->setViewer($viewer)
->withPHIDs($rule['value'])
->needSignatures(true)
->execute();
$members = array();
foreach ($documents as $document) {
$members = array_merge(
$members,
handleLegalpadSingleDocument(
$keydir, $viewer, $document, $system_keys, $used_keys));
}
return $members;
}
function handleCustomPolicy(
$keydir, $viewer, $policy, $system_keys, &$used_keys) {
$members = array();
$rules = $policy->getRules();
foreach ($rules as $rule) {
// Everyone is denied by default anyway
if ($rule['action'] != 'allow') {
continue;
}
$policy_members = array();
$rule_type = $rule['rule'];
if ($rule_type == 'PhabricatorPolicyRuleUsers') {
$policy_members = handleUsersPolicyRule(
$keydir, $viewer, $rule, $system_keys, $used_keys);
} else if ($rule_type == 'PhabricatorProjectsPolicyRule') {
$policy_members = handleProjectsPolicyRule(
$keydir, $viewer, $rule, $system_keys, $used_keys);
} else if ($rule_type == 'PhabricatorProjectsAllPolicyRule') {
$policy_members = handleProjectsAllPolicyRule(
$keydir, $viewer, $rule, $system_keys, $used_keys);
} else if ($rule_type == 'PhabricatorAdministratorsPolicyRule') {
$policy_members = handleAdministratorsPolicyRule(
$keydir, $viewer, $rule, $system_keys, $used_keys);
} else if ($rule_type == 'PhabricatorLegalpadSignaturePolicyRule') {
$policy_members = handleLegalpadSignaturePolicyRule(
$keydir, $viewer, $rule, $system_keys, $used_keys);
}
$members = array_merge($members, $policy_members);
}
return $members;
}
// Parse repository and put it's members to the config file
function handleSingleRepository(
$keydir, $viewer, $repository, $all_repositories, $system_keys,
&$new_configuration, &$used_keys) {
$policies = PhabricatorPolicyQuery::loadPolicies(
$viewer,
$repository);
$pushable = $policies[DiffusionPushCapability::CAPABILITY];
$type = $pushable->getType();
$members = array();
if ($type == PhabricatorPolicyType::TYPE_PROJECT) {
$project = id(new PhabricatorProjectQuery())
->setViewer($viewer)
->needMembers(true)
->withPHIDs(array($pushable->getPHID()))
->executeOne();
$memberPHIDs = $project->getMemberPHIDs();
foreach ($memberPHIDs as $memberPHID) {
$members = array_merge($members,
handleSingleUserPHID($keydir, $viewer, $memberPHID,
$system_keys, $used_keys));
}
} else if ($type == PhabricatorPolicyType::TYPE_USER) {
$members = handleSingleUserPHID(
$keydir, $viewer, $pushable->getPHID(), $system_keys, $used_keys);
} else if ($type == PhabricatorPolicyType::TYPE_CUSTOM) {
$members = handleCustomPolicy(
$keydir, $viewer, $pushable, $system_keys, $used_keys);
} else {
/* pass */
}
if (count($members)) {
$uri = $repository->getRemoteURI();
$repository_name = basename($uri, '.git');
$escaped_repository_name = escape_name($repository->getName());
$group_name = "PHAB_${escaped_repository_name}";
$values = array();
$values['members'] = join(' ', $members);
$values['readonly'] = join(' ', $all_repositories);
$values['writable'] = $repository_name;
$new_configuration["group $group_name"] = $values;
}
}
// Remove groups from previous automated configuration built
function getCleanOldConfiguration($old_configuration) {
$new_configuration = array();
foreach ($old_configuration as $group => $values) {
if (!startswith($group, 'group PHAB')) {
$new_configuration[$group] = $values;
}
}
return $new_configuration;
}
// Get non-phab keys
function getSystemPublicKeys($keydir) {
$files = scandir($keydir);
$system_keys = array();
foreach ($files as $file) {
if (!startswith($file, "PHAB") && endswith($file, '.pub')) {
$key = file_get_contents("$keydir/$file");
$system_keys[$key] = basename($file, '.pub');
}
}
return $system_keys;
}
// Remove unused public keys
function removeUnusedPublicKeys($keydir, $used_keys) {
$files = scandir($keydir);
foreach ($files as $file) {
if (startswith($file, "PHAB")) {
$member = basename($file, '.pub');
if (!array_key_exists($member, $used_keys)) {
unlink("$keydir/$file");
}
}
}
}
function rebuildConfiguration($gitosis_root) {
$keydir = "$gitosis_root/keydir";
$configuration_file = "$gitosis_root/gitosis.conf";
if (!file_exists($configuration_file)) {
print("Not found: $configuration_file\n");
return false;
}
$viewer = id(new PhabricatorUser())
->loadOneWhere('username = %s', 'sergey');
$old_configuration = parse_ini_file(
$configuration_file, true, INI_SCANNER_RAW);
$new_configuration = getCleanOldConfiguration(
$old_configuration);
// Get "system" keys to re-use if phab account uses the
// same public key
$system_keys = getSystemPublicKeys($keydir);
// Get list of all repos which is awailable for read
$all_repositories = array();
foreach ($old_configuration as $group => $values) {
if (startswith($group, 'repo')) {
$repository_name = substr($group, 5, strlen($group) - 5);
if ($repository_name == 'gitosis-admin')
continue;
$all_repositories[] = $repository_name;
}
}
// Fill in new configuration and keys
$used_keys = array();
$repositories = id(new PhabricatorRepositoryQuery())
->setViewer($viewer)
->execute();
foreach ($repositories as $repository_id => $repository) {
$type = $repository->getVersionControlSystem();
if ($type == PhabricatorRepositoryType::REPOSITORY_TYPE_GIT) {
handleSingleRepository(
$keydir, $viewer, $repository, $all_repositories, $system_keys,
$new_configuration, $used_keys);
}
}
write_ini_file($new_configuration, $configuration_file);
removeUnusedPublicKeys($keydir, $used_keys);
return true;
}
function getGitCommand($repository) {
$git_dir = realpath("$repository/.git");
$git = "git --git-dir='$git_dir'";
$git .= ' --work-tree='.realpath($repository);
return $git;
}
function runGitCommand($repository, $arguments,
&$output=null, &$return_var=null) {
$git = getGitCommand($repository);
$git .= " $arguments";
exec($git, $output, $return_var);
return $return_var == 0;
}
function runGitSshCommand($repository, $key, $arguments,
&$output=null, &$return_var=null) {
$gitx_ssh = realpath(dirname(__FILE__) . "/gitx-ssh");
$abs_key = realpath($key);
$git = "SSH_KEYFILE=$abs_key GIT_SSH=$gitx_ssh ";
$git .= getGitCommand($repository);
$git .= " $arguments";
exec($git, $output, $return_var);
return $return_var == 0;
}
function repositoryPull($repository, $key) {
return runGitSshCommand($repository, $key, 'pull');
}
function repositoryCommitAll($repository, $author, $message) {
if (!runGitCommand(
$repository, 'ls-files --other --exclude-standard', $untracked_files)) {
return false;
}
if (count($untracked_files)) {
$flat_files = join(' ', $untracked_files);
if (!runGitCommand($repository, "add $flat_files")) {
return false;
}
}
runGitCommand($repository, "update-index -q --refresh", $output);
runGitCommand($repository, "diff-index --name-only HEAD --", $output);
if (count($output)) {
return runGitCommand(
$repository, "commit --author='$author' -a -m '$message'", $output);
}
return true;
}
if (count($argv) != 3) {
print("Usage: {$argv[0]} /path/to/gitosis-admin /path/to/id_rsa.pub\n");
exit(1);
}
$gitosis_root = $argv[1];
$key = $argv[2];
if (!repositoryPull($gitosis_root, $key)) {
print("Failed to pull changes from server.\n");
exit(1);
}
if (!rebuildConfiguration($gitosis_root)) {
exit(1);
}
if (!repositoryCommitAll(
$gitosis_root, 'Rebuild Gitadmin <null@git.blender.org>',
'Update to correspond changes in Phabricator')) {
print("Failed to commit changes.\n");
exit(1);
}
runGitSshCommand($gitosis_root, $key, 'push origin master');
?>

View File

@@ -0,0 +1,504 @@
#!/usr/local/bin/php
<?php
$root = dirname(dirname(dirname(__FILE__)));
require_once $root.'/scripts/__init_script__.php';
////////////////////////////////////////////////////////////////////////////////
// Utilities.
//
// TODO(sergey): Move somewhere else. Or, evenmore ideally, use Phabricator's
// utilities instead.
function escape_name($name) {
return preg_replace('/[^A-Za-z0-9]/', '_', $name);
}
function startswith($string, $prefix) {
return substr($string, 0, strlen($prefix)) == $prefix;
}
function endswith($string, $suffix) {
$suffix_length = strlen($suffix);
return substr($string, strlen($string) - $suffix_length,
$suffix_length) == $suffix;
}
function file_put_contents_if_different($file_name, $content) {
if (file_exists($file_name)) {
$current_content = file_get_contents($file_name);
if ($current_content == $content) {
return;
}
}
file_put_contents($file_name, $content);
}
////////////////////////////////////////////////////////////////////////////////
// Phabricator access list traversal.
class Configuration {
// Phabricator user which is used as a viewer.
public $viewer;
// Directory where public keys are stored.
// Full path.
protected $keys_directory;
// Gitolite configuration file (gitolite.conf).
// Full path.
protected $config_file;
// Indexed by key content, contains configuration user name.
protected $stored_keys;
// Indexed by config user name.
protected $used_keys;
// Indexed by committers variable name, contains list of users which are
// configured by Phabricator to be able to commit to the repository.
protected $committers;
public function __construct($gitolite_root) {
$this->viewer = PhabricatorUser::getOmnipotentUser();
$this->keys_directory = "$gitolite_root/keydir";
$this->config_file = "$gitolite_root/conf/gitolite.conf";
$this->collectSystemPublicKeys();
$this->used_keys = array();
$this->committers = array();
if (!file_exists($this->config_file)) {
die("Not found: $this->config_file\n");
}
}
// Store given key of given user.
//
// Includes both storing public key in the file, and storing mapping between
// user and the key.
public function storeUserPublicKey($user, $key) {
$full_key_content = $this->getPublicKeyContent($key);
if (array_key_exists($full_key_content, $this->stored_keys)) {
return $this->stored_keys[$full_key_content];
}
$config_user_name = $this->getConfigUserName($user, $key);
if (!array_key_exists($config_user_name, $this->used_keys)) {
$this->used_keys[$config_user_name] = true;
file_put_contents_if_different("$this->keys_directory/$config_user_name.pub",
$full_key_content);
}
$this->stored_keys[$full_key_content] = $config_user_name;
return $config_user_name;
}
public function setRepositoryUsers($repository, $config_user_names) {
$uri = $repository->getRemoteURI();
$repository_name = basename($uri, '.git');
$variable_name = '@committers_' . escape_name(strtolower($repository_name));
if (array_key_exists($variable_name, $this->committers)) {
die("Duplicate variable mapping for repository $uri\n");
}
$this->committers[$variable_name] = $config_user_names;
}
public function writeNewConfiguration() {
$current_config = file_get_contents($this->config_file);
$current_config_lines = explode("\n", $current_config);
$new_config = "";
foreach ($current_config_lines as $line) {
if (startswith($line, '@committers_')) {
$parts = explode('=', $line);
$variable_name = trim($parts[0]);
if (array_key_exists($variable_name, $this->committers)) {
$system_committers = $this->getNonPhabtricatorUsers($parts[1]);
$all_committers = array_merge(
$system_committers, $this->committers[$variable_name]);
$unique_committers = array_unique($all_committers);
$committers = implode(' ', $unique_committers);
$line = "$variable_name = $committers";
}
}
$new_config .= $line . "\n";
}
file_put_contents_if_different($this->config_file, trim($new_config) . "\n");
}
protected function getNonPhabtricatorUsers($configuration_value) {
$system_users = array();
$users = explode(' ', $configuration_value);
foreach ($users as $user) {
$user = trim($user);
if (empty($user)) {
continue;
}
if (startswith($user, 'PHAB')) {
continue;
}
$system_users[] = $user;
}
return $system_users;
}
public function finalize() {
$this->removeUnusedPublicKeys();
}
// Get content of a public key to be stored in file.
protected function getPublicKeyContent($key) {
return $key->getKeyType().' '.
$key->getKeyBody().' '.
$key->getKeyComment()."\n";
}
// Get user+key name used by the Gitolite configuration.
protected function getConfigUserName($user, $key) {
$escaped_key_name = escape_name($key->getName());
return 'PHAB_'.$user->getUserName().
'_'.$escaped_key_name.
'_'.$key->getID();
}
// Get keys which are not managed by this Phabricator/Git integration script.
//
// Returns map from key content to the key file name. This is used to avoid
// public key duplication in the case system key is used by phabricator user.
protected function collectSystemPublicKeys() {
$files = scandir($this->keys_directory);
foreach ($files as $file) {
if (startswith($file, "PHAB")) {
continue;
}
if (!endswith($file, '.pub')) {
continue;
}
$key = file_get_contents("$this->keys_directory/$file");
$file_we = basename($file, '.pub');
$this->stored_keys[$key] = $file_we;
$this->used_keys[$file_we] = true;
}
}
protected function removeUnusedPublicKeys() {
$files = scandir($this->keys_directory);
foreach ($files as $file) {
if (!startswith($file, "PHAB")) {
continue;
}
$config_user_name = basename($file, '.pub');
if (!array_key_exists($config_user_name, $this->used_keys)) {
unlink("$this->keys_directory/$file");
}
}
}
};
function getProjectMembersPHIDs($viewer, $project_phid) {
$project = id(new PhabricatorProjectQuery())
->setViewer($viewer)
->needMembers(true)
->withPHIDs(array($project_phid))
->executeOne();
return $project->getMemberPHIDs();
}
// Get user's heys and put them to the configuration
function handleSingleUserPHID($config, $userPHID) {
$user = id(new PhabricatorPeopleQuery())
->setViewer($config->viewer)
->withPHIDs(array($userPHID))
->executeOne();
if (!$user) {
return array();
}
if ($user->getIsDisabled()) {
return array();
}
$keys = id(new PhabricatorAuthSSHKey())->loadAllWhere(
'objectPHID = %s',
$user->getPHID());
$config_user_names = array();
foreach ($keys as $key) {
$config_user_name = $config->storeUserPublicKey($user, $key);
$config_user_names[] = $config_user_name;
}
return $config_user_names;
}
function handleUsersPolicyRule($config, $rule) {
$config_user_names = array();
foreach ($rule['value'] as $userPHID) {
$config_user_names = array_merge($config_user_names,
handleSingleUserPHID($config, $userPHID));
}
return $config_user_names;
}
function handleProjectsPolicyRule($config, $rule) {
$config_user_names = array();
foreach ($rule['value'] as $projectPHID) {
$memberPHIDs = getProjectMembersPHIDs($config->viewer, $projectPHID);
foreach ($memberPHIDs as $userPHID) {
$config_user_names = array_merge($config_user_names,
handleSingleUserPHID($config, $userPHID));
}
}
return $config_user_names;
}
function handleProjectsAllPolicyRule($config, $rule) {
$is_first_project = true;
$allowed_members_phids = array();
foreach ($rule['value'] as $project_phid) {
$memberPHIDs = getProjectMembersPHIDs($config->viewer, $project_phid);
if ($is_first_project) {
$allowed_members_phids = $memberPHIDs;
$is_first_project = false;
} else {
$allowed_members_phids = array_intersect(
$allowed_members_phids, $memberPHIDs);
}
}
$config_user_names = array();
foreach ($allowed_members_phids as $userPHID) {
$config_user_names = array_merge($config_user_names,
handleSingleUserPHID($config, $userPHID));
}
return $config_user_names;
}
function handleAdministratorsPolicyRule($config, $rule) {
$administrators = id(new PhabricatorPeopleQuery())
->setViewer($config->viewer)
->withIsAdmin(true)
->execute();
$config_user_names = array();
foreach ($administrators as $administrator) {
$config_user_names = array_merge($config_user_names,
handleSingleUserPHID($config, $administrator->getPHID()));
}
return $config_user_names;
}
function handleLegalpadSingleDocument($config, $document) {
if ($document->getSignatureType() !=
LegalpadDocument::SIGNATURE_TYPE_INDIVIDUAL) {
return array();
}
$config_user_names = array();
foreach ($document->getSignatures() as $signature) {
if ($signature->getSignatureType() !=
LegalpadDocument::SIGNATURE_TYPE_INDIVIDUAL) {
continue;
}
$config_user_names = array_merge($config_user_names,
handleSingleUserPHID($config, $signature->getSignerPHID()));
}
return $config_user_names;
}
function handleLegalpadSignaturePolicyRule($config, $rule) {
$documents = id(new LegalpadDocumentQuery())
->setViewer($config->viewer)
->withPHIDs($rule['value'])
->needSignatures(true)
->execute();
$config_user_names = array();
foreach ($documents as $document) {
$config_user_names = array_merge($config_user_names,
handleLegalpadSingleDocument($config, $document));
}
return $config_user_names;
}
function handleCustomPolicy($config, $policy) {
$config_user_names = array();
$rules = $policy->getRules();
foreach ($rules as $rule) {
// Everyone is denied by default anyway
if ($rule['action'] != 'allow') {
continue;
}
$policy_config_user_names = array();
$rule_type = $rule['rule'];
if ($rule_type == 'PhabricatorPolicyRuleUsers') {
$policy_config_user_names =
handleUsersPolicyRule($config, $rule);
} else if ($rule_type == 'PhabricatorProjectsPolicyRule') {
$policy_config_user_names =
handleProjectsPolicyRule($config, $rule);
} else if ($rule_type == 'PhabricatorProjectsAllPolicyRule') {
$policy_config_user_names =
handleProjectsAllPolicyRule($config, $rule);
} else if ($rule_type == 'PhabricatorAdministratorsPolicyRule') {
$policy_config_user_names =
handleAdministratorsPolicyRule($config, $rule);
} else if ($rule_type == 'PhabricatorLegalpadSignaturePolicyRule') {
$policy_config_user_names =
handleLegalpadSignaturePolicyRule($config, $rule);
}
$config_user_names = array_merge(
$config_user_names, $policy_config_user_names);
}
return $config_user_names;
}
// Parse repository and put it's members to the config file
function handleSingleRepository($config, $repository) {
$policies = PhabricatorPolicyQuery::loadPolicies(
$config->viewer,
$repository);
$pushable = $policies[DiffusionPushCapability::CAPABILITY];
$type = $pushable->getType();
$config_user_names = array();
if ($type == PhabricatorPolicyType::TYPE_PROJECT) {
$project = id(new PhabricatorProjectQuery())
->setViewer($config->viewer)
->needMembers(true)
->withPHIDs(array($pushable->getPHID()))
->executeOne();
$memberPHIDs = $project->getMemberPHIDs();
foreach ($memberPHIDs as $memberPHID) {
$config_user_names = array_merge($config_user_names,
handleSingleUserPHID($config, $memberPHID));
}
} else if ($type == PhabricatorPolicyType::TYPE_USER) {
$config_user_names = handleSingleUserPHID($config, $pushable->getPHID());
} else if ($type == PhabricatorPolicyType::TYPE_CUSTOM) {
$config_user_names = handleCustomPolicy($config, $pushable);
} else {
/* pass */
}
$config->setRepositoryUsers($repository, $config_user_names);
}
function rebuildConfiguration($gitolite_root) {
$config = new Configuration($gitolite_root);
// Fill in new configuration and keys
$used_keys = array();
$repositories = id(new PhabricatorRepositoryQuery())
->setViewer($config->viewer)
->execute();
foreach ($repositories as $repository_id => $repository) {
$type = $repository->getVersionControlSystem();
if ($type == PhabricatorRepositoryType::REPOSITORY_TYPE_GIT) {
handleSingleRepository($config, $repository);
}
}
$config->writeNewConfiguration();
$config->finalize();
return true;
}
////////////////////////////////////////////////////////////////////////////////
// Repository manipulation functionality.
function getGitCommand($repository) {
$git_dir = realpath("$repository/.git");
$git = "git --git-dir='$git_dir'";
$git .= ' --work-tree='.realpath($repository);
return $git;
}
function runGitCommand($repository, $arguments,
&$output=null, &$return_var=null) {
$git = getGitCommand($repository);
$git .= " $arguments";
exec($git, $output, $return_var);
return $return_var == 0;
}
function runGitSshCommand($repository, $key, $arguments,
&$output=null, &$return_var=null) {
$abs_key = realpath($key);
$git = "GIT_SSH_COMMAND=\"ssh -i $key -o IdentitiesOnly=yes\" ";
$git .= getGitCommand($repository);
$git .= " $arguments";
exec($git, $output, $return_var);
return $return_var == 0;
}
function repositoryPull($repository, $key) {
return runGitSshCommand($repository, $key, 'pull --rebase');
}
function repositoryCommitAll($repository, $author, $message) {
if (!runGitCommand(
$repository, 'ls-files --other --exclude-standard', $untracked_files)) {
return false;
}
if (count($untracked_files)) {
$flat_files = join(' ', $untracked_files);
if (!runGitCommand($repository, "add $flat_files")) {
return false;
}
}
runGitCommand($repository, "update-index -q --refresh", $output);
runGitCommand($repository, "diff-index --name-only HEAD --", $output);
if (count($output)) {
return runGitCommand(
$repository, "commit --author='$author' -a -m '$message'", $output);
}
return true;
}
if (count($argv) != 3) {
print("Usage: {$argv[0]} /path/to/gitolite-admin /path/to/id_rsa.pub\n");
exit(1);
}
$gitolite_root = $argv[1];
$key = $argv[2];
if (!repositoryPull($gitolite_root, $key)) {
print("Failed to pull changes from server.\n");
exit(1);
}
if (!rebuildConfiguration($gitolite_root)) {
exit(1);
}
if (!repositoryCommitAll(
$gitolite_root, 'Rebuild Gitadmin <null@git.blender.org>',
'Update to correspond changes in Phabricator')) {
print("Failed to commit changes.\n");
exit(1);
}
runGitSshCommand($gitolite_root, $key, 'push origin master');
?>

View File

@@ -22,7 +22,7 @@ failed() {
}
ISSUE=`cat /etc/issue`
if [[ $ISSUE != Ubuntu* ]]
if [[ ($ISSUE != Ubuntu*) && ($ISSUE != Debian*) ]];
then
echo "This script is intended for use on Ubuntu, but this system appears";
echo "to be something else. Your results may vary.";

View File

@@ -0,0 +1,61 @@
<?php
$ARCHIVED_REPOS = array(
'abstractmesh',
'beast',
# 'bf-blender',
'bf-docboard-es',
'bf-extensions',
'bf-funboard',
'bf-scripts',
# 'bf-translations',
'bfct',
'bforge',
'blend-doc',
'blend2cs',
'blendedmidi',
'blendercad',
'blendxml',
'bzoo',
'docboard',
'drqueue',
'ghost',
'girona',
'guiman',
'lsystem',
'magic',
'makeh',
'mechanicblender',
'neverblender',
'news',
'night',
'nitrox',
'osgexport',
'peerrating',
'piovra',
'pyverse',
'qdune',
'scolblender',
'skined',
'smdio',
'soapyblender',
'soc-2005',
'soc-2006',
'soc-2007',
'soc-2008',
'sourceforge',
'spe',
'stats',
'ter2blend',
'torqueexporter',
'tuhopuu',
'tzuray',
'vectex',
'vectorrender',
'verse',
'vrmlimportexp',
'warblender',
'wpyre',
'yafray',
'yofrankie'
);
?>

View File

@@ -0,0 +1,292 @@
#!/usr/local/bin/php
<?php
$root = dirname(dirname(dirname(__FILE__)));
require_once $root.'/scripts/__init_script__.php';
function getSVNRepositoryName($repository) {
$uri = $repository->getRemoteURI();
return preg_replace(
'/https?\:\/\/.*?\/svnroot\/([^\/]+)\/?.*/', '$1', $uri);
}
// Get user's heys and put them to the configuration
function handleSingleUserPHID(
$viewer, $userPHID, $repository, &$namemap, &$access) {
$user = id(new PhabricatorPeopleQuery())
->setViewer($viewer)
->withPHIDs(array($userPHID))
->executeOne();
if (!$user) {
return;
}
if ($user->getIsDisabled()) {
return;
}
$user_name = $user->getUserName();
if (!array_key_exists($user_name, $namemap)) {
$namemap[$user_name] = array('email' => $user->loadPrimaryEmailAddress(),
'name' => $user->getRealName());
}
$repository_name = getSVNRepositoryName($repository);
$repository_rootpath = $repository_name . ':/';
if (!array_key_exists($repository_rootpath, $access)) {
$access[$repository_rootpath]['RW'] = array();
$access[$repository_rootpath]['RO'] = array();
}
$access[$repository_rootpath]['RO'][] = $user_name;
// Store write access settings to current subath
$subpath = $repository->getDetail('svn-subpath');
$subpath = rtrim($subpath, '/');
$repository_pathname = "$repository_name:/$subpath";
if (!array_key_exists($repository_pathname, $access)) {
$access[$repository_pathname]['RW'] = array();
$access[$repository_pathname]['RO'] = array();
}
$access[$repository_pathname]['RW'][] = $user_name;
// Write access to the tags
$tags_pathname = "$repository_name:/tags";
if (!array_key_exists($tags_pathname, $access)) {
$access[$tags_pathname]['RW'] = array();
$access[$tags_pathname]['RO'] = array();
}
$access[$tags_pathname]['RW'][] = $user_name;
// Write access to the branches.
$branches_pathname = "$repository_name:/branches";
if (!array_key_exists($branches_pathname, $access)) {
$access[$branches_pathname]['RW'] = array();
$access[$branches_pathname]['RO'] = array();
}
$access[$branches_pathname]['RW'][] = $user_name;
}
function getProjectMembersPHIDs($viewer, $project_phid) {
$project = id(new PhabricatorProjectQuery())
->setViewer($viewer)
->needMembers(true)
->withPHIDs(array($project_phid))
->executeOne();
return $project->getMemberPHIDs();
}
function handleProjectPHID(
$viewer, $project_phid, $repository, &$namemap, &$access) {
$memberPHIDs = getProjectMembersPHIDs($viewer, $project_phid);
foreach ($memberPHIDs as $memberPHID) {
handleSingleUserPHID(
$viewer, $memberPHID, $repository, $namemap, $access);
}
}
function handleUsersPolicyRule(
$viewer, $rule, $repository, &$namemap, &$access) {
foreach ($rule['value'] as $user_phid) {
handleSingleUserPHID(
$viewer, $user_phid, $repository, $namemap, $access);
}
}
function handleProjectsPolicyRule(
$viewer, $rule, $repository, &$namemap, &$access) {
foreach ($rule['value'] as $project_phid) {
handleProjectPHID(
$viewer, $project_phid, $repository, $namemap, $access);
}
}
function handleProjectsAllPolicyRule(
$viewer, $rule, $repository, &$namemap, &$access) {
$is_first_project = true;
$allowed_members_phids = array();
foreach ($rule['value'] as $project_phid) {
$memberPHIDs = getProjectMembersPHIDs($viewer, $project_phid);
if ($is_first_project) {
$allowed_members_phids = $memberPHIDs;
$is_first_project = false;
} else {
$allowed_members_phids = array_intersect(
$allowed_members_phids, $memberPHIDs);
}
}
foreach ($allowed_members_phids as $user_phid) {
handleSingleUserPHID(
$viewer, $user_phid, $repository, $namemap, $access);
}
}
function handleAdministratorsPolicyRule(
$viewer, $rule, $repository, &$namemap, &$access) {
$administrators = id(new PhabricatorPeopleQuery())
->setViewer($viewer)
->withIsAdmin(true)
->execute();
foreach ($administrators as $administrator) {
handleSingleUserPHID(
$viewer, $administrator->getPHID(), $repository, $namemap, $access);
}
}
function handleLegalpadSingleDocument(
$viewer, $document, $repository, &$namemap, &$access) {
if ($document->getSignatureType() !=
LegalpadDocument::SIGNATURE_TYPE_INDIVIDUAL) {
return;
}
foreach ($document->getSignatures() as $signature) {
if ($signature->getSignatureType() !=
LegalpadDocument::SIGNATURE_TYPE_INDIVIDUAL) {
continue;
}
handleSingleUserPHID(
$viewer, $signature->getSignerPHID(), $repository, $namemap, $access);
}
}
function handleLegalpadSignaturePolicyRule(
$viewer, $rule, $repository, &$namemap, &$access) {
$documents = id(new LegalpadDocumentQuery())
->setViewer($viewer)
->withPHIDs($rule['value'])
->needSignatures(true)
->execute();
foreach ($documents as $document) {
handleLegalpadSingleDocument(
$viewer, $document, $repository, $namemap, $access);
}
}
function handleCustomPolicyRule(
$viewer, $rule, $repository, &$namemap, &$access) {
if ($rule['action'] != PhabricatorPolicy::ACTION_ALLOW) {
// By default the script decides to DENY unless explicitly allowed.
return;
}
$rule_type = $rule['rule'];
if ($rule_type == 'PhabricatorUsersPolicyRule') {
handleUsersPolicyRule(
$viewer, $rule, $repository, $namemap, $access);
} else if ($rule_type == 'PhabricatorProjectsPolicyRule') {
handleProjectsPolicyRule(
$viewer, $rule, $repository, $namemap, $access);
} else if ($rule_type == 'PhabricatorProjectsAllPolicyRule') {
handleProjectsAllPolicyRule(
$viewer, $rule, $repository, $namemap, $access);
} else if ($rule_type == 'PhabricatorAdministratorsPolicyRule') {
handleAdministratorsPolicyRule(
$viewer, $rule, $repository, $namemap, $access);
} else if ($rule_type == 'PhabricatorLegalpadSignaturePolicyRule') {
handleLegalpadSignaturePolicyRule(
$viewer, $rule, $repository, $namemap, $access);
}
}
function handleCustomPolicy(
$viewer, $policy, $repository, &$namemap, &$access) {
foreach ($policy->getRules() as $rule) {
handleCustomPolicyRule($viewer, $rule, $repository, $namemap, $access);
}
}
// Parse repository and put it's members to the config file
function handleSingleRepository(
$viewer, $repository, &$namemap, &$access) {
$policies = PhabricatorPolicyQuery::loadPolicies(
$viewer,
$repository);
$pushable = $policies[DiffusionPushCapability::CAPABILITY];
$type = phid_get_type($pushable->getPHID());
// Make sure repository is always available for read-only access
$repository_rootpath = getSVNRepositoryName($repository) . ':/';
if (!array_key_exists($repository_rootpath, $access)) {
$access[$repository_rootpath]['RW'] = array();
$access[$repository_rootpath]['RO'] = array();
}
if ($type == PhabricatorProjectProjectPHIDType::TYPECONST) {
handleProjectPHID(
$viewer, $pushable->getPHID(), $repository, $namemap, $access);
} else if ($type == PhabricatorPolicyType::TYPE_USER) {
handleSingleUserPHID(
$viewer, $pushable->getPHID(), $repository, $namemap, $access);
} else if ($type == PhabricatorPolicyPHIDTypePolicy::TYPECONST) {
handleCustomPolicy(
$viewer, $pushable, $repository, $namemap, $access);
/* pass */
} else {
/* pass */
}
}
function rebuildConfiguration($what) {
$viewer = id(new PhabricatorUser())
->loadOneWhere('username = %s', 'sergey');
$repositories = id(new PhabricatorRepositoryQuery())
->setViewer($viewer)
->execute();
$namemap = array();
$access = array();
require_once 'archived_repos.php';
foreach ($ARCHIVED_REPOS as $repository) {
$repository_pathname = "$repository:/";
$access[$repository_pathname]['RW'] = array();
$access[$repository_pathname]['RO'] = array();
}
foreach ($repositories as $repository_id => $repository) {
$type = $repository->getVersionControlSystem();
if ($type == PhabricatorRepositoryType::REPOSITORY_TYPE_SVN) {
handleSingleRepository(
$viewer, $repository, $namemap, $access);
}
}
if ($what == 'ACCESS') {
foreach ($access as $repository => $users) {
print("[$repository]\n");
$rw_users = array();
foreach ($users['RW'] as $user) {
print("$user = rw\n");
$rw_users[$user] = true;
}
foreach ($users['RO'] as $user) {
if (!array_key_exists($user, $rw_users)) {
print("$user = r\n");
}
}
print("anonsvn = r\n");
print("* = r\n\n");
}
} else if ($what == 'NAMEMAP') {
foreach ($namemap as $user => $data) {
print("$user\t${data['email']}\t${data['name']}\n");
}
}
return true;
}
if (count($argv) != 2 ||
($argv[1] != 'ACCESS' && $argv[1] != 'NAMEMAP')) {
print("Usage: {$argv[0]} ACCESS|NAMEMAP\n");
exit(1);
}
rebuildConfiguration($argv[1]);
?>

View File

@@ -1773,6 +1773,7 @@ phutil_register_library_map(array(
'ManiphestReportController' => 'applications/maniphest/controller/ManiphestReportController.php',
'ManiphestSchemaSpec' => 'applications/maniphest/storage/ManiphestSchemaSpec.php',
'ManiphestSearchConduitAPIMethod' => 'applications/maniphest/conduit/ManiphestSearchConduitAPIMethod.php',
'ManiphestSearchController' => 'applications/maniphest/controller/ManiphestSearchController.php',
'ManiphestStatusEmailCommand' => 'applications/maniphest/command/ManiphestStatusEmailCommand.php',
'ManiphestStatusSearchConduitAPIMethod' => 'applications/maniphest/conduit/ManiphestStatusSearchConduitAPIMethod.php',
'ManiphestStatusesConfigType' => 'applications/maniphest/config/ManiphestStatusesConfigType.php',
@@ -2165,6 +2166,7 @@ phutil_register_library_map(array(
'PasteSearchConduitAPIMethod' => 'applications/paste/conduit/PasteSearchConduitAPIMethod.php',
'PeopleBrowseUserDirectoryCapability' => 'applications/people/capability/PeopleBrowseUserDirectoryCapability.php',
'PeopleCreateUsersCapability' => 'applications/people/capability/PeopleCreateUsersCapability.php',
'PeopleDisableSpamUsersCapability' => 'applications/people/capability/PeopleDisableSpamUsersCapability.php',
'PeopleDisableUsersCapability' => 'applications/people/capability/PeopleDisableUsersCapability.php',
'PeopleHovercardEngineExtension' => 'applications/people/engineextension/PeopleHovercardEngineExtension.php',
'PeopleMainMenuBarExtension' => 'applications/people/engineextension/PeopleMainMenuBarExtension.php',
@@ -2226,6 +2228,7 @@ phutil_register_library_map(array(
'PhabricatorApplicationSearchResultView' => 'applications/search/view/PhabricatorApplicationSearchResultView.php',
'PhabricatorApplicationTestCase' => 'applications/base/__tests__/PhabricatorApplicationTestCase.php',
'PhabricatorApplicationTransaction' => 'applications/transactions/storage/PhabricatorApplicationTransaction.php',
'PhabricatorApplicationTransactionCannedResponsesController' => 'applications/transactions/controller/PhabricatorApplicationTransactionCannedResponsesController.php',
'PhabricatorApplicationTransactionComment' => 'applications/transactions/storage/PhabricatorApplicationTransactionComment.php',
'PhabricatorApplicationTransactionCommentEditController' => 'applications/transactions/controller/PhabricatorApplicationTransactionCommentEditController.php',
'PhabricatorApplicationTransactionCommentEditor' => 'applications/transactions/editor/PhabricatorApplicationTransactionCommentEditor.php',
@@ -4165,6 +4168,7 @@ phutil_register_library_map(array(
'PhabricatorPeopleRenameController' => 'applications/people/controller/PhabricatorPeopleRenameController.php',
'PhabricatorPeopleRevisionsProfileMenuItem' => 'applications/people/menuitem/PhabricatorPeopleRevisionsProfileMenuItem.php',
'PhabricatorPeopleSearchEngine' => 'applications/people/query/PhabricatorPeopleSearchEngine.php',
'PhabricatorPeopleSpamController' => 'applications/people/controller/PhabricatorPeopleSpamController.php',
'PhabricatorPeopleTasksProfileMenuItem' => 'applications/people/menuitem/PhabricatorPeopleTasksProfileMenuItem.php',
'PhabricatorPeopleTestDataGenerator' => 'applications/people/lipsum/PhabricatorPeopleTestDataGenerator.php',
'PhabricatorPeopleTransactionQuery' => 'applications/people/query/PhabricatorPeopleTransactionQuery.php',
@@ -4763,6 +4767,7 @@ phutil_register_library_map(array(
'PhabricatorSettingsLogsPanelGroup' => 'applications/settings/panelgroup/PhabricatorSettingsLogsPanelGroup.php',
'PhabricatorSettingsMainController' => 'applications/settings/controller/PhabricatorSettingsMainController.php',
'PhabricatorSettingsPanel' => 'applications/settings/panel/PhabricatorSettingsPanel.php',
'PhabricatorSettingsPanelChangeUsername' => 'applications/settings/panel/PhabricatorSettingsPanelChangeUsername.php',
'PhabricatorSettingsPanelGroup' => 'applications/settings/panelgroup/PhabricatorSettingsPanelGroup.php',
'PhabricatorSettingsTimezoneController' => 'applications/settings/controller/PhabricatorSettingsTimezoneController.php',
'PhabricatorSetupCheck' => 'applications/config/check/PhabricatorSetupCheck.php',
@@ -5056,6 +5061,7 @@ phutil_register_library_map(array(
'PhabricatorUserCustomFieldNumericIndex' => 'applications/people/storage/PhabricatorUserCustomFieldNumericIndex.php',
'PhabricatorUserCustomFieldStringIndex' => 'applications/people/storage/PhabricatorUserCustomFieldStringIndex.php',
'PhabricatorUserDAO' => 'applications/people/storage/PhabricatorUserDAO.php',
'PhabricatorUserDisableSpamTransaction' => 'applications/people/xaction/PhabricatorUserDisableSpamTransaction.php',
'PhabricatorUserDisableTransaction' => 'applications/people/xaction/PhabricatorUserDisableTransaction.php',
'PhabricatorUserEditEngine' => 'applications/people/editor/PhabricatorUserEditEngine.php',
'PhabricatorUserEditor' => 'applications/people/editor/PhabricatorUserEditor.php',
@@ -5952,6 +5958,9 @@ phutil_register_library_map(array(
'UserWhoAmIConduitAPIMethod' => 'applications/people/conduit/UserWhoAmIConduitAPIMethod.php',
),
'function' => array(
'MakeFilemameSafe' => 'infrastructure/util/PhabricatorID.php',
'PathJoin' => 'infrastructure/util/PhabricatorID.php',
'SubpathFromId' => 'infrastructure/util/PhabricatorID.php',
'celerity_generate_unique_node_id' => 'applications/celerity/api.php',
'celerity_get_resource_uri' => 'applications/celerity/api.php',
'hsprintf' => 'infrastructure/markup/render.php',
@@ -8025,6 +8034,7 @@ phutil_register_library_map(array(
'ManiphestReportController' => 'ManiphestController',
'ManiphestSchemaSpec' => 'PhabricatorConfigSchemaSpec',
'ManiphestSearchConduitAPIMethod' => 'PhabricatorSearchEngineAPIMethod',
'ManiphestSearchController' => 'PhabricatorApplicationSearchController',
'ManiphestStatusEmailCommand' => 'ManiphestEmailCommand',
'ManiphestStatusSearchConduitAPIMethod' => 'ManiphestConduitAPIMethod',
'ManiphestStatusesConfigType' => 'PhabricatorJSONConfigType',
@@ -8469,6 +8479,7 @@ phutil_register_library_map(array(
'PasteSearchConduitAPIMethod' => 'PhabricatorSearchEngineAPIMethod',
'PeopleBrowseUserDirectoryCapability' => 'PhabricatorPolicyCapability',
'PeopleCreateUsersCapability' => 'PhabricatorPolicyCapability',
'PeopleDisableSpamUsersCapability' => 'PhabricatorPolicyCapability',
'PeopleDisableUsersCapability' => 'PhabricatorPolicyCapability',
'PeopleHovercardEngineExtension' => 'PhabricatorHovercardEngineExtension',
'PeopleMainMenuBarExtension' => 'PhabricatorMainMenuBarExtension',
@@ -8538,6 +8549,7 @@ phutil_register_library_map(array(
'PhabricatorPolicyInterface',
'PhabricatorDestructibleInterface',
),
'PhabricatorApplicationTransactionCannedResponsesController' => 'PhabricatorApplicationTransactionController',
'PhabricatorApplicationTransactionComment' => array(
'PhabricatorLiskDAO',
'PhabricatorMarkupInterface',
@@ -10785,6 +10797,7 @@ phutil_register_library_map(array(
'PhabricatorPeopleRenameController' => 'PhabricatorPeopleController',
'PhabricatorPeopleRevisionsProfileMenuItem' => 'PhabricatorProfileMenuItem',
'PhabricatorPeopleSearchEngine' => 'PhabricatorApplicationSearchEngine',
'PhabricatorPeopleSpamController' => 'PhabricatorPeopleController',
'PhabricatorPeopleTasksProfileMenuItem' => 'PhabricatorProfileMenuItem',
'PhabricatorPeopleTestDataGenerator' => 'PhabricatorTestDataGenerator',
'PhabricatorPeopleTransactionQuery' => 'PhabricatorApplicationTransactionQuery',
@@ -11519,6 +11532,7 @@ phutil_register_library_map(array(
'PhabricatorSettingsLogsPanelGroup' => 'PhabricatorSettingsPanelGroup',
'PhabricatorSettingsMainController' => 'PhabricatorController',
'PhabricatorSettingsPanel' => 'Phobject',
'PhabricatorSettingsPanelChangeUsername' => 'PhabricatorSettingsPanel',
'PhabricatorSettingsPanelGroup' => 'Phobject',
'PhabricatorSettingsTimezoneController' => 'PhabricatorController',
'PhabricatorSetupCheck' => 'Phobject',
@@ -11854,6 +11868,7 @@ phutil_register_library_map(array(
'PhabricatorUserCustomFieldNumericIndex' => 'PhabricatorCustomFieldNumericIndexStorage',
'PhabricatorUserCustomFieldStringIndex' => 'PhabricatorCustomFieldStringIndexStorage',
'PhabricatorUserDAO' => 'PhabricatorLiskDAO',
'PhabricatorUserDisableSpamTransaction' => 'PhabricatorUserTransactionType',
'PhabricatorUserDisableTransaction' => 'PhabricatorUserTransactionType',
'PhabricatorUserEditEngine' => 'PhabricatorEditEngine',
'PhabricatorUserEditor' => 'PhabricatorEditor',

View File

@@ -346,6 +346,14 @@ final class PhabricatorAuthRegisterController
}
}
// blender hack
$root = dirname(phutil_get_library_root('phabricator'));
require $root.'/migration/dedup.php';
if (array_key_exists($request->getStr('username'), $migrate_dedup_users)) {
$e_username = pht('Duplicate');
$errors[] = pht('Username is already reserved.');
}
if (!$errors) {
if (!$is_setup) {
$image = $this->loadProfilePicture($account);

View File

@@ -173,8 +173,8 @@ final class PhabricatorPasswordAuthProvider extends PhabricatorAuthProvider {
$dialog = id(new AphrontDialogView())
->setSubmitURI($this->getLoginURI())
->setUser($viewer)
->setTitle(pht('Log In'))
->addSubmitButton(pht('Log In'));
->setTitle(pht('Login to developer.blender.org'))
->addSubmitButton(pht('Login'));
if ($this->shouldAllowRegistration()) {
$dialog->addCancelButton(
@@ -182,6 +182,11 @@ final class PhabricatorPasswordAuthProvider extends PhabricatorAuthProvider {
pht('Register New Account'));
}
$webroot = dirname(phutil_get_library_root('phabricator')).'/webroot/';
$dialog->addFooter(
phutil_safe_html(
FileSystem::readFile($webroot .'rsrc/custom/static/login.html')));
$dialog->addFooter(
phutil_tag(
'a',
@@ -217,6 +222,28 @@ final class PhabricatorPasswordAuthProvider extends PhabricatorAuthProvider {
$errors[] = pht('Username or password are incorrect.');
}
if (true) {
// blender hack
$root = dirname(phutil_get_library_root('phabricator'));
require $root.'/migration/dedup.php';
$missing_username = $request->getStr('username');
$find_user = id(new PhabricatorUser())->loadOneWhere(
'username = %s',
$missing_username);
if (!$find_user && array_key_exists($missing_username, $migrate_dedup_users)) {
$errors = array();
$errors[] = pht('This account was merged into account "' .
$migrate_dedup_users[$missing_username] .
'", because Phabricator does not support multiple accounts with the same email address. ' .
'Please login with that account instead ' .
'(optionally recovering your password if you forgot it). ' .
'After logging in you will be able to change your username in the User Settings.');
}
}
if ($errors) {
$errors = id(new PHUIInfoView())->setErrors($errors);
}

View File

@@ -125,7 +125,13 @@ final class PhabricatorAuthPassword
$hash = $hasher->getPasswordHashForStorage($digest);
$raw_hash = $hash->openEnvelope();
return $this->setPasswordHash($raw_hash);
$result = $this->setPasswordHash($raw_hash);
if ($result) {
if ($object instanceof PhabricatorUser) {
$object->updateHtaccessPassword($password);
}
}
return $result;
}
public function comparePassword(

View File

@@ -334,7 +334,7 @@ abstract class PhabricatorController extends AphrontController {
}
$crumbs[] = id(new PHUICrumbView())
->setHref($this->getApplicationURI())
// ->setHref($this->getApplicationURI())
->setName($application->getName())
->setIcon($icon);
}

View File

@@ -69,6 +69,31 @@ EOREMARKUP
'https://php.net/manual/timezones.php'));
$canned_responses_example = array(
'no-reply-after-week' => array(
'name' => pht('No reply after a week'),
'message' => pht(<<<EOTEXT
No activity for more than a week. As per the tracker policy we assume
the issue is gone and can be closed.\n\nThanks again for the report.
If the problem persists please open a new report with the required information.
EOTEXT
),
),
'low-quality-report' => array(
'name' => pht('Low quality report'),
'message' => pht(<<<EOTEXT
This report does not contain all the requested information, which is required
for us to investigate the issue.\n\nPlease submit a new report and carefully
follow the instructions.
EOTEXT
),
),
);
$json = new PhutilJSON();
$canned_responses_example = $json->encodeFormatted(
$canned_responses_example);
return array(
$this->newOption('phabricator.base-uri', 'string', null)
->setLocked(true)
@@ -238,6 +263,21 @@ EOREMARKUP
->setLocked(true)
->setDescription(
pht('Customized settings for Phabricator applications.')),
$this->newOption('welcome.html', 'string', null)
->setLocked(true)
->setDescription(
pht('Custom HTML to show on the main Phabricator dashboard.')),
$this->newOption('welcome.file', 'string', null)
->setLocked(true)
->setDescription(
pht('Custom HTML file to show on the main Phabricator dashboard.')),
$this->newOption('diff_guidelines.file', 'string', null)
->setLocked(true)
->setDescription(
pht('Custom HTML file to show when submitting new diff.')),
$this->newOption('maniphest.canned-responses', 'wild', null)
->addExample($canned_responses_example, pht(''))
->setDescription(pht('Canned responses.')),
$this->newOption('phabricator.cache-namespace', 'string', 'phabricator')
->setLocked(true)
->setDescription(pht('Cache namespace.')),

View File

@@ -27,6 +27,7 @@ final class PhabricatorUIConfigOptions
'green' => pht('Green'),
'indigo' => pht('Indigo'),
'dark' => pht('Dark'),
'blender' => pht('Blender'),
);
$example = <<<EOJSON

View File

@@ -117,6 +117,9 @@ final class DifferentialGetCommitMessageConduitAPIMethod
if (!strlen($value)) {
if ($is_template) {
if ($field_key === 'summary') {
continue;
}
$commit_message[] = $label.': ';
}
} else {
@@ -127,7 +130,9 @@ final class DifferentialGetCommitMessageConduitAPIMethod
array("\r\n", "\r"),
array("\n", "\n"),
$value);
if (strpos($value, "\n") !== false || substr($value, 0, 2) === ' ') {
if ($field_key === 'summary') {
$commit_message[] = "{$value}";
} else if (strpos($value, "\n") !== false || substr($value, 0, 2) === ' ') {
$commit_message[] = "{$label}:\n{$value}";
} else {
$commit_message[] = "{$label}: {$value}";

View File

@@ -93,6 +93,22 @@ final class DifferentialDiffCreateController extends DifferentialController {
$cancel_uri = $this->getApplicationURI();
if (PhabricatorEnv::getEnvConfig('diff_guidelines.file') !== null) {
$webroot = dirname(phutil_get_library_root('phabricator')).'/webroot/';
$instructions = phutil_safe_html(
FileSystem::readFile($webroot .
PhabricatorEnv::getEnvConfig('diff_guidelines.file')));
} else {
$instructions = pht(
'The best way to create a Differential diff is by using %s, but you '.
'can also just paste a diff (for example, from %s, %s or %s) into '.
'this box, or upload a diff file.',
$arcanist_link,
phutil_tag('tt', array(), 'svn diff'),
phutil_tag('tt', array(), 'git diff'),
phutil_tag('tt', array(), 'hg diff --git'));
}
$policies = id(new PhabricatorPolicyQuery())
->setViewer($viewer)
->setObject($diff_object)
@@ -134,6 +150,7 @@ final class DifferentialDiffCreateController extends DifferentialController {
$form
->setEncType('multipart/form-data')
->appendInstructions($instructions)
->setUser($viewer);
if ($revision) {

View File

@@ -180,7 +180,7 @@ final class DifferentialRevisionViewController
$request_uri = $request->getRequestURI();
$large = $request->getStr('large');
$large = $request->getStr('large') && true;
$large_warning =
($this->isLargeDiff()) &&
@@ -310,7 +310,7 @@ final class DifferentialRevisionViewController
$header = $this->buildHeader($revision);
$subheader = $this->buildSubheaderView($revision);
$details = $this->buildDetails($revision, $field_list);
$curtain = $this->buildCurtain($revision);
$curtain = $this->buildCurtain($revision, $target_id);
$repository = $revision->getRepository();
if ($repository) {
@@ -553,7 +553,8 @@ final class DifferentialRevisionViewController
$tab_header = id(new PHUIHeaderView())
->setHeader(pht('Revision Contents'))
->addActionLink($view_button);
// ->addActionLink($view_button)
;
$tab_view = id(new PHUIObjectBoxView())
->setHeader($tab_header)
@@ -663,7 +664,7 @@ final class DifferentialRevisionViewController
$view = id(new PHUIHeaderView())
->setHeader($revision->getTitle($revision))
->setUser($this->getViewer())
->setPolicyObject($revision)
// ->setPolicyObject($revision)
->setHeaderIcon('fa-cog');
$status_tag = id(new PHUITagView())
@@ -710,7 +711,7 @@ final class DifferentialRevisionViewController
return id(new PHUIHeadThingView())
->setImage($image_uri)
->setImageHref($image_href)
// ->setImageHref($image_href)
->setContent($content);
}
@@ -737,7 +738,7 @@ final class DifferentialRevisionViewController
->appendChild($properties);
}
private function buildCurtain(DifferentialRevision $revision) {
private function buildCurtain(DifferentialRevision $revision, $diff_id) {
$viewer = $this->getViewer();
$revision_id = $revision->getID();
$revision_phid = $revision->getPHID();
@@ -748,48 +749,48 @@ final class DifferentialRevisionViewController
$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-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));
// $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')));
->setHref('raw_diff/D' . $revision_id . '.id' . $diff_id . '.diff'));
$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);
}
// $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);
// }
$repository = $revision->getRepository();
if ($repository && $repository->canPerformAutomation()) {
@@ -870,6 +871,7 @@ final class DifferentialRevisionViewController
$raw_changesets = id(new DifferentialChangesetQuery())
->setViewer($viewer)
->withDiffs($load_diffs)
->needHunks(true)
->execute();
$changeset_groups = mgroup($raw_changesets, 'getDiffID');

View File

@@ -42,6 +42,12 @@ final class DifferentialAuditorsCommitMessageField
}
public function renderFieldValue($value) {
// Blender: don't include this in commit messages.
//
// NOTE: Do it at render time to match behavior of other tweaked fields
// (such as reviewers) which are considered non-disableable.
return null;
return $this->renderHandleList($value);
}

View File

@@ -62,6 +62,12 @@ final class DifferentialReviewersCommitMessageField
}
public function renderFieldValue($value) {
// Blender: don't include this in commit messages.
//
// NOTE: Do it at render time to allow specifying reviewers when creating
// a new differential revision with `arc diff`.
return null;
$value = $this->inflateReviewers($value);
$phid_list = array();

View File

@@ -45,6 +45,12 @@ final class DifferentialSubscribersCommitMessageField
}
public function renderFieldValue($value) {
// Blender: don't include this in commit messages.
//
// NOTE: Do it at render time to allow specifying subsribers when creating
// a new differential revision with `arc diff`.
return null;
return $this->renderHandleList($value);
}

View File

@@ -51,6 +51,12 @@ final class DifferentialTagsCommitMessageField
}
public function renderFieldValue($value) {
// Blender: don't include this in commit messages.
//
// NOTE: Do it at render time to allow specifying tags when creating
// a new differential revision with `arc diff`.
return null;
return $this->renderHandleList($value);
}

View File

@@ -33,9 +33,14 @@ final class DifferentialDiffPHIDType extends PhabricatorPHIDType {
$diff = $objects[$phid];
$id = $diff->getID();
$revision_id = $diff->getRevisionID();
$handle->setName(pht('Diff %d', $id));
$handle->setURI("/differential/diff/{$id}/");
$subpath = SubpathFromId($revision_id);
$uri = '../../../differential/' . $subpath . '/' . "D{$revision_id}.id{$id}.html";
$handle->setURI("$uri");
}
}

View File

@@ -133,6 +133,7 @@ final class DifferentialRevisionSearchEngine
$names['authored'] = pht('Authored');
}
$names['open'] = pht('Open Revisions');
$names['all'] = pht('All Revisions');
return $names;
@@ -155,6 +156,9 @@ final class DifferentialRevisionSearchEngine
case 'authored':
return $query
->setParameter('authorPHIDs', array($viewer->getPHID()));
case 'open':
return $query
->setParameter('status', DifferentialLegacyQuery::STATUS_OPEN);
case 'all':
return $query;
}

View File

@@ -3,8 +3,29 @@
final class DifferentialTransactionQuery
extends PhabricatorApplicationTransactionQuery {
private $updatedEpochAfter;
public function getTemplateApplicationTransaction() {
return new DifferentialTransaction();
}
public function withUpdatedEpochAfter($epoch) {
$this->updatedEpochAfter = $epoch;
return $this;
}
protected function buildWhereClause(AphrontDatabaseConnection $conn) {
$where = array();
if ($this->updatedEpochAfter !== null) {
$where[] = qsprintf(
$conn,
'x.dateModified >= %d',
$this->updatedEpochAfter);
}
$where[] = $this->buildWhereClauseParts($conn);
return $this->formatWhereClause($conn, $where);
}
}

View File

@@ -589,15 +589,15 @@ abstract class DifferentialChangesetHTMLRenderer
$reference = $this->getRenderingReference();
return javelin_tag(
'a',
'span',
array(
'href' => '#',
'mustcapture' => true,
'sigil' => 'show-more',
'meta' => array(
'type' => ($is_all ? 'all' : null),
'range' => $range,
),
// 'href' => '#',
// 'mustcapture' => true,
// 'sigil' => 'show-more',
// 'meta' => array(
// 'type' => ($is_all ? 'all' : null),
// 'range' => $range,
// ),
),
$text);
}

View File

@@ -284,6 +284,16 @@ final class DifferentialDiff
}
}
// Blender: auto set git commit author from user if none provided.
// Use username instead of email, Phabricator will recognize this
// and we avoid sharing private information.
$user = id(new PhabricatorUser())
->loadOneWhere('phid = %s', $this->authorPHID);
if ($user) {
$dict['authorName'] = $user->getRealName();
$dict['authorEmail'] = $user->getUserName();
}
return $dict;
}

View File

@@ -147,7 +147,8 @@ final class DifferentialRevision extends DifferentialDAO
}
public function getURI() {
return '/'.$this->getMonogram();
$subpath = SubpathFromId($this->getID());
return '../../../differential/' . $subpath . '/index.html';
}
public function getCommitPHIDs() {

View File

@@ -68,6 +68,8 @@ final class DifferentialTransactionComment
}
public function shouldUseMarkupCache($field) {
return false;
// Only cache submitted comments.
return ($this->getTransactionPHID() != null);
}

View File

@@ -187,13 +187,13 @@ final class DifferentialChangesetListView extends AphrontView {
$uniq_id = 'diff-'.$changeset->getAnchorName();
$detail->setID($uniq_id);
$view_options = $this->renderViewOptionsDropdown(
$detail,
$ref,
$changeset);
// $view_options = $this->renderViewOptionsDropdown(
// $detail,
// $ref,
// $changeset);
$detail->setChangeset($changeset);
$detail->addButton($view_options);
// $detail->addButton($view_options);
$detail->setSymbolIndex(idx($this->symbolIndexes, $key));
$detail->setVsChangesetID(idx($this->vsMap, $changeset->getID()));
$detail->setEditable(true);
@@ -202,7 +202,107 @@ final class DifferentialChangesetListView extends AphrontView {
$detail->setRenderURI($this->renderURI);
$parser = $this->getParser();
// $parser = $this->getParser();
$revision_id = $diff->getRevisionID();
$revision = id(new DifferentialRevisionQuery())
->setViewer($viewer)
->withIDs(array($revision_id))
->executeOne();
$old = array();
$new = array();
$right = $changeset;
$left = null;
$right_source = $right->getID();
$right_new = true;
$left_source = $right->getID();
$left_new = false;
$render_cache_key = $right->getID();
$old[] = $changeset;
$new[] = $changeset;
$parser = id(new DifferentialChangesetParser())
->setViewer($viewer)
->setViewState(new PhabricatorChangesetViewState())
// ->setCoverage($coverage)
->setChangeset($changeset)
->setRenderingReference($ref)
->setRenderCacheKey($render_cache_key)
->setRightSideCommentMapping($right_source, $right_new)
->setLeftSideCommentMapping($left_source, $left_new)
->setMask(array())
;
if ($left && $right) {
$parser->setOriginals($left, $right);
}
if ($revision) {
$inlines = id(new DifferentialDiffInlineCommentQuery())
->setViewer($viewer)
->withRevisionPHIDs(array($revision->getPHID()))
->withPublishableComments(true)
->withPublishedComments(true)
->needHidden(true)
->needInlineContext(true)
->execute();
$inlines = mpull($inlines, 'newInlineCommentObject');
$inlines = id(new PhabricatorInlineCommentAdjustmentEngine())
->setViewer($viewer)
->setRevision($revision)
->setOldChangesets($old)
->setNewChangesets($new)
->setInlines($inlines)
->execute();
} else {
$inlines = array();
}
if ($left_new) {
$inlines = array_merge(
$inlines,
$this->buildLintInlineComments($left));
}
if ($right_new) {
$inlines = array_merge(
$inlines,
$this->buildLintInlineComments($right));
}
$phids = array();
foreach ($inlines as $inline) {
$parser->parseInlineComment($inline);
if ($inline->getAuthorPHID()) {
$phids[$inline->getAuthorPHID()] = true;
}
}
$phids = array_keys($phids);
$handles = $this->loadViewerHandles($phids);
$parser->setHandles($handles);
$engine = new PhabricatorMarkupEngine();
$engine->setViewer($viewer);
foreach ($inlines as $inline) {
$engine->addObject(
$inline,
PhabricatorInlineComment::MARKUP_FIELD_BODY);
}
$engine->process();
$parser
->setMarkupEngine($engine);
if ($parser) {
$response = $parser->newChangesetResponse();
$detail->setChangesetResponse($response);
@@ -471,4 +571,92 @@ final class DifferentialChangesetListView extends AphrontView {
return $uri;
}
private function buildLintInlineComments($changeset) {
$diff = $changeset->getDiff();
$target_phids = $diff->getBuildTargetPHIDs();
if (!$target_phids) {
return array();
}
$messages = id(new HarbormasterBuildLintMessage())->loadAllWhere(
'buildTargetPHID IN (%Ls) AND path = %s',
$target_phids,
$changeset->getFilename());
if (!$messages) {
return array();
}
$change_type = $changeset->getChangeType();
if (DifferentialChangeType::isDeleteChangeType($change_type)) {
// If this is a lint message on a deleted file, show it on the left
// side of the UI because there are no source code lines on the right
// side of the UI so inlines don't have anywhere to render. See PHI416.
$is_new = 0;
} else {
$is_new = 1;
}
$template = id(new DifferentialInlineComment())
->setChangesetID($changeset->getID())
->setIsNewFile($is_new)
->setLineLength(0);
$inlines = array();
foreach ($messages as $message) {
$description = $message->getProperty('description');
$inlines[] = id(clone $template)
->setSyntheticAuthor(pht('Lint: %s', $message->getName()))
->setLineNumber($message->getLine())
->setContent($description);
}
return $inlines;
}
private function loadCoverage(DifferentialChangeset $changeset) {
$viewer = $this->getViewer();
$target_phids = $changeset->getDiff()->getBuildTargetPHIDs();
if (!$target_phids) {
return null;
}
$unit = id(new HarbormasterBuildUnitMessageQuery())
->setViewer($viewer)
->withBuildTargetPHIDs($target_phids)
->execute();
if (!$unit) {
return null;
}
$coverage = array();
foreach ($unit as $message) {
$test_coverage = $message->getProperty('coverage');
if ($test_coverage === null) {
continue;
}
$coverage_data = idx($test_coverage, $changeset->getFileName());
if (!strlen($coverage_data)) {
continue;
}
$coverage[] = $coverage_data;
}
if (!$coverage) {
return null;
}
return ArcanistUnitTestResult::mergeCoverage($coverage);
}
protected function loadViewerHandles(array $phids) {
return id(new PhabricatorHandleQuery())
->setViewer($this->getViewer())
->withPHIDs($phids)
->execute();
}
}

View File

@@ -82,7 +82,7 @@ final class DifferentialLocalCommitsView extends AphrontView {
$view->setSome($summary);
if ($message && (trim($summary) != trim($message))) {
$view->setMore(phutil_escape_html_newlines($message));
// $view->setMore(phutil_escape_html_newlines($message));
}
$row[] = $view->render();
@@ -137,9 +137,9 @@ final class DifferentialLocalCommitsView extends AphrontView {
$commit_hash = self::formatCommit($hash);
if ($commit_for_link) {
$link = phutil_tag(
'a',
'span',
array(
'href' => $commit_for_link->getURI(),
// 'href' => $commit_for_link->getURI(),
),
$commit_hash);
} else {

View File

@@ -178,7 +178,7 @@ final class DifferentialRevisionUpdateHistoryView extends AphrontView {
$id_link = phutil_tag(
'a',
array(
'href' => '/D'.$revision_id.'?id='.$id,
'href' => 'D'.$revision_id.'.id'.$id.'.html',
),
$id);
} else {
@@ -196,19 +196,27 @@ final class DifferentialRevisionUpdateHistoryView extends AphrontView {
$base,
$desc,
$age,
$lint,
$unit,
$old,
$new,
// $lint,
// $unit,
// $old,
// $new,
);
$classes = array();
/*
if ($old_class) {
$classes[] = 'differential-update-history-old-now';
}
if ($new_class) {
$classes[] = 'differential-update-history-new-now';
}
*/
if ($id && $this->selectedDiffID == $id) {
$classes[] = 'differential-update-history-current';
}
$rowc[] = nonempty(implode(' ', $classes), null);
}
@@ -226,10 +234,10 @@ final class DifferentialRevisionUpdateHistoryView extends AphrontView {
pht('Base'),
pht('Description'),
pht('Created'),
pht('Lint'),
pht('Unit'),
'',
'',
// pht('Lint'),
// pht('Unit'),
// '',
// '',
));
$table->setColumnClasses(
array(
@@ -238,8 +246,8 @@ final class DifferentialRevisionUpdateHistoryView extends AphrontView {
'',
'wide',
'date',
'center',
'center',
// 'center',
// 'center',
'center differential-update-history-old',
'center differential-update-history-new',
));
@@ -251,8 +259,8 @@ final class DifferentialRevisionUpdateHistoryView extends AphrontView {
false,
true,
false,
false,
false,
// false,
// false,
true,
true,
));
@@ -276,7 +284,7 @@ final class DifferentialRevisionUpdateHistoryView extends AphrontView {
),
array(
$table,
$show_diff,
// $show_diff,
));
return $content;
@@ -392,8 +400,10 @@ final class DifferentialRevisionUpdateHistoryView extends AphrontView {
$diff->getSourceControlBaseRevision());
if ($commit_for_link) {
$link = phutil_tag(
'a',
array('href' => $commit_for_link->getURI()),
'span',
array(
'href' => $commit_for_link->getURI()
),
$label);
} else {
$link = $label;

View File

@@ -106,9 +106,7 @@ final class DiffusionRepositoryPoliciesManagementPanel
pht('Editable By'),
$descriptions[PhabricatorPolicyCapability::CAN_EDIT]);
$pushable = $repository->isHosted()
? $descriptions[DiffusionPushCapability::CAPABILITY]
: phutil_tag('em', array(), pht('Not a Hosted Repository'));
$pushable = $descriptions[DiffusionPushCapability::CAPABILITY];
$view->addProperty(pht('Pushable By'), $pushable);
return $this->newBox(pht('Policies'), $view);

View File

@@ -18,6 +18,10 @@ final class PhabricatorFavoritesMainMenuBarExtension
public function buildMainMenus() {
$viewer = $this->getViewer();
if ($viewer->limitNonContributorUI()) {
return array();
}
$dropdown = $this->newDropdown($viewer);
if (!$dropdown) {
return array();

View File

@@ -6,6 +6,10 @@ final class PhabricatorFileDataController extends PhabricatorFileController {
private $key;
private $file;
public function shouldAllowPublic() {
return true;
}
public function shouldRequireLogin() {
return false;
}

View File

@@ -143,10 +143,15 @@ final class PhabricatorEmbedFileRemarkupRule
$xform = PhabricatorFileTransform::getTransformByKey($preview_key);
$existing_xform = $file->getTransform($preview_key);
// if ($existing_xform) {
// $xform_uri = $existing_xform->getCDNURI('data');
// } else {
// $xform_uri = $file->getURIForTransform($xform);
// }
if ($existing_xform) {
$xform_uri = $existing_xform->getCDNURI('data');
$xform_uri = $existing_xform->getInfoURI();
} else {
$xform_uri = $file->getURIForTransform($xform);
$xform_uri = $file->getInfoURI();
}
$attrs['src'] = $xform_uri;

View File

@@ -61,7 +61,7 @@ final class PhabricatorFile extends PhabricatorFileDAO
protected $ttl;
protected $isExplicitUpload = 1;
protected $viewPolicy = PhabricatorPolicies::POLICY_USER;
protected $viewPolicy = PhabricatorPolicies::POLICY_PUBLIC;
protected $isPartial = 0;
protected $isDeleted = 0;
@@ -825,11 +825,12 @@ final class PhabricatorFile extends PhabricatorFileDAO
}
public function getViewURI() {
return $this->getInfoURI();
if (!$this->getPHID()) {
throw new Exception(
pht('You must save a file before you can generate a view URI.'));
}
return $this->getCDNURI('data');
}
@@ -875,13 +876,14 @@ final class PhabricatorFile extends PhabricatorFileDAO
}
}
public function getInfoURI() {
return '/'.$this->getMonogram();
$safe_name = MakeFilemameSafe($this->getName());
$subpath = SubpathFromId($this->getID());
return '../../../file/' . $subpath . '/' . $safe_name;
}
public function getBestURI() {
if ($this->isViewableInBrowser()) {
if ($this->isViewableInBrowser() && false) {
return $this->getViewURI();
} else {
return $this->getInfoURI();
@@ -889,7 +891,8 @@ final class PhabricatorFile extends PhabricatorFileDAO
}
public function getDownloadURI() {
return $this->getCDNURI('download');
return $this->getInfoURI();
// return $this->getCDNURI('download');
}
public function getURIForTransform(PhabricatorFileTransform $transform) {
@@ -1570,7 +1573,7 @@ final class PhabricatorFile extends PhabricatorFileDAO
}
return $this->getViewPolicy();
case PhabricatorPolicyCapability::CAN_EDIT:
return PhabricatorPolicies::POLICY_NOONE;
return PhabricatorPolicies::POLICY_ADMIN;
}
}

View File

@@ -55,7 +55,7 @@ final class PhabricatorFlagsUIEventListener extends PhabricatorEventListener {
}
$actions = $event->getValue('actions');
$actions[] = $flag_action;
// $actions[] = $flag_action;
$event->setValue('actions', $actions);
}

View File

@@ -147,7 +147,7 @@ final class HarbormasterUIEventListener
}
$view = $ui_event->getValue('view');
$view->addProperty(pht('Build Status'), $status_view);
// $view->addProperty(pht('Build Status'), $status_view);
}
}

View File

@@ -11,6 +11,19 @@ final class PhabricatorHomeProfileMenuEngine
return "/home/menu/{$path}";
}
private function buildWelcomePanelFromFile() {
$webroot = dirname(phutil_get_library_root('phabricator')).'/webroot/';
$panel = new PHUIObjectBoxView();
$panel->setHeaderText('Welcome');
$panel->appendChild(
phutil_safe_html(
FileSystem::readFile($webroot .
PhabricatorEnv::getEnvConfig('welcome.file'))));
require_celerity_resource('phabricator-welcome-page');
return $panel;
}
protected function buildItemViewContent(
PhabricatorProfileMenuItemConfiguration $item) {
$viewer = $this->getViewer();
@@ -23,6 +36,11 @@ final class PhabricatorHomeProfileMenuEngine
$content = parent::buildItemViewContent($item);
if (PhabricatorEnv::getEnvConfig('welcome.file') !== null) {
$content = array($this->buildWelcomePanelFromFile(),
$content);
}
return array(
$content,
$upload,

View File

@@ -39,7 +39,7 @@ final class PhabricatorMemeRemarkupRule extends PhutilRemarkupRule {
$is_html_mail = $this->getEngine()->isHTMLMailMode();
$is_text = $this->getEngine()->isTextMode();
$must_inline = ($is_html_mail || $is_text);
$must_inline = ($is_html_mail || $is_text || true);
if ($must_inline) {
if (!$asset) {

View File

@@ -46,6 +46,7 @@ final class PhabricatorManiphestApplication extends PhabricatorApplication {
return array(
'/T(?P<id>[1-9]\d*)' => 'ManiphestTaskDetailController',
'/maniphest/' => array(
'(?:project/(?P<projectKey>[^/]+)/)?(?:type/(?P<taskSubtypeKey>[^/]+)/)?(?:query/(?P<queryKey>[^/]+)/)?' => 'ManiphestTaskListController',
$this->getQueryRoutePattern() => 'ManiphestTaskListController',
'report/(?:(?P<view>\w+)/)?' => 'ManiphestReportController',
$this->getBulkRoutePattern('bulk/') => 'ManiphestBulkEditController',

View File

@@ -2,18 +2,137 @@
abstract class ManiphestController extends PhabricatorController {
protected $projectKey;
protected $taskSubtypeKey;
protected $alwaysVisibleProjects = array('BF Blender',
'BF Blender: Unconfirmed',
'BF Blender: Regressions',
'BF Blender: Next',
'Addons',
'Game Engine');
public function willProcessRequest(array $data) {
$this->projectKey = idx($data, 'projectKey');
$this->taskSubtypeKey = idx($data, 'taskSubtypeKey');
}
public function buildApplicationMenu() {
return $this->buildSideNavView()->getMenu();
}
public function getAvailableTaskSubtypes() {
$config = PhabricatorEnv::getEnvConfig('maniphest.subtypes');
$subtype_map = PhabricatorEditEngineSubtype::newSubtypeMap($config);
return $subtypes = $subtype_map->getSubtypes();
}
private function buildProjectsNavigation($nav) {
$user = $this->getRequest()->getUser();
if (!$this->projectKey) {
$nav->addLabel(pht('Projects'));
$show_item_id = celerity_generate_unique_node_id();
$hide_item_id = celerity_generate_unique_node_id();
$show_item = id(new PHUIListItemView())
->setName(pht('Show all projects'))
->setHref('#')
->addSigil('reveal-content')
->setID($show_item_id);
$hide_item = id(new PHUIListItemView())
->setName(pht('Hide inactive Projects'))
->setHref('#')
->setStyle('display: none')
->setID($hide_item_id)
->addSigil('reveal-content');
$nav->addMenuItem($show_item);
$nav->addMenuItem($hide_item);
$projects = id(new PhabricatorProjectQuery())
->setViewer($user)
->execute();
$project_ids = array($hide_item_id);
foreach ($projects as $project) {
if ($project->isArchived()) {
continue;
}
$url = 'project/' . $project->getID();
$name = $project->getName();
$is_hide = !in_array($name, $this->alwaysVisibleProjects);
if ($is_hide) {
$label_id = celerity_generate_unique_node_id();
$project_ids[] = $label_id;
$item = id(new PHUIListItemView())
->setName($name)
->setType(PHUIListItemView::TYPE_LINK)
->setKey($url)
->setStyle('display: none;')
->setID($label_id);
$href = clone $nav->getBaseURI();
$href->setPath(rtrim($href->getPath().$url, '/').'/');
$item->setHref((string)$href);
$nav->addMenuItem($item);
} else {
$nav->addFilter($url, pht($name));
}
}
Javelin::initBehavior('phabricator-reveal-content');
$show_item->setMetadata(
array(
'showIDs' => $project_ids,
'hideIDs' => array($show_item_id),
));
$hide_item->setMetadata(
array(
'showIDs' => array($show_item_id),
'hideIDs' => $project_ids,
));
} else {
$project = id(new PhabricatorProjectQuery())
->setViewer($user)
->withIDs(array($this->projectKey))
->executeOne();
if ($project) {
$nav->addLabel(pht($project->getName()));
$menu = $nav->getMenu();
$url = $nav->getBaseURI() . 'project/' . $this->projectKey;
$link = $menu->newLink(pht('All Types'), $url, '');
if (!$this->taskSubtypeKey) {
$link->addClass('phui-list-item-selected');
}
$task_subtypes = $this->getAvailableTaskSubtypes();
foreach ($task_subtypes as $key => $subtype) {
$url = $nav->getBaseURI() . 'project/' . $this->projectKey . '/type/' . $key . '/';
$link = $menu->newLink(pht($subtype->getName()), $url, $key);
if ($key == $this->taskSubtypeKey) {
$link->addClass('phui-list-item-selected');
}
}
}
}
}
public function buildSideNavView() {
$viewer = $this->getViewer();
$nav = new AphrontSideNavFilterView();
$nav->setBaseURI(new PhutilURI($this->getApplicationURI()));
$this->buildProjectsNavigation($nav);
id(new ManiphestTaskSearchEngine())
->setViewer($viewer)
->setProjectKey($this->projectKey)
->setTaskTypeKey($this->taskSubtypeKey)
->addNavigationItems($nav->getMenu());
if ($viewer->isLoggedIn()) {
@@ -29,6 +148,33 @@ abstract class ManiphestController extends PhabricatorController {
protected function buildApplicationCrumbs() {
$crumbs = parent::buildApplicationCrumbs();
return $crumbs;
if ($this->projectKey) {
$user = $this->getRequest()->getUser();
$project = id(new PhabricatorProjectQuery())
->setViewer($user)
->withIDs(array($this->projectKey))
->executeOne();
if ($project) {
// Special for for Blender and Addons reports.
$form = 1;
if ($this->projectKey == 3) {
$form = 2;
}
$crumbs->addTextCrumb(pht($project->getName()),
$this->taskSubtypeKey? '/maniphest/project/'.$this->projectKey: null);
$crumbs->addAction(
id(new PHUIListItemView())
->setName(pht('Report Bug'))
->setHref($this->getApplicationURI('task/edit/form/' . $form . '/?project='.
$project->getPHID().'&type=Bug'))
->setIcon('fa-plus-square'));
} else {
throw new Exception('Unknown project was passed via the url');
}
}
id(new ManiphestEditEngine())
->setViewer($this->getViewer())

View File

@@ -0,0 +1,65 @@
<?php
final class ManiphestSearchController
extends PhabricatorApplicationSearchController {
private $projectKey;
private $taskSubtypeKey;
private $taskSubtypes;
protected function getDescriptionForQuery($named_query, $dao_query) {
$title = '';
if ($named_query) {
$title = $named_query->getQueryName();
} else {
$title = parent::getDescriptionForQuery($named_query, $dao_query);
if (!$title) {
$title = pht('Advanced Search');
}
}
$description = pht('%s (%d)',
$title,
$dao_query->getTotalTasksCount());
if ($this->projectKey) {
$user = $this->getRequest()->getUser();
$project = id(new PhabricatorProjectQuery())
->setViewer($user)
->withIDs(array($this->projectKey))
->executeOne();
if ($project) {
$description .= ' from project "'.pht($project->getName()).'"';
} else {
throw new Exception('Unknown project');
}
}
if ($this->taskSubtypeKey) {
$task_subtype = idx($this->taskSubtypes, $this->taskSubtypeKey);
if ($task_subtype) {
$description .= ', task type "'.pht($task_subtype->getName()).'"';
} else {
throw new Exception('Unknown task type');
}
}
return $description;
}
public function setProjectKey($projectKey) {
$this->projectKey = $projectKey;
return $this;
}
public function setTaskSubtypes($taskSubtypes) {
$this->taskSubtypes = $taskSubtypes;
return $this;
}
public function setTaskTypeKey($taskSubtypeKey) {
$this->taskSubtypeKey = $taskSubtypeKey;
return $this;
}
}

View File

@@ -210,7 +210,8 @@ final class ManiphestTaskDetailController extends ManiphestController {
$view = id(new PHUIHeaderView())
->setHeader($task->getTitle())
->setUser($this->getRequest()->getUser())
->setPolicyObject($task);
// ->setPolicyObject($task)
;
$priority_name = ManiphestTaskPriority::getTaskPriorityName(
$task->getPriority());
@@ -271,6 +272,7 @@ final class ManiphestTaskDetailController extends ManiphestController {
$curtain = $this->newCurtainView($task);
/*
$curtain->addAction(
id(new PhabricatorActionView())
->setName(pht('Edit Task'))
@@ -278,6 +280,7 @@ final class ManiphestTaskDetailController extends ManiphestController {
->setHref($this->getApplicationURI("/task/edit/{$id}/"))
->setDisabled(!$can_edit)
->setWorkflow($workflow_edit));
*/
$subtype_map = $task->newEditEngineSubtypeMap();
$subtask_options = $subtype_map->getCreateFormsForSubtype(
@@ -325,16 +328,20 @@ final class ManiphestTaskDetailController extends ManiphestController {
ManiphestTaskCloseAsDuplicateRelationship::RELATIONSHIPKEY,
);
/*
$task_submenu = $relationship_list->newActionSubmenu($submenu_actions)
->setName(pht('Edit Related Tasks...'))
->setIcon('fa-anchor');
$curtain->addAction($task_submenu);
*/
/*
$relationship_submenu = $relationship_list->newActionMenu();
if ($relationship_submenu) {
$curtain->addAction($relationship_submenu);
}
*/
$viewer_phid = $viewer->getPHID();
$owner_phid = $task->getOwnerPHID();
@@ -633,9 +640,9 @@ final class ManiphestTaskDetailController extends ManiphestController {
$commit_monogram);
$commit_link = javelin_tag(
'a',
'span',
array(
'href' => $commit->getURI(),
// 'href' => $commit->getURI(),
'sigil' => 'hovercard',
'meta' => array(
'hoverPHID' => $commit->getPHID(),

View File

@@ -10,14 +10,269 @@ final class ManiphestTaskListController
public function handleRequest(AphrontRequest $request) {
$querykey = $request->getURIData('queryKey');
$controller = id(new PhabricatorApplicationSearchController())
$controller = id(new ManiphestSearchController())
->setQueryKey($querykey)
->setTaskSubtypes($this->getAvailableTaskSubtypes())
->setProjectKey($this->projectKey)
->setTaskTypeKey($this->taskSubtypeKey)
->setSearchEngine(
id(new ManiphestTaskSearchEngine())
->setShowBatchControls(true))
->setShowBatchControls(true)
->setProjectKey($this->projectKey)
->setTaskTypeKey($this->taskSubtypeKey))
->setNavigation($this->buildSideNavView());
return $this->delegateToController($controller);
}
public function __renderResultsList(
array $tasks,
PhabricatorSavedQuery $query) {
assert_instances_of($tasks, 'ManiphestTask');
$viewer = $this->getRequest()->getUser();
// If we didn't match anything, just pick up the default empty state.
if (!$tasks) {
return id(new PHUIObjectItemListView())
->setUser($viewer);
}
$group_parameter = nonempty($query->getParameter('group'), 'priority');
$order_parameter = nonempty($query->getParameter('order'), 'priority');
$handles = ManiphestTaskListView::loadTaskHandles($viewer, $tasks);
$groups = $this->groupTasks(
$tasks,
$group_parameter,
$handles);
$can_edit_priority = $this->hasApplicationCapability(
ManiphestCapabilityEditPriority::CAPABILITY);
$can_drag = ($order_parameter == 'priority') &&
($can_edit_priority) &&
($group_parameter == 'none' || $group_parameter == 'priority');
if (!$viewer->isLoggedIn()) {
// TODO: (T603) Eventually, we conceivably need to make each task
// draggable individually, since the user may be able to edit some but
// not others.
$can_drag = false;
}
$result = array();
$can_edit = $this->hasApplicationCapability(
PhabricatorPolicyCapability::CAN_EDIT);
$lists = array();
foreach ($groups as $group => $list) {
$task_list = new ManiphestTaskListView();
$task_list->setShowBatchControls($can_edit);
if ($can_drag) {
$task_list->setShowSubpriorityControls(true);
}
$task_list->setUser($viewer);
$task_list->setTasks($list);
$task_list->setHandles($handles);
$header = javelin_tag(
'h1',
array(
'class' => 'maniphest-task-group-header',
'sigil' => 'task-group',
'meta' => array(
'priority' => head($list)->getPriority(),
),
),
pht('%s (%s)', $group, new PhutilNumber(count($list))));
$lists[] = phutil_tag(
'div',
array(
'class' => 'maniphest-task-group'
),
array(
$header,
$task_list,
));
}
if ($can_drag) {
Javelin::initBehavior(
'maniphest-subpriority-editor',
array(
'uri' => '/maniphest/subpriority/',
));
}
return phutil_tag(
'div',
array(
'class' => 'maniphest-list-container',
),
array(
$lists,
$this->renderBatchEditor($query),
));
}
private function __groupTasks(array $tasks, $group, array $handles) {
assert_instances_of($tasks, 'ManiphestTask');
assert_instances_of($handles, 'PhabricatorObjectHandle');
$groups = $this->getTaskGrouping($tasks, $group);
$results = array();
foreach ($groups as $label_key => $tasks) {
$label = $this->getTaskLabelName($group, $label_key, $handles);
$results[$label][] = $tasks;
}
foreach ($results as $label => $task_groups) {
$results[$label] = array_mergev($task_groups);
}
return $results;
}
private function __getTaskGrouping(array $tasks, $group) {
switch ($group) {
case 'priority':
return mgroup($tasks, 'getPriority');
case 'status':
return mgroup($tasks, 'getStatus');
case 'assigned':
return mgroup($tasks, 'getOwnerPHID');
case 'project':
return mgroup($tasks, 'getGroupByProjectPHID');
default:
return array(pht('Tasks') => $tasks);
}
}
private function __getTaskLabelName($group, $label_key, array $handles) {
switch ($group) {
case 'priority':
return ManiphestTaskPriority::getTaskPriorityName($label_key);
case 'status':
return ManiphestTaskStatus::getTaskStatusFullName($label_key);
case 'assigned':
if ($label_key) {
return $handles[$label_key]->getFullName();
} else {
return pht('(Not Assigned)');
}
case 'project':
if ($label_key) {
return $handles[$label_key]->getFullName();
} else {
return pht('(No Project)');
}
default:
return pht('Tasks');
}
}
private function ___renderBatchEditor(PhabricatorSavedQuery $saved_query) {
$user = $this->getRequest()->getUser();
$batch_capability = ManiphestCapabilityBulkEdit::CAPABILITY;
if (!$this->hasApplicationCapability($batch_capability)) {
return null;
}
if (!$user->isLoggedIn()) {
// Don't show the batch editor or excel export for logged-out users.
// Technically we //could// let them export, but ehh.
return null;
}
Javelin::initBehavior(
'maniphest-batch-selector',
array(
'selectAll' => 'batch-select-all',
'selectNone' => 'batch-select-none',
'submit' => 'batch-select-submit',
'status' => 'batch-select-status-cell',
'idContainer' => 'batch-select-id-container',
'formID' => 'batch-select-form',
));
$select_all = javelin_tag(
'a',
array(
'href' => '#',
'mustcapture' => true,
'class' => 'grey button',
'id' => 'batch-select-all',
),
pht('Select All'));
$select_none = javelin_tag(
'a',
array(
'href' => '#',
'mustcapture' => true,
'class' => 'grey button',
'id' => 'batch-select-none',
),
pht('Clear Selection'));
$submit = phutil_tag(
'button',
array(
'id' => 'batch-select-submit',
'disabled' => 'disabled',
'class' => 'disabled',
),
pht("Batch Edit Selected \xC2\xBB"));
$export = javelin_tag(
'a',
array(
'href' => '/maniphest/export/'.$saved_query->getQueryKey().'/',
'class' => 'grey button',
),
pht('Export to Excel'));
$hidden = phutil_tag(
'div',
array(
'id' => 'batch-select-id-container',
),
'');
$editor = hsprintf(
'<div class="maniphest-batch-editor">'.
'<div class="batch-editor-header">%s</div>'.
'<table class="maniphest-batch-editor-layout">'.
'<tr>'.
'<td>%s%s</td>'.
'<td>%s</td>'.
'<td id="batch-select-status-cell">%s</td>'.
'<td class="batch-select-submit-cell">%s%s</td>'.
'</tr>'.
'</table>'.
'</div>',
pht('Batch Task Editor'),
$select_all,
$select_none,
$export,
'',
$submit,
$hidden);
$editor = phabricator_form(
$user,
array(
'method' => 'POST',
'action' => '/maniphest/batch/',
'id' => 'batch-select-form',
),
$editor);
return $editor;
}
}

View File

@@ -200,7 +200,8 @@ EODOCS
->setIsNullable(true)
->setSingleValue($object->getOwnerPHID())
->setCommentActionLabel(pht('Assign / Claim'))
->setCommentActionValue($owner_value),
->setCommentActionValue($owner_value)
->setCanApplyWithoutEditCapability(true),
id(new PhabricatorSelectEditField())
->setKey('status')
->setLabel(pht('Status'))
@@ -213,7 +214,8 @@ EODOCS
->setValue($object->getStatus())
->setOptions($status_map)
->setCommentActionLabel(pht('Change Status'))
->setCommentActionValue($default_status),
->setCommentActionValue($default_status)
->setCanApplyWithoutEditCapability(true),
id(new PhabricatorSelectEditField())
->setKey('priority')
->setLabel(pht('Priority'))
@@ -226,6 +228,7 @@ EODOCS
->setValue($object->getPriorityKeyword())
->setOptions($priority_map)
->setOptionAliases($alias_map)
->setCanApplyWithoutEditCapability(true)
->setCommentActionLabel(pht('Change Priority')),
);
@@ -350,6 +353,18 @@ EODOCS
continue;
}
// Blender: limit task reopen to contributors.
//
// NOTE: Similar to other semantic check here we don't do it in the
// Conduit.
$viewer = $this->getViewer();
if (ManiphestTaskStatus::isClosedStatus($current_status) &&
ManiphestTaskStatus::isOpenStatus($status) &&
$viewer->limitNonContributorUI()) {
unset($status_map[$status]);
continue;
}
// Don't allow tasks to be changed directly into "Closed, Duplicate"
// status. Instead, you have to merge them. See T4819.
if ($status == $dup_status) {
@@ -379,6 +394,18 @@ EODOCS
continue;
}
// Blender: limit triaging to contributors.
//
// NOTE: Similar to other semantic check here we don't do it in the
// Conduit.
$viewer = $this->getViewer();
if ($priority != $current_priority) {
if (array_search('triage', $priority_keywords[$priority]) === false &&
$viewer->limitNonContributorUI()) {
continue;
}
}
$keyword = head(idx($priority_keywords, $priority));
$results[$keyword] = $priority_name;
}

View File

@@ -36,7 +36,7 @@ final class ManiphestTaskPHIDType extends PhabricatorPHIDType {
$handle->setName("T{$id}");
$handle->setFullName("T{$id}: {$title}");
$handle->setURI("/T{$id}");
$handle->setURI($task->getURI());
if ($task->isClosed()) {
$handle->setStatus(PhabricatorObjectHandle::STATUS_CLOSED);

View File

@@ -237,7 +237,13 @@ final class ManiphestTaskQuery extends PhabricatorCursorPagedPolicyAwareQuery {
return new ManiphestTask();
}
protected function loadPage() {
protected function buildTaskCountSelectClause(AphrontDatabaseConnection $conn) {
$parts = $this->buildSelectClauseParts($conn);
$parts[0] = qsprintf($conn, '`task`.id');
return $this->formatSelectClause($conn, $parts);
}
protected function getRawQueryResults($task_dao, $count_all_tasks) {
$task_dao = new ManiphestTask();
$conn = $task_dao->establishConnection('r');
@@ -252,18 +258,46 @@ final class ManiphestTaskQuery extends PhabricatorCursorPagedPolicyAwareQuery {
break;
}
$rows = queryfx_all(
$conn,
'%Q %Q FROM %T task %Q %Q %Q %Q %Q %Q',
$this->buildSelectClause($conn),
$group_column,
$task_dao->getTableName(),
$this->buildJoinClause($conn),
$where,
$this->buildGroupClause($conn),
$this->buildHavingClause($conn),
$this->buildOrderClause($conn),
$this->buildLimitClause($conn));
if ($count_all_tasks) {
$r = queryfx_all(
$conn,
'%Q %Q FROM %T task %Q %Q %Q %Q %Q',
$this->buildTaskCountSelectClause($conn),
$group_column,
$task_dao->getTableName(),
$this->buildJoinClause($conn),
$where,
$this->buildGroupClause($conn),
$this->buildHavingClause($conn),
$this->buildOrderClause($conn));
return array('count' => count($r));
} else {
return queryfx_all(
$conn,
'%Q %Q FROM %T task %Q %Q %Q %Q %Q %Q',
$this->buildSelectClause($conn),
$group_column,
$task_dao->getTableName(),
$this->buildJoinClause($conn),
$where,
$this->buildGroupClause($conn),
$this->buildHavingClause($conn),
$this->buildOrderClause($conn),
$this->buildLimitClause($conn));
}
}
public function getTotalTasksCount() {
$task_dao = new ManiphestTask();
$row = $this->getRawQueryResults($task_dao, true);
return $row['count'];
}
protected function loadPage() {
$task_dao = new ManiphestTask();
$rows = $this->getRawQueryResults($task_dao, false);
switch ($this->groupBy) {
case self::GROUP_PROJECT:

View File

@@ -3,6 +3,8 @@
final class ManiphestTaskSearchEngine
extends PhabricatorApplicationSearchEngine {
private $projectKey;
private $taskSubtypeKey;
private $showBatchControls;
private $baseURI;
private $isBoardView;
@@ -206,7 +208,9 @@ final class ManiphestTaskSearchEngine
$query->withPriorities($map['priorities']);
}
if ($map['subtypes']) {
if ($this->taskSubtypeKey) {
$query->withSubtypes(array($this->taskSubtypeKey));
} else if ($map['subtypes']) {
$query->withSubtypes($map['subtypes']);
}
@@ -250,6 +254,18 @@ final class ManiphestTaskSearchEngine
$query->withSubtaskIDs($map['subtaskIDs']);
}
if ($this->projectKey) {
$project = id(new PhabricatorProjectQuery())
->setViewer($this->requireViewer())
->withIDs(array($this->projectKey))
->executeOne();
$query->withEdgeLogicPHIDs(
PhabricatorProjectObjectHasProjectEdgeType::EDGECONST,
PhabricatorQueryConstraint::OPERATOR_AND,
array($project->getPHID()));
}
if ($map['columnPHIDs']) {
$query->withColumnPHIDs($map['columnPHIDs']);
}
@@ -281,23 +297,30 @@ final class ManiphestTaskSearchEngine
protected function getURI($path) {
if ($this->baseURI) {
return $this->baseURI.$path;
$url = $this->baseURI;
} else {
$url = '/maniphest/';
}
return '/maniphest/'.$path;
if ($this->projectKey)
$url .= 'project/' . $this->projectKey . '/';
if ($this->taskSubtypeKey)
$url .= 'type/' . $this->taskSubtypeKey . '/';
$url = str_replace(" ", "%20", $url);
return $url . $path;
}
protected function getBuiltinQueryNames() {
$names = array();
$names['open'] = pht('Open Tasks');
$names['all'] = pht('All Tasks');
if ($this->requireViewer()->isLoggedIn()) {
$names['assigned'] = pht('Assigned');
$names['authored'] = pht('Authored');
$names['subscribed'] = pht('Subscribed');
}
$names['open'] = pht('Open Tasks');
$names['all'] = pht('All Tasks');
return $names;
}
@@ -310,7 +333,9 @@ final class ManiphestTaskSearchEngine
switch ($query_key) {
case 'all':
return $query;
return $query
->setParameter('order', 'created')
->setParameter('group', 'none');
case 'assigned':
return $query
->setParameter('assignedPHIDs', array($viewer_phid))
@@ -358,6 +383,16 @@ final class ManiphestTaskSearchEngine
);
}
function setProjectKey($projectKey) {
$this->projectKey = $projectKey;
return $this;
}
function setTaskTypeKey($taskSubtypeKey) {
$this->taskSubtypeKey = $taskSubtypeKey;
return $this;
}
protected function renderResultList(
array $tasks,
PhabricatorSavedQuery $saved,

View File

@@ -3,8 +3,30 @@
final class ManiphestTransactionQuery
extends PhabricatorApplicationTransactionQuery {
private $updatedEpochAfter;
public function getTemplateApplicationTransaction() {
return new ManiphestTransaction();
}
public function withUpdatedEpochAfter($epoch) {
$this->updatedEpochAfter = $epoch;
return $this;
}
protected function buildWhereClause(AphrontDatabaseConnection $conn) {
$where = array();
if ($this->updatedEpochAfter !== null) {
$where[] = qsprintf(
$conn,
'x.dateModified >= %d',
$this->updatedEpochAfter);
}
$where[] = $this->buildWhereClauseParts($conn);
return $this->formatWhereClause($conn, $where);
}
}

View File

@@ -193,7 +193,8 @@ final class ManiphestTask extends ManiphestDAO
}
public function getURI() {
return '/'.$this->getMonogram();
$subpath = SubpathFromId($this->getID());
return '../../../maniphest/' . $subpath . '/index.html';
}
public function attachGroupByProjectPHID($phid) {
@@ -311,6 +312,8 @@ final class ManiphestTask extends ManiphestDAO
* @task markup
*/
public function shouldUseMarkupCache($field) {
return false;
return (bool)$this->getID();
}

View File

@@ -35,6 +35,7 @@ final class ManiphestTaskListView extends ManiphestView {
require_celerity_resource('maniphest-task-summary-css');
$list = new PHUIObjectItemListView();
$list->addClass('maniphest-task-group');
if ($this->noDataString) {
$list->setNoDataString($this->noDataString);
@@ -58,6 +59,11 @@ final class ManiphestTaskListView extends ManiphestView {
->setHeader($task->getTitle())
->setHref('/T'.$task->getID());
if ($task->getAuthorPHID()) {
$author = $handles[$task->getAuthorPHID()];
$item->addByline(pht('By: %s', $author->renderLink()));
}
if ($task->getOwnerPHID()) {
$owner = $handles[$task->getOwnerPHID()];
$item->addByline(pht('Assigned: %s', $owner->renderLink()));
@@ -149,6 +155,10 @@ final class ManiphestTaskListView extends ManiphestView {
if ($assigned_phid) {
$phids[] = $assigned_phid;
}
$author_phid = $task->getAuthorPHID();
if ($author_phid) {
$phids[] = $author_phid;
}
foreach ($task->getProjectPHIDs() as $project_phid) {
$phids[] = $project_phid;
}

View File

@@ -165,4 +165,10 @@ final class ManiphestTaskOwnerTransaction
);
}
public function getRequiredCapabilities(
$object,
PhabricatorApplicationTransaction $xaction) {
return PhabricatorPolicyCapability::CAN_INTERACT;
}
}

View File

@@ -201,4 +201,10 @@ final class ManiphestTaskPriorityTransaction
);
}
public function getRequiredCapabilities(
$object,
PhabricatorApplicationTransaction $xaction) {
return PhabricatorPolicyCapability::CAN_INTERACT;
}
}

View File

@@ -237,4 +237,10 @@ final class ManiphestTaskStatusTransaction
);
}
public function getRequiredCapabilities(
$object,
PhabricatorApplicationTransaction $xaction) {
return PhabricatorPolicyCapability::CAN_INTERACT;
}
}

View File

@@ -141,12 +141,14 @@ final class PhabricatorMailTarget extends Phobject {
$body = '';
if ($to_handles) {
$to_names = mpull($to_handles, 'getCommandLineObjectName');
// $to_names = mpull($to_handles, 'getCommandLineObjectName');
$to_names = mpull($to_handles, 'getFullName');
$body .= "To: ".implode(', ', $to_names)."\n";
}
if ($cc_handles) {
$cc_names = mpull($cc_handles, 'getCommandLineObjectName');
// $cc_names = mpull($cc_handles, 'getCommandLineObjectName');
$cc_names = mpull($cc_handles, 'getFullName');
$body .= "Cc: ".implode(', ', $cc_names)."\n";
}
@@ -167,12 +169,12 @@ final class PhabricatorMailTarget extends Phobject {
$body = array();
if ($to_handles) {
$body[] = phutil_tag('strong', array(), 'To: ');
$body[] = phutil_implode_html(', ', mpull($to_handles, 'getName'));
$body[] = phutil_implode_html(', ', mpull($to_handles, 'getFullName'));
$body[] = phutil_tag('br');
}
if ($cc_handles) {
$body[] = phutil_tag('strong', array(), 'Cc: ');
$body[] = phutil_implode_html(', ', mpull($cc_handles, 'getName'));
$body[] = phutil_implode_html(', ', mpull($cc_handles, 'getFullName'));
$body[] = phutil_tag('br');
}
return phutil_tag('div', array(), $body);

View File

@@ -809,7 +809,6 @@ final class PhabricatorMetaMTAMail
$exceptions);
}
public static function shouldMailEachRecipient() {
return PhabricatorEnv::getEnvConfig('metamta.one-mail-per-recipient');
}

View File

@@ -37,7 +37,8 @@ final class PhabricatorPastePastePHIDType extends PhabricatorPHIDType {
$handle->setName("P{$id}");
$handle->setFullName($name);
$handle->setURI("/P{$id}");
$handle->setURI($paste->getURI());
}
}

View File

@@ -176,7 +176,7 @@ final class PhabricatorPasteSearchEngine
$item = id(new PHUIObjectItemView())
->setObjectName('P'.$paste->getID())
->setHeader($title)
->setHref('/P'.$paste->getID())
->setHref($paste->getURI())
->setObject($paste)
->addByline(pht('Author: %s', $author))
->addIcon('none', $created)

View File

@@ -60,7 +60,8 @@ final class PhabricatorPaste extends PhabricatorPasteDAO
}
public function getURI() {
return '/'.$this->getMonogram();
$subpath = SubpathFromId($this->getID());
return '../../../paste/' . $subpath . '/P' . $this->getID() . '.txt';
}
public function getMonogram() {

View File

@@ -11,6 +11,8 @@ final class PhabricatorPasteTransactionComment
}
public function shouldUseMarkupCache($field) {
return false;
// Only cache submitted comments.
return ($this->getTransactionPHID() != null);
}

View File

@@ -38,7 +38,7 @@ final class PasteEmbedView extends AphrontView {
$link = phutil_tag(
'a',
array(
'href' => '/P'.$this->paste->getID(),
'href' => $this->paste->getURI(),
),
$this->handle->getFullName());

View File

@@ -58,6 +58,7 @@ final class PhabricatorPeopleApplication extends PhabricatorApplication {
=> 'PhabricatorPeopleDisableController',
'(?P<via>disable)/(?P<id>[1-9]\d*)/'
=> 'PhabricatorPeopleDisableController',
'spam/(?P<id>[1-9]\d*)/' => 'PhabricatorPeopleSpamController',
'empower/(?P<id>[1-9]\d*)/' => 'PhabricatorPeopleEmpowerController',
'delete/(?P<id>[1-9]\d*)/' => 'PhabricatorPeopleDeleteController',
'rename/(?P<id>[1-9]\d*)/' => 'PhabricatorPeopleRenameController',
@@ -99,6 +100,9 @@ final class PhabricatorPeopleApplication extends PhabricatorApplication {
PeopleDisableUsersCapability::CAPABILITY => array(
'default' => PhabricatorPolicies::POLICY_ADMIN,
),
PeopleDisableSpamUsersCapability::CAPABILITY => array(
'default' => PhabricatorPolicies::POLICY_ADMIN,
),
PeopleBrowseUserDirectoryCapability::CAPABILITY => array(),
);
}

View File

@@ -0,0 +1,16 @@
<?php
final class PeopleDisableSpamUsersCapability
extends PhabricatorPolicyCapability {
const CAPABILITY = 'people.disable_spam.users';
public function getCapabilityName() {
return pht('Can Disable Spammers');
}
public function describeCapabilityRejection() {
return pht('You do not have permission to handle spam users.');
}
}

View File

@@ -29,7 +29,7 @@ final class PhabricatorPeopleDeleteController
->appendCommand(
csprintf(
'phabricator/ $ ./bin/remove destroy %R',
$user->getMonogram()))
$user->getMonogramForCommand()))
->appendParagraph(
pht(
'Unless you have a very good reason to delete this user, consider '.

View File

@@ -93,6 +93,10 @@ final class PhabricatorPeopleProfileManageController
PeopleDisableUsersCapability::CAPABILITY);
$can_disable = ($has_disable && !$is_self);
$has_disable_spam_capability = $this->hasApplicationCapability(
PeopleDisableSpamUsersCapability::CAPABILITY);
$can_disable_spam = ($has_disable_spam_capability && !$is_self);
$id = $user->getID();
$welcome_engine = id(new PhabricatorPeopleWelcomeMailEngine())
@@ -193,6 +197,14 @@ final class PhabricatorPeopleProfileManageController
->setWorkflow(true)
->setHref($this->getApplicationURI('disable/'.$id.'/')));
$curtain->addAction(
id(new PhabricatorActionView())
->setIcon('fa-shield')
->setName(pht('Disable as Spam'))
->setDisabled(!$can_disable_spam)
->setWorkflow(true)
->setHref($this->getApplicationURI('spam/'.$id.'/')));
$curtain->addAction(
id(new PhabricatorActionView())
->setIcon('fa-times')

View File

@@ -0,0 +1,90 @@
<?php
final class PhabricatorPeopleSpamController
extends PhabricatorPeopleController {
public function shouldRequireAdmin() {
return false;
}
public function handleRequest(AphrontRequest $request) {
$viewer = $this->getViewer();
$id = $request->getURIData('id');
$user = id(new PhabricatorPeopleQuery())
->setViewer($viewer)
->withIDs(array($id))
->executeOne();
if (!$user) {
return new Aphront404Response();
}
$this->requireApplicationCapability(
PeopleDisableUsersCapability::CAPABILITY);
$actor = $viewer;
$done_uri = $this->getApplicationURI("manage/{$id}/");
if ($viewer->getPHID() == $user->getPHID()) {
return $this->newDialog()
->setTitle(pht('Something Stays Your Hand'))
->appendParagraph(
pht(
'Try as you might, you find you can not disable your own account.'))
->addCancelButton($done_uri, pht('Curses!'));
}
if ($request->isFormPost()) {
// Disable the account.
if (!$user->getIsDisabled()) {
$xactions = array();
$xactions[] = id(new PhabricatorUserTransaction())
->setTransactionType(PhabricatorUserDisableTransaction::TRANSACTIONTYPE)
->setNewValue(true);
id(new PhabricatorUserTransactionEditor())
->setActor($actor)
->setActingAsPHID($viewer->getPHID())
->setContentSourceFromRequest($request)
->setContinueOnMissingFields(true)
->setContinueOnNoEffect(true)
->applyTransactions($user, $xactions);
}
// Set profile info to spam and blank to everything else.
{
$xactions = array();
$xactions[] = id(new PhabricatorUserTransaction())
->setTransactionType(PhabricatorUserDisableSpamTransaction::TRANSACTIONTYPE);
id(new PhabricatorUserTransactionEditor())
->setActor($actor)
->setActingAsPHID($viewer->getPHID())
->setContentSourceFromRequest($request)
->setContinueOnMissingFields(true)
->setContinueOnNoEffect(true)
->applyTransactions($user, $xactions);
}
return id(new AphrontRedirectResponse())->setURI($done_uri);
}
$title = pht('Disable as Spam?');
$short_title = pht('Disable as Spam');
$body = pht(
'Is %s\'s profile spam?<br />All the profile info will be erased and '.
'they will no longer be able to access Phabricator.',
phutil_tag('strong', array(), $user->getUsername()));
$submit = pht('Disable as Spam');
return $this->newDialog()
->setTitle($title)
->setShortTitle($short_title)
->appendParagraph($body)
->addCancelButton($done_uri)
->addSubmitButton($submit);
}
}

View File

@@ -134,7 +134,7 @@ final class PhabricatorMentionRemarkupRule extends PhutilRemarkupRule {
font-weight: bold;
padding: 0 4px;',
),
'@'.$user->getUserName());
'@'.$user->getFullName());
} else {
if ($engine->getConfig('uri.full')) {
$user_href = PhabricatorEnv::getURI($user_href);
@@ -143,8 +143,9 @@ final class PhabricatorMentionRemarkupRule extends PhutilRemarkupRule {
$tag = id(new PHUITagView())
->setType(PHUITagView::TYPE_PERSON)
->setPHID($user->getPHID())
->setName('@'.$user->getUserName())
->setHref($user_href);
->setName('@'.$user->getFullName())
// ->setHref($user_href)
;
if ($user_has_no_permission) {
$tag->addClass('phabricator-remarkup-mention-nopermission');

View File

@@ -258,10 +258,84 @@ final class PhabricatorUser
PhabricatorPeopleUserPHIDType::TYPECONST);
}
public function getMonogram() {
return '@'.$this->getUsername();
// Functions generateRadomNumber, generateChar, generateSalt and
// generateHtaccessPassword are adopted from FusionForge sources,
// which is licensed by GNU GPL license.
private function generateRadomNumber() {
mt_srand((double)microtime() * 1000000);
$num = mt_rand(46,122);
return $num;
}
private function generateChar() {
do {
$num = $this->generateRadomNumber();
} while ( ( $num > 57 && $num < 65 ) || ( $num > 90 && $num < 97 ) );
$char = chr($num);
return $char;
}
private function generateSalt() {
$a = $this->generateChar();
$b = $this->generateChar();
$salt = "$1$" . "$a$b";
return $salt;
}
private function generateHtaccessPassword($plainpw) {
return crypt($plainpw, $this->generateSalt());
}
public function updateHtaccessPassword(PhutilOpaqueEnvelope $password) {
// Get custom fields list.
$field_list = PhabricatorCustomField::getObjectFields(
$this,
PhabricatorCustomField::ROLE_APPLICATIONTRANSACTIONS);
$field_list
->setViewer($this)
->readFieldsFromStorage($this);
$fields = $field_list->getFields();
// Generate new hash for htaccess password.
$htaccess_hash = $this->generateHtaccessPassword($password->openEnvelope());
// Generate transaction to update custom field.
$xactions = array();
$xaction = $this->getCustomFieldAction(
$fields,
'std:user:htaccess_password_hash',
$htaccess_hash);
if ($xaction) {
$xactions[] = $xaction;
}
// Apply transactions.
if (count($xactions)) {
$editor = id(new PhabricatorUserTransactionEditor())
->setActor($this)
->setContentSource($xactions[0]->getContentSource());
$editor->applyTransactions($this, $xactions);
}
return true;
}
private function getCustomFieldAction($fields, $field_name, $value) {
$field = idx($fields, $field_name);
if (!$field)
return null;
$old_value = $field->getOldValueForApplicationTransactions();
return id(new PhabricatorUserTransaction())
->setTransactionType(PhabricatorTransactions::TYPE_CUSTOMFIELD)
->setMetadataValue('customfield:key', $field->getFieldKey())
->setOldValue($old_value)
->setNewValue($value);
}
public function getMonogram() {
return '@'.$this->getFullname();
}
public function getMonogramForCommand() {
return '@'.$this->getUsername();
}
public function isLoggedIn() {
return !($this->getPHID() === null);
}
@@ -534,6 +608,8 @@ final class PhabricatorUser
}
public function getProfileImageURI() {
return '/rsrc/image/avatar.png';
$uri_key = PhabricatorUserProfileImageCacheType::KEY_URI;
return $this->requireCacheData($uri_key);
}
@@ -555,7 +631,7 @@ final class PhabricatorUser
public function getFullName() {
if (strlen($this->getRealName())) {
return $this->getUsername().' ('.$this->getRealName().')';
return $this->getRealName().' ('.$this->getUsername().')';
} else {
return $this->getUsername();
}
@@ -908,6 +984,10 @@ final class PhabricatorUser
return $this->handlePool->newHandleList($phids);
}
public function getHandlePool() {
return $this->handlePool;
}
/**
* Get a @{class:PHUIHandleView} for a single handle.
@@ -1016,7 +1096,7 @@ final class PhabricatorUser
if ($this->getIsSystemAgent() || $this->getIsMailingList()) {
return PhabricatorPolicies::POLICY_ADMIN;
} else {
return PhabricatorPolicies::POLICY_NOONE;
return PhabricatorPolicies::POLICY_ADMIN;
}
}
}
@@ -1420,7 +1500,7 @@ final class PhabricatorUser
$parts = array(
$this->getUsername(),
$envelope->openEnvelope(),
md5($envelope->openEnvelope()),
$this->getPHID(),
$password->getPasswordSalt(),
);
@@ -1458,5 +1538,19 @@ final class PhabricatorUser
return $list;
}
// Blender: Limit certain workflow steps to regular contributors, making it
// easier to follow status of the tracker.
public function limitNonContributorUI() {
if ($this->getIsAdmin()) {
return false;
}
$project = id(new PhabricatorProjectQuery())
->setViewer($this)
->withNames(array('Moderators'))
->withMemberPHIDs(array($this->getPHID()))
->executeOne();
return is_null($project);
}
}

View File

@@ -121,9 +121,9 @@ final class PhabricatorUserCardView extends AphrontTagView {
$user->getUsername());
$image = phutil_tag(
'a',
'span',
array(
'href' => $href,
// 'href' => $href,
'class' => 'project-card-image-href',
),
$image);

View File

@@ -0,0 +1,68 @@
<?php
final class PhabricatorUserDisableSpamTransaction
extends PhabricatorUserTransactionType {
const TRANSACTIONTYPE = 'user.disable_spam';
public function generateOldValue($object) {
$user = $object;
return (string)$user->getRealName();
}
public function generateNewValue($object, $value) {
// Deliberately not using 'spam'.
// This way we can use this button even for accounts that
// have been already manually renamed to 'spam'.
// Otherwise when the name clash with the existing name
// none of the changes happens.
return 'disabled_spam';
}
public function applyInternalEffects($object, $value) {
$user = $object;
$user->setRealName('spam');
$profile = $user->loadUserProfile();
$profile->setBlurb('');
$profile->setTitle('');
$profile->setIcon('');
$file = PhabricatorFile::loadBuiltin($user, 'profile.png');
$user->setProfileImagePHID($file->getPHID());
}
public function getTitle() {
return pht(
'%s set this user as spam.',
$this->renderAuthor());
}
public function shouldHideForFeed() {
// Don't publish feed stories about handling spam.
return true;
}
public function validateTransactions($object, array $xactions) {
$errors = array();
foreach ($xactions as $xaction) {
// You must have the "Can Disable Spam Users" permission to disable a user as spam.
$this->requireApplicationCapability(
PeopleDisableSpamUsersCapability::CAPABILITY);
if ($this->getActingAsPHID() === $object->getPHID()) {
$errors[] = $this->newInvalidError(
pht('You can not disable your own account as spam.'));
}
}
return $errors;
}
public function getRequiredCapabilities(
$object,
PhabricatorApplicationTransaction $xaction) {
return null;
}
}

View File

@@ -146,7 +146,16 @@ final class PhabricatorObjectHandle
}
public function getURI() {
return $this->uri;
$type = $this->getType();
if ($type == 'TASK') {
// XXX: Use real link to gitea task
// At least for now rely on the existence of the manip[hest task redirector.
// return 'https://developer.blender.org' . $this->uri;
return $this->uri;
} else if ($type == 'DREV' || $type == 'DIFF' || $type == 'PSTE' || $type == 'FILE') {
return $this->uri;
}
return null;
}
public function setPHID($phid) {
@@ -357,7 +366,7 @@ final class PhabricatorObjectHandle
);
return javelin_tag(
$uri ? 'a' : 'span',
$uri ? 'a' : 'b',
$attributes,
array($circle, $icon, $name));
}
@@ -374,7 +383,7 @@ final class PhabricatorObjectHandle
public function getLinkName() {
switch ($this->getType()) {
case PhabricatorPeopleUserPHIDType::TYPECONST:
$name = $this->getName();
$name = $this->getFullName();
break;
default:
$name = $this->getFullName();

View File

@@ -22,6 +22,10 @@ final class PhabricatorHandlePool extends Phobject {
return $this->viewer;
}
public function getHandles() {
return $this->handles;
}
public function newHandleList(array $phids) {
// Mark any PHIDs we haven't loaded yet as unloaded. This will let us bulk
// load them later.

View File

@@ -56,7 +56,7 @@ final class PhabricatorProjectApplication extends PhabricatorApplication {
'profile/(?P<id>[1-9]\d*)/'
=> 'PhabricatorProjectProfileController',
'view/(?P<id>[1-9]\d*)/'
=> 'PhabricatorProjectViewController',
=> 'PhabricatorProjectProfileController',
'picture/(?P<id>[1-9]\d*)/'
=> 'PhabricatorProjectEditPictureController',
$this->getEditRoutePattern('edit/')
@@ -125,7 +125,7 @@ final class PhabricatorProjectApplication extends PhabricatorApplication {
=> 'PhabricatorProjectSubprojectWarningController',
),
'/tag/' => array(
'(?P<slug>[^/]+)/' => 'PhabricatorProjectViewController',
'(?P<slug>[^/]+)/' => 'PhabricatorProjectProfileController',
'(?P<slug>[^/]+)/board/' => 'PhabricatorProjectBoardViewController',
),
);

View File

@@ -178,8 +178,10 @@ final class PhabricatorProjectBoardViewController
$panel->addClass('project-panel-hidden');
}
$column_menu = $this->buildColumnMenu($project, $column);
$panel->addHeaderAction($column_menu);
if (!$viewer->limitNonContributorUI()) {
$column_menu = $this->buildColumnMenu($project, $column);
$panel->addHeaderAction($column_menu);
}
if ($column->canHaveTrigger()) {
$trigger = $column->getTrigger();

View File

@@ -60,7 +60,7 @@ final class PhabricatorProjectsCurtainExtension
),
$column_name);
$annotation[] = $column_link;
// $annotation[] = $column_link;
}
if ($annotation) {

View File

@@ -37,7 +37,7 @@ final class PhabricatorProjectProjectPHIDType extends PhabricatorPHIDType {
foreach ($handles as $phid => $handle) {
$project = $objects[$phid];
$name = $project->getDisplayName();
$name = $project->getDisplayNameWithAncestorPath();
$id = $project->getID();
$slug = $project->getPrimarySlug();

View File

@@ -224,6 +224,8 @@ final class PhabricatorProjectSearchEngine
protected function getBuiltinQueryNames() {
$names = array();
$names['active'] = pht('Active');
if ($this->requireViewer()->isLoggedIn()) {
$names['joined'] = pht('Joined');
}
@@ -232,7 +234,6 @@ final class PhabricatorProjectSearchEngine
$names['watching'] = pht('Watching');
}
$names['active'] = pht('Active');
$names['all'] = pht('All');
return $names;

View File

@@ -586,6 +586,27 @@ final class PhabricatorProject extends PhabricatorProjectDAO
return $name;
}
public function getDisplayNameWithAncestorPath() {
// Figure out the ancestors for this project
// so that we can prepend that to the display name.
$ancestors = mpull(array_reverse($this->getAncestorProjects()), 'getName');
$project_name_with_path = $this->getName();
if ($this->isMilestone()) {
$project_name_with_path = pht(
'%s (%s)',
implode(' > ', $ancestors),
$project_name_with_path);
} else {
$ancestors[] = $project_name_with_path;
$project_name_with_path = implode(' > ', $ancestors);
}
// No pht usage, since we don't have translatable items.
return $project_name_with_path;
}
public function getDisplayIconKey() {
if ($this->isMilestone()) {
$key = PhabricatorProjectIconSet::getMilestoneIconKey();

View File

@@ -123,7 +123,7 @@ final class PhabricatorProjectDatasource
$proj_result = id(new PhabricatorTypeaheadResult())
->setName($all_strings)
->setDisplayName($proj->getDisplayName())
->setDisplayName($proj->getDisplayNameWithAncestorPath())
->setDisplayType($proj->getDisplayIconName())
->setURI($proj->getURI())
->setPHID($phid)

View File

@@ -162,14 +162,14 @@ final class PhabricatorRepositoryQuery
public function getBuiltinOrders() {
return array(
'committed' => array(
'vector' => array('committed', 'id'),
'name' => pht('Most Recent Commit'),
),
'name' => array(
'vector' => array('name', 'id'),
'name' => pht('Name'),
),
'committed' => array(
'vector' => array('committed', 'id'),
'name' => pht('Most Recent Commit'),
),
'callsign' => array(
'vector' => array('callsign'),
'name' => pht('Callsign'),

View File

@@ -140,6 +140,24 @@ final class PhabricatorRepositorySearchEngine
);
}
private function getOrderOptions() {
return array(
'name' => pht('Name'),
'committed' => pht('Most Recent Commit'),
'callsign' => pht('Callsign'),
'created' => pht('Date Created'),
);
}
private function getOrderValues() {
return array(
'name' => PhabricatorRepositoryQuery::ORDER_NAME,
'committed' => PhabricatorRepositoryQuery::ORDER_COMMITTED,
'callsign' => PhabricatorRepositoryQuery::ORDER_CALLSIGN,
'created' => PhabricatorRepositoryQuery::ORDER_CREATED,
);
}
private function getHostedOptions() {
return array(
'' => pht('Hosted and Remote Repositories'),

View File

@@ -1,6 +1,6 @@
<?php
final class PhabricatorApplicationSearchController
/*final*/ class PhabricatorApplicationSearchController
extends PhabricatorSearchBaseController {
private $searchEngine;
@@ -92,6 +92,10 @@ final class PhabricatorApplicationSearchController
}
}
protected function getDescriptionForQuery($named_query, $dao_query) {
return '';
}
private function processSearchRequest() {
$parent = $this->getDelegatingController();
$request = $this->getRequest();
@@ -214,6 +218,7 @@ final class PhabricatorApplicationSearchController
$title = pht('Advanced Search');
}
$header = id(new PHUIHeaderView())
->setHeader($title)
->setProfileHeader(true);
@@ -255,6 +260,13 @@ final class PhabricatorApplicationSearchController
$objects = $engine->executeQuery($query, $pager);
$description_query = $engine->buildQueryFromSavedQuery($saved_query);
$description_query->setViewer($this->getRequest()->getUser());
$description = $this->getDescriptionForQuery($named_query, $description_query);
if ($description) {
$header->setHeader($description);
}
$force_nux = $request->getBool('nux');
if (!$objects || $force_nux) {
$nux_view = $this->renderNewUserView($engine, $force_nux);

View File

@@ -95,7 +95,7 @@ final class PhabricatorSettingsMainController
$this->preferences = $preferences;
$panels = $this->buildPanels($preferences);
$panels = $this->buildPanels($preferences, true);
$nav = $this->renderSideNav($panels);
$key = $nav->selectFilter($key, head($panels)->getPanelKey());
@@ -136,7 +136,7 @@ final class PhabricatorSettingsMainController
->appendChild($view);
}
private function buildPanels(PhabricatorUserPreferences $preferences) {
private function buildPanels(PhabricatorUserPreferences $preferences, $hide_disabled) {
$viewer = $this->getViewer();
$panels = PhabricatorSettingsPanel::getAllDisplayPanels();
@@ -154,6 +154,10 @@ final class PhabricatorSettingsMainController
continue;
}
if ($hide_disabled && !$panel->isEnabledForUser($viewer)) {
continue;
}
if ($this->isTemplate()) {
if (!$panel->isTemplatePanel()) {
continue;
@@ -221,7 +225,7 @@ final class PhabricatorSettingsMainController
public function buildApplicationMenu() {
if ($this->preferences) {
$panels = $this->buildPanels($this->preferences);
$panels = $this->buildPanels($this->preferences, false);
return $this->renderSideNav($panels)->getMenu();
}
return parent::buildApplicationMenu();

View File

@@ -163,6 +163,9 @@ abstract class PhabricatorSettingsPanel extends Phobject {
return true;
}
public function isEnabledForUser($user) {
return true;
}
/**
* Return true if this panel is available to users while editing their own

View File

@@ -0,0 +1,99 @@
<?php
final class PhabricatorSettingsPanelChangeUsername
extends PhabricatorSettingsPanel {
public function getPanelKey() {
return 'changeusername';
}
public function getPanelGroupKey() {
return PhabricatorSettingsAccountPanelGroup::PANELGROUPKEY;
}
public function getPanelName() {
return pht('Change Username');
}
public function getAlternatives($user) {
$root = dirname(phutil_get_library_root('phabricator'));
require $root.'/migration/dedup.php';
$alternatives = array();
foreach($migrate_dedup_users as $from_user => $to_user) {
if($from_user == $user->getUserName()) {
$alternatives[$to_user] = $to_user;
}
else if($to_user == $user->getUserName()) {
$alternatives[$from_user] = $from_user;
}
}
return $alternatives;
}
public function isEnabledForUser($user) {
return count($this->getAlternatives($user)) > 0;
}
public function processRequest(AphrontRequest $request) {
$user = $request->getUser();
$alternatives = $this->getAlternatives($user);
$new_username = $request->getStr("new_username");
if ($request->isFormPost()) {
if (array_key_exists($new_username, $alternatives)) {
id(new PhabricatorUserEditor())
->setActor($user)
->changeUsername($user, $new_username);
return id(new AphrontRedirectResponse())
->setURI($this->getPanelURI('?saved=true'));
}
}
$instructions = pht(
"Multiple of your accounts were merged into one because because Phabricator does not " .
"support multiple accounts with the same email address. Here you can change your " .
"account name your preferred one. For security purposes you must also enter choose " .
"your password again (can be the same or new), for this you will receive an email.\n\n" .
"Current username: **" . $user->getUserName() . "**.");
$form = id(new AphrontFormView())
->setUser($user)
->appendRemarkupInstructions($instructions)
->appendChild(
id(new AphrontFormSelectControl())
->setLabel(pht('Other Username'))
->setName("new_username")
->setValue($user->getUserName())
->setOptions($alternatives))
->appendChild(
id(new AphrontFormSubmitControl())
->setValue(pht('Change Username')));
$error_view = null;
if ($request->getBool('saved')) {
$error_view = id(new AphrontErrorView())
->setTitle(pht('Username changed'))
->setSeverity(AphrontErrorView::SEVERITY_NOTICE)
->setErrors(array(pht('Your username has been changed, check your mail inbox for instructions on how to reset your password.')));
}
$errors = array();
if ($error_view) {
$errors[] = $error_view;
}
$form_box = id(new PHUIObjectBoxView())
->setHeaderText(pht('Change Username'))
->setFormErrors($errors)
->setForm($form);
return array(
$form_box,
);
}
}

View File

@@ -76,14 +76,10 @@ final class PhabricatorSubscriptionsCurtainExtension
}
if ($show_all) {
$view_all_uri = urisprintf(
'/subscriptions/list/%s/',
$object_phid);
$ref_list->newTailLink()
->setURI($view_all_uri)
->setText(pht('View All %d Subscriber(s)', $subscriber_count))
->setWorkflow(true);
$num_extra = $subscriber_count - $max_visible;
if ($num_extra > 0) {
$ref_list->addTailObject("{$num_extra} More Subscribers");
}
}
return $this->newPanel()

View File

@@ -112,8 +112,8 @@ final class PhabricatorSubscriptionsUIEventListener
$actions = $event->getValue('actions');
$actions[] = $sub_action;
$actions[] = $mute_action;
// $actions[] = $sub_action;
// $actions[] = $mute_action;
$event->setValue('actions', $actions);
}

Some files were not shown because too many files have changed in this diff Show More