This task contains:
- A script for copying values from an older "points" field in Maniphest using Custom Fields to the new formal "points" field.
- A script for moving existing, top-level projects underneath other existing, top-level projects as milestones or subprojects.
Neither workflow is formally supported by the upstream, and we do not currently plan to maintain these scripts. The were written circa February 2016, and may not work (and may even be dangerous) if run against future versions of Phabricator.
Script For Copying Points From a Custom Field
This script emits SQL you can use to copy an existing custom "Points" field into the new first-class "Points" field.
To run this script:
- Put it in `phabricator/`
- Make it executable with `chmod +x copy_points.php`
- Run it as `./copy_points.php`
- It will walk you through giving it the information it needs, primarily a `--field <field key>` argument to pick which field to copy from.
The script just prints SQL statements to stdout. It does not touch the database, so **running it won't make any actual changes** to the data. Here's an example run:
$ ./copy_points.php --field std:maniphest:birthday
UPDATE `phabricator_maniphest`.`maniphest_task` SET points = 238 WHERE id = 216;
Generally, the migration process will probably look something like this:
- Run the script.
- Look at the output SQL to make sure it seems OK.
- Load a couple of tasks to double-check (e.g., for the output above, load `T216` in the web UI and make sure it should have 238 points).
- Pipe the SQL into MySQL to actually run it.
That might look like this:
$ ./copy_points.php --field whatever > points.sql
$ cat points.sql # Look at the results and sanity check them.
$ cat points.sql | mysql -u root
The script will not copy points to tasks that already have a "points" value. If you make a mistake (for example, copy the wrong field) and need to wipe out all the "new" points values in all tasks so you can do another copy of everything, you can use this query:
/* DANGEROUS! DESTROYS DATA! */ UPDATE phabricator_maniphest.maniphest_task SET points = null;
That will destroy the "new" points, but leave any custom points untouched. Then you can use `copy_points.php` again to do a fresh copy.
Here's the actual script:
Script For Moving Projects Underneath Other Projects
This script moves an existing, top-level project underneath another existing project, turning it into either a subproject or a milestone.
To run this script:
- Put it in `phabricator/`.
- Make it executable with `chmod +x move_beneath.php`.
- Run it as `./move_beneath.php`.
- It will walk you through giving it the information it needs.
IMPORTANT: This script **mutates data immediately, without prompting, and can not be undone**. Double check your command line before running it!
Here's an example run:
$ ./move_beneath.php --parent p1 --child p2 --keep-members both --subproject
Broadly, you will use these flags:
- `--parent <id|phid|hashtag>` Choose which project will be the parent. This project must not already be a milestone.
- `--child <id|phid|hashtag>` Choose which project will be the child. This project must be a top-level project with no children of its own -- this script can not move project trees. Plan ahead! This project must not be the same as the parent project.
- `--subproject` or `--milestone` Choose whether the child should become a subproject or a milestone.
- `--keep-members <both|child|parent>` Choose which members to keep (and, implicitly, which to destroy). See below for discussion.
These are mostly straightforward, except for `--keep-members`. Broadly, when moving projects, we must adjust membership because subprojects and milestones have these special rules:
- Milestones can not have their own members (they have the same members as their parent).
- Projects with subprojects can not have their own members (they have the union of all children as members).
When you move a child under a parent, one of them either becomes a milestone or a project with subprojects, and thus can not have members. We have to do something with the invalid members.
With `--keep-members both`, overall member ship will be preserved. If the child is becoming a milestone, members will be copied to the parent. If the child is becoming a subproject, members will be copied to the child. This mode is safe, and won't destroy data, although it could make users members of projects you don't want or expect them to be members of.
With `--keep-members parent`, the child's members will be wiped out. If the child is becoming a milestone, nothing else happens. If the child is becoming a subproject, the parent's members are then copied to the child.
With `--keep-members child`, the parent's members will be wiped out. If the child is becoming a milestone, the members are then copied. If the child is becoming a subproject, nothing else happens.
Note that when you are making the child a milestone of a parent with subprojects, **neither project may have members**! The script will only permit this operation with `--keep-members parent`, which wipes child members and leaves parent members untouched (the union of all subprojects). If a milestone has unique members and you want to perform this operation and retain them, you need to manually move them to some subproject of the parent.
WARNING: I've made a reasonable effort to test this locally, and will make a reasonable effort to help repair any damage it causes, but this is basically a big hack. So, be careful with it, make a backup first, do some small runs on test data before converting hundreds of projects with thousands of members, let someone else run it first and complain that I wiped their install, etc., etc.
Here's the actual script:
- See https://phabricator.wikimedia.org/project/profile/483/ for an example of using faked sub-projects.