diff options
35 files changed, 1115 insertions, 645 deletions
diff --git a/UPGRADING b/UPGRADING deleted file mode 100644 index 863fde3..0000000 --- a/UPGRADING +++ /dev/null @@ -1,610 +0,0 @@ -Upgrading -========= - -From 3.0.0 to 3.1.0 -------------------- - -1. Increase the size of all fields containing package names, license names, -group names or package versions: - ----- -ALTER TABLE PackageBases MODIFY Name VARCHAR(255) NOT NULL; -ALTER TABLE Packages - MODIFY Name VARCHAR(255) NOT NULL, - MODIFY Version VARCHAR(255) NOT NULL DEFAULT ''; -ALTER TABLE Licenses MODIFY Name VARCHAR(255) NOT NULL; -ALTER TABLE Groups MODIFY Name VARCHAR(255) NOT NULL; -ALTER TABLE PackageDepends MODIFY DepCondition VARCHAR(255); -ALTER TABLE PackageRelations MODIFY RelCondition VARCHAR(255); ----- - -From 2.3.1 to 3.0.0 -------------------- - -1. Drop the user ID foreign key from the "PackageComments" table: - -`ALTER TABLE PackageComments DROP FOREIGN KEY PackageComments_ibfk_1;` should -work in most cases. Otherwise, check the output of `SHOW CREATE TABLE -PackageComments;` and use the foreign key name shown there. - -2. Add support for anonymous comments: - ----- -ALTER TABLE PackageComments - MODIFY UsersID INTEGER UNSIGNED NULL DEFAULT NULL, - ADD FOREIGN KEY (UsersID) REFERENCES Users(ID) ON DELETE SET NULL; ----- - -3. Create the PackageBases table: - ----- -CREATE TABLE PackageBases ( - ID INTEGER UNSIGNED NOT NULL AUTO_INCREMENT, - Name VARCHAR(64) NOT NULL, - CategoryID TINYINT UNSIGNED NOT NULL DEFAULT 1, - NumVotes INTEGER UNSIGNED NOT NULL DEFAULT 0, - OutOfDateTS BIGINT UNSIGNED NULL DEFAULT NULL, - SubmittedTS BIGINT UNSIGNED NOT NULL, - ModifiedTS BIGINT UNSIGNED NOT NULL, - SubmitterUID INTEGER UNSIGNED NULL DEFAULT NULL, - MaintainerUID INTEGER UNSIGNED NULL DEFAULT NULL, - PackagerUID INTEGER UNSIGNED NULL DEFAULT NULL, - PRIMARY KEY (ID), - UNIQUE (Name), - INDEX (CategoryID), - INDEX (NumVotes), - INDEX (SubmitterUID), - INDEX (MaintainerUID), - INDEX (PackagerUID), - FOREIGN KEY (CategoryID) REFERENCES PackageCategories(ID) ON DELETE NO ACTION, - -- deleting a user will cause packages to be orphaned, not deleted - FOREIGN KEY (SubmitterUID) REFERENCES Users(ID) ON DELETE SET NULL, - FOREIGN KEY (MaintainerUID) REFERENCES Users(ID) ON DELETE SET NULL, - FOREIGN KEY (PackagerUID) REFERENCES Users(ID) ON DELETE SET NULL -) ENGINE = InnoDB; ----- - -4. Migrate data from Packages to PackageBases: - ----- -INSERT INTO PackageBases - SELECT ID, Name, CategoryID, NumVotes, OutOfDateTS, SubmittedTS, - ModifiedTS, SubmitterUID, MaintainerUID, NULL FROM Packages; ----- - -5. Delete unneeded foreign keys from Packages: - -First, drop the foreign keys on CategoryID, SubmitterUID and MaintainerUID. The -following queries should work in most cases: - ----- -ALTER TABLE Packages - DROP FOREIGN KEY Packages_ibfk_1, - DROP FOREIGN KEY Packages_ibfk_2, - DROP FOREIGN KEY Packages_ibfk_3; ----- - -You can use `SHOW CREATE TABLE Packages;` to check whether you should use -different names for your setup. - -6. Delete unneeded fields from Packages: - ----- -ALTER TABLE Packages - DROP COLUMN CategoryID, - DROP COLUMN NumVotes, - DROP COLUMN OutOfDateTS, - DROP COLUMN SubmittedTS, - DROP COLUMN ModifiedTS, - DROP COLUMN SubmitterUID, - DROP COLUMN MaintainerUID; ----- - -7. Add package base references to the Packages table: - ----- -ALTER TABLE Packages ADD COLUMN PackageBaseID INTEGER UNSIGNED NULL; -UPDATE Packages SET PackageBaseID = ID; -ALTER TABLE Packages - MODIFY PackageBaseID INTEGER UNSIGNED NOT NULL, - ADD FOREIGN KEY (PackageBaseID) REFERENCES PackageBases(ID) ON DELETE CASCADE; ----- - -8. Delete foreign keys from PackageVotes, PackageComments and CommentNotify: - ----- -ALTER TABLE PackageVotes - DROP FOREIGN KEY PackageVotes_ibfk_1, - DROP FOREIGN KEY PackageVotes_ibfk_2; -ALTER TABLE PackageComments - DROP FOREIGN KEY PackageComments_ibfk_3; -ALTER TABLE CommentNotify - DROP FOREIGN KEY CommentNotify_ibfk_1, - DROP FOREIGN KEY CommentNotify_ibfk_2; ----- - -We highly recommend to use `SHOW CREATE TABLE PackageVotes;` etc. to check -whether you should use different names for your setup. - -9. Delete indexes from PackageVotes and CommentNotify: - ----- -ALTER TABLE PackageVotes DROP INDEX VoteUsersIDPackageID; -ALTER TABLE CommentNotify DROP INDEX NotifyUserIDPkgID; ----- - -10. Migrate PackageVotes, PackageComments and CommentNotify to refer to package -bases: - ----- -ALTER TABLE PackageVotes ADD COLUMN PackageBaseID INTEGER UNSIGNED NOT NULL; -UPDATE PackageVotes SET PackageBaseID = PackageID; -ALTER TABLE PackageVotes DROP COLUMN PackageID; -ALTER TABLE PackageComments ADD COLUMN PackageBaseID INTEGER UNSIGNED NOT NULL; -UPDATE PackageComments SET PackageBaseID = PackageID; -ALTER TABLE PackageComments DROP COLUMN PackageID; -ALTER TABLE CommentNotify ADD COLUMN PackageBaseID INTEGER UNSIGNED NOT NULL; -UPDATE CommentNotify SET PackageBaseID = PkgID; -ALTER TABLE CommentNotify DROP COLUMN PkgID; ----- - -11. Recreate missing foreign keys and indexes: - ----- -ALTER TABLE PackageVotes - ADD FOREIGN KEY (UsersID) REFERENCES Users(ID) ON DELETE CASCADE, - ADD FOREIGN KEY (PackageBaseID) REFERENCES PackageBases(ID) ON DELETE CASCADE; -ALTER TABLE PackageComments - ADD FOREIGN KEY (PackageBaseID) REFERENCES PackageBases(ID) ON DELETE CASCADE; -ALTER TABLE CommentNotify - ADD FOREIGN KEY (PackageBaseID) REFERENCES PackageBases(ID) ON DELETE CASCADE, - ADD FOREIGN KEY (UserID) REFERENCES Users(ID) ON DELETE CASCADE; -CREATE UNIQUE INDEX VoteUsersIDPackageID ON PackageVotes (UsersID, PackageBaseID); -CREATE UNIQUE INDEX NotifyUserIDPkgID ON CommentNotify (UserID, PackageBaseID); ----- - -12. Create a new table to store package dependency types: - ----- -CREATE TABLE DependencyTypes ( - ID TINYINT UNSIGNED NOT NULL AUTO_INCREMENT, - Name VARCHAR(32) NOT NULL DEFAULT '', - PRIMARY KEY (ID) -) ENGINE = InnoDB; -INSERT INTO DependencyTypes VALUES (1, 'depends'); -INSERT INTO DependencyTypes VALUES (2, 'makedepends'); -INSERT INTO DependencyTypes VALUES (3, 'checkdepends'); -INSERT INTO DependencyTypes VALUES (4, 'optdepends'); ----- - -13. Add a field to store the dependency type to the PackageDepends table: - ----- -ALTER TABLE PackageDepends ADD COLUMN DepTypeID TINYINT UNSIGNED NOT NULL; -UPDATE PackageDepends SET DepTypeID = 1; -ALTER TABLE PackageDepends - ADD FOREIGN KEY (DepTypeID) REFERENCES DependencyTypes(ID) ON DELETE NO ACTION; ----- - -14. Resize the package dependency name field: - ----- -ALTER TABLE PackageDepends MODIFY DepName VARCHAR(255) NOT NULL; ----- - -15. Create a new table to store package relation types: - ----- -CREATE TABLE RelationTypes ( - ID TINYINT UNSIGNED NOT NULL AUTO_INCREMENT, - Name VARCHAR(32) NOT NULL DEFAULT '', - PRIMARY KEY (ID) -) ENGINE = InnoDB; -INSERT INTO RelationTypes VALUES (1, 'conflicts'); -INSERT INTO RelationTypes VALUES (2, 'provides'); -INSERT INTO RelationTypes VALUES (3, 'replaces'); ----- - -16. Create a new table to store package relations: - ----- -CREATE TABLE PackageRelations ( - PackageID INTEGER UNSIGNED NOT NULL, - RelTypeID TINYINT UNSIGNED NOT NULL, - RelName VARCHAR(255) NOT NULL, - RelCondition VARCHAR(20), - INDEX (PackageID), - INDEX (RelName), - FOREIGN KEY (PackageID) REFERENCES Packages(ID) ON DELETE CASCADE, - FOREIGN KEY (RelTypeID) REFERENCES RelationTypes(ID) ON DELETE NO ACTION -) ENGINE = InnoDB; ----- - -17. Create tables to store package groups: - ----- -CREATE TABLE Groups ( - ID INTEGER UNSIGNED NOT NULL AUTO_INCREMENT, - Name VARCHAR(64) NOT NULL, - PRIMARY KEY (ID), - UNIQUE (Name) -) ENGINE = InnoDB; -CREATE TABLE PackageGroups ( - PackageID INTEGER UNSIGNED NOT NULL, - GroupID INTEGER UNSIGNED NOT NULL, - PRIMARY KEY (PackageID, GroupID), - FOREIGN KEY (PackageID) REFERENCES Packages(ID) ON DELETE CASCADE, - FOREIGN KEY (GroupID) REFERENCES Groups(ID) ON DELETE CASCADE -) ENGINE = InnoDB; ----- - -18. Create tables to store package licenses: - ----- -CREATE TABLE Licenses ( - ID INTEGER UNSIGNED NOT NULL AUTO_INCREMENT, - Name VARCHAR(64) NOT NULL, - PRIMARY KEY (ID), - UNIQUE (Name) -) ENGINE = InnoDB; -CREATE TABLE PackageLicenses ( - PackageID INTEGER UNSIGNED NOT NULL, - LicenseID INTEGER UNSIGNED NOT NULL, - PRIMARY KEY (PackageID, LicenseID), - FOREIGN KEY (PackageID) REFERENCES Packages(ID) ON DELETE CASCADE, - FOREIGN KEY (LicenseID) REFERENCES Licenses(ID) ON DELETE CASCADE -) ENGINE = InnoDB; ----- - -19. Convert existing licenses to the new storage format: - ----- -INSERT INTO Licenses (Name) SELECT DISTINCT License FROM Packages; -INSERT INTO PackageLicenses (PackageID, LicenseID) - SELECT Packages.ID, Licenses.ID FROM Packages - INNER JOIN Licenses ON Licenses.Name = Packages.License; ----- - -20. Delete the license column from the Packages table: - ----- -ALTER TABLE Packages DROP COLUMN License; ----- - -From 2.2.0 to 2.3.0 -------------------- - -1. Add registration and inactivity time stamps to the "Users" table: - ----- -ALTER TABLE Users - ADD COLUMN RegistrationTS TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, - ADD COLUMN InactivityTS BIGINT NOT NULL DEFAULT 0; ----- - -2. Add fields to store the total number of TUs and the quorum to the - "TU_VoteInfo" table: - ----- -ALTER TABLE TU_VoteInfo - ADD COLUMN ActiveTUs tinyint(3) unsigned NOT NULL default '0', - ADD COLUMN Quorum decimal(2, 2) unsigned NOT NULL; ----- - -3. Add a "fonts" category: - ----- -INSERT INTO PackageCategories (Category) VALUES ('fonts'); ----- - -From 2.1.0 to 2.2.0 -------------------- - -1. Add new "Users" table login IP address column: - ----- -ALTER TABLE Users - ADD COLUMN LastLoginIPAddress INTEGER UNSIGNED NOT NULL DEFAULT 0; ----- - -2. Add a new "Bans" table: - ----- -CREATE TABLE Bans ( - IPAddress INTEGER UNSIGNED NOT NULL DEFAULT 0, - BanTS TIMESTAMP NOT NULL, - PRIMARY KEY (IPAddress) -) ENGINE = InnoDB; ----- - -From 2.0.0 to 2.1.0 -------------------- - -1. Update your aurblup setup to match configuration changes. See commit -6dc61e7d9e87ad6821869dab61e5f005af2e0252 for details. - -From 1.9.1 to 2.0.0 -------------------- - -1. Add new "Users" table login date and PGP key columns: - ----- -ALTER TABLE Users ADD COLUMN LastLogin BIGINT NOT NULL DEFAULT 0; -ALTER TABLE Users ADD COLUMN PGPKey VARCHAR(40) NULL DEFAULT NULL; ----- - -2. Merge "web/lib/config.inc.php.proto" with "web/lib/config.inc.php". - -3. Enable the PDO MySQL extension (pdo_mysql.so) in "php.ini". - -4. Upgrade to PHP>=5.4.0 or enable "short_open_tag" in "php.ini". - -5. Install translations by running `make install` in "po/". - -From 1.9.0 to 1.9.1 -------------------- - -1. Merge "web/lib/config.inc.php.proto" with "web/lib/config.inc.php". - -2. Install translations by running `make install` in "po/". - -From 1.8.2 to 1.9.0 -------------------- - -1. Translation files are now gettext compatible and need to be compiled after -each AUR upgrade by running `make install` in the "po/" directory. - -2. Remove the "NewPkgNotify" column from the "Users" table: - -ALTER TABLE Users DROP COLUMN NewPkgNotify; - -3. Fix up issues with depends performance on large dataset. - -ALTER TABLE PackageDepends ADD INDEX (DepName); - -4. Rename "web/lib/config.inc" to "web/lib/config.inc.php". - -5. Merge "web/lib/config.inc.php.proto" with "web/lib/config.inc.php". - -6. Run the upload directory transform script ("scripts/uploadbuckets.sh") and -rotate the converted directory structure into place. - -7. In order to to provide backward compatible package URLs, enable mod_rewrite -and add the following to your Apache configuration (inside the "VirtualHost" -container or optionally create a ".htaccess" file in the upload directory): - ----- -RewriteEngine on -RewriteRule ^/packages/([^/]{1,2})([^/]*/(PKGBUILD|[^/]*\.tar\.gz|))$ /packages/$1/$1$2 ----- - -The following equivalent rule can be used for lighttpd setups: - ----- -url.rewrite-once = ( "^/packages/([^/]{1,2})([^/]*/(PKGBUILD|[^/]*\.tar\.gz|))$" => "/packages/$1/$1$2" ) ----- - -If you use a non-standard URL_DIR, slight modifications might be necessary. - -8. Merge "scripts/aurblup/config.h.proto" with "scripts/aurblup/config.h". - -From 1.8.1 to 1.8.2 -------------------- - -1. Update the modified package timestamp for new packages. - -UPDATE Packages SET ModifiedTS = SubmittedTS WHERE ModifiedTS = 0; - -2. Move to new method of storing package depends. - ----- -ALTER TABLE PackageDepends ADD COLUMN DepName VARCHAR(64) NOT NULL DEFAULT '' AFTER PackageID; -UPDATE PackageDepends SET DepName = (SELECT Name FROM Packages WHERE ID = DepPkgID); -ALTER TABLE PackageDepends MODIFY DepName VARCHAR(64) NOT NULL; -ALTER TABLE PackageDepends DROP FOREIGN KEY `PackageDepends_ibfk_2`; -ALTER TABLE PackageDepends DROP COLUMN DepPkgID; -DELETE FROM Packages WHERE DummyPkg = 1; -ALTER TABLE Packages DROP COLUMN DummyPkg; ----- - -3. The File_Find PEAR module is no longer required. You can safely uninstall it -if nothing else depends on it. - -From 1.8.0 to 1.8.1 -------------------- - -1. Drop foreign keys from the "Sessions" table: - -`ALTER TABLE Sessions DROP FOREIGN KEY Sessions_ibfk_1;` should work in most -cases. Otherwise, check the output of `SHOW CREATE TABLE Sessions;` and use the -foreign key name shown there. - -2. Run the following MySQL statements: - ----- -ALTER TABLE Sessions - ADD FOREIGN KEY (UsersID) REFERENCES Users(ID) ON DELETE CASCADE; -ALTER TABLE PackageDepends - ADD FOREIGN KEY (PackageID) REFERENCES Packages(ID) ON DELETE CASCADE, - ADD FOREIGN KEY (DepPkgID) REFERENCES Packages(ID) ON DELETE CASCADE; -ALTER TABLE PackageSources - ADD FOREIGN KEY (PackageID) REFERENCES Packages(ID) ON DELETE CASCADE; -ALTER TABLE TU_VoteInfo - ADD FOREIGN KEY (SubmitterID) REFERENCES Users(ID) ON DELETE CASCADE; -ALTER TABLE TU_Votes - ADD FOREIGN KEY (VoteID) REFERENCES TU_VoteInfo(ID) ON DELETE CASCADE, - ADD FOREIGN KEY (UserID) REFERENCES Users(ID) ON DELETE CASCADE; -ALTER TABLE PackageComments - MODIFY DelUsersID INTEGER UNSIGNED NULL DEFAULT NULL; -UPDATE PackageComments SET DelUsersID = NULL WHERE DelUsersID = 0; -ALTER TABLE Packages - MODIFY SubmitterUID INTEGER UNSIGNED NULL DEFAULT NULL, - MODIFY MaintainerUID INTEGER UNSIGNED NULL DEFAULT NULL; -UPDATE Packages SET SubmitterUID = NULL WHERE SubmitterUID = 0; -UPDATE Packages SET MaintainerUID = NULL WHERE MaintainerUID = 0; ----- - -3. (optional) If you converted your database from MyISAM to InnoDB during the -upgrade process from 1.7.0 to 1.8.0 or from 1.8.0 to 1.8.1 without completely -rebuilding the database from the MySQL schema, you should additionally run the -following MySQL statements to add missing foreign keys: - ----- -ALTER TABLE Users - ADD FOREIGN KEY (AccountTypeID) REFERENCES AccountTypes(ID) ON DELETE NO ACTION; -ALTER TABLE Packages - ADD FOREIGN KEY (CategoryID) REFERENCES PackageCategories(ID) ON DELETE NO ACTION, - ADD FOREIGN KEY (SubmitterUID) REFERENCES Users(ID) ON DELETE NO ACTION, - ADD FOREIGN KEY (MaintainerUID) REFERENCES Users(ID) ON DELETE NO ACTION; -ALTER TABLE PackageVotes - ADD FOREIGN KEY (UsersID) REFERENCES Users(ID) ON DELETE CASCADE, - ADD FOREIGN KEY (PackageID) REFERENCES Packages(ID) ON DELETE CASCADE; -ALTER TABLE PackageComments - ADD FOREIGN KEY (UsersID) REFERENCES Users(ID) ON DELETE CASCADE, - ADD FOREIGN KEY (DelUsersID) REFERENCES Users(ID) ON DELETE CASCADE, - ADD FOREIGN KEY (PackageID) REFERENCES Packages(ID) ON DELETE CASCADE; -ALTER TABLE CommentNotify - ADD FOREIGN KEY (PkgID) REFERENCES Packages(ID) ON DELETE CASCADE, - ADD FOREIGN KEY (UserID) REFERENCES Users(ID) ON DELETE CASCADE; ----- - -4. Merge "web/lib/config.inc.proto" with "web/lib/config.inc". - -From 1.7.0 to 1.8.0 -------------------- - -1. Run the following MySQL statements: - ----- -ALTER TABLE Packages ADD OutOfDateTS BIGINT UNSIGNED NULL DEFAULT NULL; -UPDATE Packages SET OutOfDateTS = UNIX_TIMESTAMP() WHERE OutOfDate = 1; -ALTER TABLE Packages DROP OutOfDate, DROP FSPath, DROP URLPath, DROP LocationID; -DROP TABLE PackageLocations, PackageContents; -ALTER TABLE AccountTypes MODIFY AccountType VARCHAR(32) NOT NULL DEFAULT ''; -ALTER TABLE Users MODIFY Username VARCHAR(32) NOT NULL, - MODIFY Email VARCHAR(64) NOT NULL, - MODIFY RealName VARCHAR(64) NOT NULL DEFAULT '', - MODIFY LangPreference VARCHAR(5) NOT NULL DEFAULT 'en', - MODIFY IRCNick VARCHAR(32) NOT NULL DEFAULT ''; -ALTER TABLE PackageCategories MODIFY Category VARCHAR(32) NOT NULL; -ALTER TABLE Packages MODIFY Name VARCHAR(64) NOT NULL, - MODIFY Version VARCHAR(32) NOT NULL DEFAULT '', - MODIFY Description VARCHAR(255) NOT NULL DEFAULT "An Arch Package", - MODIFY URL VARCHAR(255) NOT NULL DEFAULT "https://www.archlinux.org", - MODIFY License VARCHAR(40) NOT NULL DEFAULT ''; -ALTER TABLE PackageSources - MODIFY Source VARCHAR(255) NOT NULL DEFAULT "/dev/null"; -ALTER TABLE TU_VoteInfo - MODIFY User VARCHAR(32) collate latin1_general_ci NOT NULL; -CREATE TABLE PackageBlacklist ( - ID INTEGER UNSIGNED NOT NULL AUTO_INCREMENT, - Name VARCHAR(64) NOT NULL, - PRIMARY KEY (ID), - UNIQUE (Name) -); ----- - -2. Drop all fulltext indexes from the "Packages" table: - -Please do this with care. `ALTER TABLE Packages DROP INDEX Name;` will work in -most cases but might remove the wrong index if your indexes have been created -in a non-standard order (e.g. during some update process). You'd better run -`SHOW INDEX FROM Packages;` before to ensure that your setup doesn't use a -different naming. - -3. You will need to update all packages which are stored in the incoming dir as -in 1.8.0, source tarballs are no longer extracted automatically and PKGBUILDs -are from now on located in the same subdirectories as the tarballs themselves. -The following script will do the conversion automatically when being run inside -"$INCOMING_DIR": - ----- -#!/bin/bash - -for pkg in *; do - if [ -d "${pkg}" -a ! -f "${pkg}/PKGBUILD" ]; then - pkgbuild_file=$(find -P "${pkg}" -name PKGBUILD) - [ -n "${pkgbuild_file}" ] && \ - cp "${pkgbuild_file}" "${pkg}/PKGBUILD" - fi -done ----- - -4. (optional): 1.8.0 includes a helper utility called "aurblup" that can be -used to prevent users from uploading source packages with names identical to -packages in predefined binary repos, e.g. the official repositories of your -distribution. In order to build and install aurblup, enter the following -commands: - - cd scripts/aurblup/ - make config.h - $EDITOR config.h - make install # as root - -Add something like "0 * * * * /usr/local/bin/aurblup" to root's crontab to make -aurblup update the package blacklist every hour. - -NOTE: You can run aurblup as non-privileged user as well. Make sure that the -user has read-write access to "/var/lib/aurblup/" (or whatever you defined with -"ALPM_DBPATH") tho. - -5. (optional): As of 1.8.0, all MySQL tables should be InnoDB compatible. To -convert a table, you can use this statement: `ALTER TABLE $foo ENGINE=InnoDB;`. -If you want to stick with MyISAM or another storage engine that doesn't support -transactions, you will need to disable the "MYSQL_USE_TRANSACTIONS" setting in -"config.h" when setting up aurblup. - -From 1.6.0 to 1.7.0 -------------------- -ALTER TABLE Users ADD Salt CHAR(32) NOT NULL DEFAULT ''; -ALTER TABLE Users ADD ResetKey CHAR(32) NOT NULL DEFAULT ''; -ALTER TABLE Users MODIFY LangPreference CHAR(5) NOT NULL DEFAULT 'en'; - - -From 1.5.2 to 1.5.3 -------------------- -1. Ensure this appears in config.inc: - define("DEFAULT_LANG", "en"); - - -From 1.5.1 to 1.5.2 -------------------- -1. Ensure Pear and File/Find.php are in the path. See web/README.txt. - -2. Update your running copy of support/scripts/newpackage-notify. - -3. Run this in web/lib: -<?php - -# Run the script from within lib -include('config.inc'); -include('aur.inc'); - -$query = "UPDATE Packages SET " . - "FSPath = CONCAT('" . INCOMING_DIR . "', Name, '/', Name, -'.tar.gz'), " . - "URLPath = CONCAT('" . URL_DIR . "', Name, '/', Name, '.tar.gz') " . - "WHERE DummyPKG = 0 AND LocationID = 2;"; - -$dbh = db_connect(); -db_query($query, $dbh); - -$query = "ALTER TABLE Packages DROP COLUMN AURMaintainerUID;"; -db_query($query, $dbh); - - -1.3.0 ------ -ALTER TABLE PackageDepends ADD COLUMN DepCondition VARCHAR(20) AFTER DepPkgID; -ALTER TABLE Packages ADD License CHAR(40) NOT NULL DEFAULT ''; - - -1.2.10 ------- -ALTER TABLE Packages MODIFY Description CHAR(255) NOT NULL DEFAULT "An Arch Package"; - - -longerpkgname -------------- -ALTER TABLE Packages MODIFY Name CHAR(64) NOT NULL; - diff --git a/schema/aur-schema.sql b/schema/aur-schema.sql index 0efae93..1ec7385 100644 --- a/schema/aur-schema.sql +++ b/schema/aur-schema.sql @@ -288,6 +288,37 @@ CREATE TABLE PackageBlacklist ( UNIQUE (Name) ) ENGINE = InnoDB; +-- Define package request types +-- +CREATE TABLE RequestTypes ( + ID TINYINT UNSIGNED NOT NULL AUTO_INCREMENT, + Name VARCHAR(32) NOT NULL DEFAULT '', + PRIMARY KEY (ID) +) ENGINE = InnoDB; +INSERT INTO RequestTypes VALUES (1, 'deletion'); +INSERT INTO RequestTypes VALUES (2, 'orphan'); +INSERT INTO RequestTypes VALUES (3, 'merge'); + +-- Package requests +-- +CREATE TABLE PackageRequests ( + ID BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, + ReqTypeID TINYINT UNSIGNED NOT NULL, + PackageBaseID INTEGER UNSIGNED NULL, + PackageBaseName VARCHAR(255) NOT NULL, + MergeBaseName VARCHAR(255) NULL, + UsersID INTEGER UNSIGNED NULL DEFAULT NULL, + Comments TEXT NOT NULL DEFAULT '', + RequestTS BIGINT UNSIGNED NOT NULL DEFAULT 0, + Status TINYINT UNSIGNED NOT NULL DEFAULT 0, + PRIMARY KEY (ID), + INDEX (UsersID), + INDEX (PackageBaseID), + FOREIGN KEY (ReqTypeID) REFERENCES RequestTypes(ID) ON DELETE NO ACTION, + FOREIGN KEY (UsersID) REFERENCES Users(ID) ON DELETE SET NULL, + FOREIGN KEY (PackageBaseID) REFERENCES PackageBases(ID) ON DELETE SET NULL +) ENGINE = InnoDB; + -- Vote information -- CREATE TABLE IF NOT EXISTS TU_VoteInfo ( diff --git a/upgrading/1.2.10.txt b/upgrading/1.2.10.txt new file mode 100644 index 0000000..1b94011 --- /dev/null +++ b/upgrading/1.2.10.txt @@ -0,0 +1 @@ +ALTER TABLE Packages MODIFY Description CHAR(255) NOT NULL DEFAULT "An Arch Package"; diff --git a/upgrading/1.3.0.txt b/upgrading/1.3.0.txt new file mode 100644 index 0000000..b95496a --- /dev/null +++ b/upgrading/1.3.0.txt @@ -0,0 +1,2 @@ +ALTER TABLE PackageDepends ADD COLUMN DepCondition VARCHAR(20) AFTER DepPkgID; +ALTER TABLE Packages ADD License CHAR(40) NOT NULL DEFAULT ''; diff --git a/upgrading/1.5.2.txt b/upgrading/1.5.2.txt new file mode 100644 index 0000000..424daac --- /dev/null +++ b/upgrading/1.5.2.txt @@ -0,0 +1,22 @@ +1. Ensure Pear and File/Find.php are in the path. See web/README.txt. + +2. Update your running copy of support/scripts/newpackage-notify. + +3. Run this in web/lib: +<?php + +# Run the script from within lib +include('config.inc'); +include('aur.inc'); + +$query = "UPDATE Packages SET " . + "FSPath = CONCAT('" . INCOMING_DIR . "', Name, '/', Name, +'.tar.gz'), " . + "URLPath = CONCAT('" . URL_DIR . "', Name, '/', Name, '.tar.gz') " . + "WHERE DummyPKG = 0 AND LocationID = 2;"; + +$dbh = db_connect(); +db_query($query, $dbh); + +$query = "ALTER TABLE Packages DROP COLUMN AURMaintainerUID;"; +db_query($query, $dbh); diff --git a/upgrading/1.5.3.txt b/upgrading/1.5.3.txt new file mode 100644 index 0000000..b38159f --- /dev/null +++ b/upgrading/1.5.3.txt @@ -0,0 +1,2 @@ +1. Ensure this appears in config.inc: + define("DEFAULT_LANG", "en"); diff --git a/upgrading/1.7.0.txt b/upgrading/1.7.0.txt new file mode 100644 index 0000000..4720da1 --- /dev/null +++ b/upgrading/1.7.0.txt @@ -0,0 +1,3 @@ +ALTER TABLE Users ADD Salt CHAR(32) NOT NULL DEFAULT ''; +ALTER TABLE Users ADD ResetKey CHAR(32) NOT NULL DEFAULT ''; +ALTER TABLE Users MODIFY LangPreference CHAR(5) NOT NULL DEFAULT 'en'; diff --git a/upgrading/1.8.0.txt b/upgrading/1.8.0.txt new file mode 100644 index 0000000..7b1dcc0 --- /dev/null +++ b/upgrading/1.8.0.txt @@ -0,0 +1,80 @@ +1. Run the following MySQL statements: + +---- +ALTER TABLE Packages ADD OutOfDateTS BIGINT UNSIGNED NULL DEFAULT NULL; +UPDATE Packages SET OutOfDateTS = UNIX_TIMESTAMP() WHERE OutOfDate = 1; +ALTER TABLE Packages DROP OutOfDate, DROP FSPath, DROP URLPath, DROP LocationID; +DROP TABLE PackageLocations, PackageContents; +ALTER TABLE AccountTypes MODIFY AccountType VARCHAR(32) NOT NULL DEFAULT ''; +ALTER TABLE Users MODIFY Username VARCHAR(32) NOT NULL, + MODIFY Email VARCHAR(64) NOT NULL, + MODIFY RealName VARCHAR(64) NOT NULL DEFAULT '', + MODIFY LangPreference VARCHAR(5) NOT NULL DEFAULT 'en', + MODIFY IRCNick VARCHAR(32) NOT NULL DEFAULT ''; +ALTER TABLE PackageCategories MODIFY Category VARCHAR(32) NOT NULL; +ALTER TABLE Packages MODIFY Name VARCHAR(64) NOT NULL, + MODIFY Version VARCHAR(32) NOT NULL DEFAULT '', + MODIFY Description VARCHAR(255) NOT NULL DEFAULT "An Arch Package", + MODIFY URL VARCHAR(255) NOT NULL DEFAULT "https://www.archlinux.org", + MODIFY License VARCHAR(40) NOT NULL DEFAULT ''; +ALTER TABLE PackageSources + MODIFY Source VARCHAR(255) NOT NULL DEFAULT "/dev/null"; +ALTER TABLE TU_VoteInfo + MODIFY User VARCHAR(32) collate latin1_general_ci NOT NULL; +CREATE TABLE PackageBlacklist ( + ID INTEGER UNSIGNED NOT NULL AUTO_INCREMENT, + Name VARCHAR(64) NOT NULL, + PRIMARY KEY (ID), + UNIQUE (Name) +); +---- + +2. Drop all fulltext indexes from the "Packages" table: + +Please do this with care. `ALTER TABLE Packages DROP INDEX Name;` will work in +most cases but might remove the wrong index if your indexes have been created +in a non-standard order (e.g. during some update process). You'd better run +`SHOW INDEX FROM Packages;` before to ensure that your setup doesn't use a +different naming. + +3. You will need to update all packages which are stored in the incoming dir as +in 1.8.0, source tarballs are no longer extracted automatically and PKGBUILDs +are from now on located in the same subdirectories as the tarballs themselves. +The following script will do the conversion automatically when being run inside +"$INCOMING_DIR": + +---- +#!/bin/bash + +for pkg in *; do + if [ -d "${pkg}" -a ! -f "${pkg}/PKGBUILD" ]; then + pkgbuild_file=$(find -P "${pkg}" -name PKGBUILD) + [ -n "${pkgbuild_file}" ] && \ + cp "${pkgbuild_file}" "${pkg}/PKGBUILD" + fi +done +---- + +4. (optional): 1.8.0 includes a helper utility called "aurblup" that can be +used to prevent users from uploading source packages with names identical to +packages in predefined binary repos, e.g. the official repositories of your +distribution. In order to build and install aurblup, enter the following +commands: + + cd scripts/aurblup/ + make config.h + $EDITOR config.h + make install # as root + +Add something like "0 * * * * /usr/local/bin/aurblup" to root's crontab to make +aurblup update the package blacklist every hour. + +NOTE: You can run aurblup as non-privileged user as well. Make sure that the +user has read-write access to "/var/lib/aurblup/" (or whatever you defined with +"ALPM_DBPATH") tho. + +5. (optional): As of 1.8.0, all MySQL tables should be InnoDB compatible. To +convert a table, you can use this statement: `ALTER TABLE $foo ENGINE=InnoDB;`. +If you want to stick with MyISAM or another storage engine that doesn't support +transactions, you will need to disable the "MYSQL_USE_TRANSACTIONS" setting in +"config.h" when setting up aurblup. diff --git a/upgrading/1.8.1.txt b/upgrading/1.8.1.txt new file mode 100644 index 0000000..48c2119 --- /dev/null +++ b/upgrading/1.8.1.txt @@ -0,0 +1,56 @@ +1. Drop foreign keys from the "Sessions" table: + +`ALTER TABLE Sessions DROP FOREIGN KEY Sessions_ibfk_1;` should work in most +cases. Otherwise, check the output of `SHOW CREATE TABLE Sessions;` and use the +foreign key name shown there. + +2. Run the following MySQL statements: + +---- +ALTER TABLE Sessions + ADD FOREIGN KEY (UsersID) REFERENCES Users(ID) ON DELETE CASCADE; +ALTER TABLE PackageDepends + ADD FOREIGN KEY (PackageID) REFERENCES Packages(ID) ON DELETE CASCADE, + ADD FOREIGN KEY (DepPkgID) REFERENCES Packages(ID) ON DELETE CASCADE; +ALTER TABLE PackageSources + ADD FOREIGN KEY (PackageID) REFERENCES Packages(ID) ON DELETE CASCADE; +ALTER TABLE TU_VoteInfo + ADD FOREIGN KEY (SubmitterID) REFERENCES Users(ID) ON DELETE CASCADE; +ALTER TABLE TU_Votes + ADD FOREIGN KEY (VoteID) REFERENCES TU_VoteInfo(ID) ON DELETE CASCADE, + ADD FOREIGN KEY (UserID) REFERENCES Users(ID) ON DELETE CASCADE; +ALTER TABLE PackageComments + MODIFY DelUsersID INTEGER UNSIGNED NULL DEFAULT NULL; +UPDATE PackageComments SET DelUsersID = NULL WHERE DelUsersID = 0; +ALTER TABLE Packages + MODIFY SubmitterUID INTEGER UNSIGNED NULL DEFAULT NULL, + MODIFY MaintainerUID INTEGER UNSIGNED NULL DEFAULT NULL; +UPDATE Packages SET SubmitterUID = NULL WHERE SubmitterUID = 0; +UPDATE Packages SET MaintainerUID = NULL WHERE MaintainerUID = 0; +---- + +3. (optional) If you converted your database from MyISAM to InnoDB during the +upgrade process from 1.7.0 to 1.8.0 or from 1.8.0 to 1.8.1 without completely +rebuilding the database from the MySQL schema, you should additionally run the +following MySQL statements to add missing foreign keys: + +---- +ALTER TABLE Users + ADD FOREIGN KEY (AccountTypeID) REFERENCES AccountTypes(ID) ON DELETE NO ACTION; +ALTER TABLE Packages + ADD FOREIGN KEY (CategoryID) REFERENCES PackageCategories(ID) ON DELETE NO ACTION, + ADD FOREIGN KEY (SubmitterUID) REFERENCES Users(ID) ON DELETE NO ACTION, + ADD FOREIGN KEY (MaintainerUID) REFERENCES Users(ID) ON DELETE NO ACTION; +ALTER TABLE PackageVotes + ADD FOREIGN KEY (UsersID) REFERENCES Users(ID) ON DELETE CASCADE, + ADD FOREIGN KEY (PackageID) REFERENCES Packages(ID) ON DELETE CASCADE; +ALTER TABLE PackageComments + ADD FOREIGN KEY (UsersID) REFERENCES Users(ID) ON DELETE CASCADE, + ADD FOREIGN KEY (DelUsersID) REFERENCES Users(ID) ON DELETE CASCADE, + ADD FOREIGN KEY (PackageID) REFERENCES Packages(ID) ON DELETE CASCADE; +ALTER TABLE CommentNotify + ADD FOREIGN KEY (PkgID) REFERENCES Packages(ID) ON DELETE CASCADE, + ADD FOREIGN KEY (UserID) REFERENCES Users(ID) ON DELETE CASCADE; +---- + +4. Merge "web/lib/config.inc.proto" with "web/lib/config.inc". diff --git a/upgrading/1.8.2.txt b/upgrading/1.8.2.txt new file mode 100644 index 0000000..ba3aebd --- /dev/null +++ b/upgrading/1.8.2.txt @@ -0,0 +1,18 @@ +1. Update the modified package timestamp for new packages. + +UPDATE Packages SET ModifiedTS = SubmittedTS WHERE ModifiedTS = 0; + +2. Move to new method of storing package depends. + +---- +ALTER TABLE PackageDepends ADD COLUMN DepName VARCHAR(64) NOT NULL DEFAULT '' AFTER PackageID; +UPDATE PackageDepends SET DepName = (SELECT Name FROM Packages WHERE ID = DepPkgID); +ALTER TABLE PackageDepends MODIFY DepName VARCHAR(64) NOT NULL; +ALTER TABLE PackageDepends DROP FOREIGN KEY `PackageDepends_ibfk_2`; +ALTER TABLE PackageDepends DROP COLUMN DepPkgID; +DELETE FROM Packages WHERE DummyPkg = 1; +ALTER TABLE Packages DROP COLUMN DummyPkg; +---- + +3. The File_Find PEAR module is no longer required. You can safely uninstall it +if nothing else depends on it. diff --git a/upgrading/1.9.0.txt b/upgrading/1.9.0.txt new file mode 100644 index 0000000..45ac0eb --- /dev/null +++ b/upgrading/1.9.0.txt @@ -0,0 +1,36 @@ +1. Translation files are now gettext compatible and need to be compiled after +each AUR upgrade by running `make install` in the "po/" directory. + +2. Remove the "NewPkgNotify" column from the "Users" table: + +ALTER TABLE Users DROP COLUMN NewPkgNotify; + +3. Fix up issues with depends performance on large dataset. + +ALTER TABLE PackageDepends ADD INDEX (DepName); + +4. Rename "web/lib/config.inc" to "web/lib/config.inc.php". + +5. Merge "web/lib/config.inc.php.proto" with "web/lib/config.inc.php". + +6. Run the upload directory transform script ("scripts/uploadbuckets.sh") and +rotate the converted directory structure into place. + +7. In order to to provide backward compatible package URLs, enable mod_rewrite +and add the following to your Apache configuration (inside the "VirtualHost" +container or optionally create a ".htaccess" file in the upload directory): + +---- +RewriteEngine on +RewriteRule ^/packages/([^/]{1,2})([^/]*/(PKGBUILD|[^/]*\.tar\.gz|))$ /packages/$1/$1$2 +---- + +The following equivalent rule can be used for lighttpd setups: + +---- +url.rewrite-once = ( "^/packages/([^/]{1,2})([^/]*/(PKGBUILD|[^/]*\.tar\.gz|))$" => "/packages/$1/$1$2" ) +---- + +If you use a non-standard URL_DIR, slight modifications might be necessary. + +8. Merge "scripts/aurblup/config.h.proto" with "scripts/aurblup/config.h". diff --git a/upgrading/1.9.1.txt b/upgrading/1.9.1.txt new file mode 100644 index 0000000..ca80a47 --- /dev/null +++ b/upgrading/1.9.1.txt @@ -0,0 +1,3 @@ +1. Merge "web/lib/config.inc.php.proto" with "web/lib/config.inc.php". + +2. Install translations by running `make install` in "po/". diff --git a/upgrading/2.0.0.txt b/upgrading/2.0.0.txt new file mode 100644 index 0000000..807f5b3 --- /dev/null +++ b/upgrading/2.0.0.txt @@ -0,0 +1,14 @@ +1. Add new "Users" table login date and PGP key columns: + +---- +ALTER TABLE Users ADD COLUMN LastLogin BIGINT NOT NULL DEFAULT 0; +ALTER TABLE Users ADD COLUMN PGPKey VARCHAR(40) NULL DEFAULT NULL; +---- + +2. Merge "web/lib/config.inc.php.proto" with "web/lib/config.inc.php". + +3. Enable the PDO MySQL extension (pdo_mysql.so) in "php.ini". + +4. Upgrade to PHP>=5.4.0 or enable "short_open_tag" in "php.ini". + +5. Install translations by running `make install` in "po/". diff --git a/upgrading/2.1.0.txt b/upgrading/2.1.0.txt new file mode 100644 index 0000000..5df5b88 --- /dev/null +++ b/upgrading/2.1.0.txt @@ -0,0 +1,2 @@ +1. Update your aurblup setup to match configuration changes. See commit +6dc61e7d9e87ad6821869dab61e5f005af2e0252 for details. diff --git a/upgrading/2.2.0.txt b/upgrading/2.2.0.txt new file mode 100644 index 0000000..1cdf2b0 --- /dev/null +++ b/upgrading/2.2.0.txt @@ -0,0 +1,16 @@ +1. Add new "Users" table login IP address column: + +---- +ALTER TABLE Users + ADD COLUMN LastLoginIPAddress INTEGER UNSIGNED NOT NULL DEFAULT 0; +---- + +2. Add a new "Bans" table: + +---- +CREATE TABLE Bans ( + IPAddress INTEGER UNSIGNED NOT NULL DEFAULT 0, + BanTS TIMESTAMP NOT NULL, + PRIMARY KEY (IPAddress) +) ENGINE = InnoDB; +---- diff --git a/upgrading/2.3.0.txt b/upgrading/2.3.0.txt new file mode 100644 index 0000000..d390d1c --- /dev/null +++ b/upgrading/2.3.0.txt @@ -0,0 +1,22 @@ +1. Add registration and inactivity time stamps to the "Users" table: + +---- +ALTER TABLE Users + ADD COLUMN RegistrationTS TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, + ADD COLUMN InactivityTS BIGINT NOT NULL DEFAULT 0; +---- + +2. Add fields to store the total number of TUs and the quorum to the + "TU_VoteInfo" table: + +---- +ALTER TABLE TU_VoteInfo + ADD COLUMN ActiveTUs tinyint(3) unsigned NOT NULL default '0', + ADD COLUMN Quorum decimal(2, 2) unsigned NOT NULL; +---- + +3. Add a "fonts" category: + +---- +INSERT INTO PackageCategories (Category) VALUES ('fonts'); +---- diff --git a/upgrading/3.0.0.txt b/upgrading/3.0.0.txt new file mode 100644 index 0000000..b134b79 --- /dev/null +++ b/upgrading/3.0.0.txt @@ -0,0 +1,249 @@ +1. Drop the user ID foreign key from the "PackageComments" table: + +`ALTER TABLE PackageComments DROP FOREIGN KEY PackageComments_ibfk_1;` should +work in most cases. Otherwise, check the output of `SHOW CREATE TABLE +PackageComments;` and use the foreign key name shown there. + +2. Add support for anonymous comments: + +---- +ALTER TABLE PackageComments + MODIFY UsersID INTEGER UNSIGNED NULL DEFAULT NULL, + ADD FOREIGN KEY (UsersID) REFERENCES Users(ID) ON DELETE SET NULL; +---- + +3. Create the PackageBases table: + +---- +CREATE TABLE PackageBases ( + ID INTEGER UNSIGNED NOT NULL AUTO_INCREMENT, + Name VARCHAR(64) NOT NULL, + CategoryID TINYINT UNSIGNED NOT NULL DEFAULT 1, + NumVotes INTEGER UNSIGNED NOT NULL DEFAULT 0, + OutOfDateTS BIGINT UNSIGNED NULL DEFAULT NULL, + SubmittedTS BIGINT UNSIGNED NOT NULL, + ModifiedTS BIGINT UNSIGNED NOT NULL, + SubmitterUID INTEGER UNSIGNED NULL DEFAULT NULL, + MaintainerUID INTEGER UNSIGNED NULL DEFAULT NULL, + PackagerUID INTEGER UNSIGNED NULL DEFAULT NULL, + PRIMARY KEY (ID), + UNIQUE (Name), + INDEX (CategoryID), + INDEX (NumVotes), + INDEX (SubmitterUID), + INDEX (MaintainerUID), + INDEX (PackagerUID), + FOREIGN KEY (CategoryID) REFERENCES PackageCategories(ID) ON DELETE NO ACTION, + -- deleting a user will cause packages to be orphaned, not deleted + FOREIGN KEY (SubmitterUID) REFERENCES Users(ID) ON DELETE SET NULL, + FOREIGN KEY (MaintainerUID) REFERENCES Users(ID) ON DELETE SET NULL, + FOREIGN KEY (PackagerUID) REFERENCES Users(ID) ON DELETE SET NULL +) ENGINE = InnoDB; +---- + +4. Migrate data from Packages to PackageBases: + +---- +INSERT INTO PackageBases + SELECT ID, Name, CategoryID, NumVotes, OutOfDateTS, SubmittedTS, + ModifiedTS, SubmitterUID, MaintainerUID, NULL FROM Packages; +---- + +5. Delete unneeded foreign keys from Packages: + +First, drop the foreign keys on CategoryID, SubmitterUID and MaintainerUID. The +following queries should work in most cases: + +---- +ALTER TABLE Packages + DROP FOREIGN KEY Packages_ibfk_1, + DROP FOREIGN KEY Packages_ibfk_2, + DROP FOREIGN KEY Packages_ibfk_3; +---- + +You can use `SHOW CREATE TABLE Packages;` to check whether you should use +different names for your setup. + +6. Delete unneeded fields from Packages: + +---- +ALTER TABLE Packages + DROP COLUMN CategoryID, + DROP COLUMN NumVotes, + DROP COLUMN OutOfDateTS, + DROP COLUMN SubmittedTS, + DROP COLUMN ModifiedTS, + DROP COLUMN SubmitterUID, + DROP COLUMN MaintainerUID; +---- + +7. Add package base references to the Packages table: + +---- +ALTER TABLE Packages ADD COLUMN PackageBaseID INTEGER UNSIGNED NULL; +UPDATE Packages SET PackageBaseID = ID; +ALTER TABLE Packages + MODIFY PackageBaseID INTEGER UNSIGNED NOT NULL, + ADD FOREIGN KEY (PackageBaseID) REFERENCES PackageBases(ID) ON DELETE CASCADE; +---- + +8. Delete foreign keys from PackageVotes, PackageComments and CommentNotify: + +---- +ALTER TABLE PackageVotes + DROP FOREIGN KEY PackageVotes_ibfk_1, + DROP FOREIGN KEY PackageVotes_ibfk_2; +ALTER TABLE PackageComments + DROP FOREIGN KEY PackageComments_ibfk_3; +ALTER TABLE CommentNotify + DROP FOREIGN KEY CommentNotify_ibfk_1, + DROP FOREIGN KEY CommentNotify_ibfk_2; +---- + +We highly recommend to use `SHOW CREATE TABLE PackageVotes;` etc. to check +whether you should use different names for your setup. + +9. Delete indexes from PackageVotes and CommentNotify: + +---- +ALTER TABLE PackageVotes DROP INDEX VoteUsersIDPackageID; +ALTER TABLE CommentNotify DROP INDEX NotifyUserIDPkgID; +---- + +10. Migrate PackageVotes, PackageComments and CommentNotify to refer to package +bases: + +---- +ALTER TABLE PackageVotes ADD COLUMN PackageBaseID INTEGER UNSIGNED NOT NULL; +UPDATE PackageVotes SET PackageBaseID = PackageID; +ALTER TABLE PackageVotes DROP COLUMN PackageID; +ALTER TABLE PackageComments ADD COLUMN PackageBaseID INTEGER UNSIGNED NOT NULL; +UPDATE PackageComments SET PackageBaseID = PackageID; +ALTER TABLE PackageComments DROP COLUMN PackageID; +ALTER TABLE CommentNotify ADD COLUMN PackageBaseID INTEGER UNSIGNED NOT NULL; +UPDATE CommentNotify SET PackageBaseID = PkgID; +ALTER TABLE CommentNotify DROP COLUMN PkgID; +---- + +11. Recreate missing foreign keys and indexes: + +---- +ALTER TABLE PackageVotes + ADD FOREIGN KEY (UsersID) REFERENCES Users(ID) ON DELETE CASCADE, + ADD FOREIGN KEY (PackageBaseID) REFERENCES PackageBases(ID) ON DELETE CASCADE; +ALTER TABLE PackageComments + ADD FOREIGN KEY (PackageBaseID) REFERENCES PackageBases(ID) ON DELETE CASCADE; +ALTER TABLE CommentNotify + ADD FOREIGN KEY (PackageBaseID) REFERENCES PackageBases(ID) ON DELETE CASCADE, + ADD FOREIGN KEY (UserID) REFERENCES Users(ID) ON DELETE CASCADE; +CREATE UNIQUE INDEX VoteUsersIDPackageID ON PackageVotes (UsersID, PackageBaseID); +CREATE UNIQUE INDEX NotifyUserIDPkgID ON CommentNotify (UserID, PackageBaseID); +---- + +12. Create a new table to store package dependency types: + +---- +CREATE TABLE DependencyTypes ( + ID TINYINT UNSIGNED NOT NULL AUTO_INCREMENT, + Name VARCHAR(32) NOT NULL DEFAULT '', + PRIMARY KEY (ID) +) ENGINE = InnoDB; +INSERT INTO DependencyTypes VALUES (1, 'depends'); +INSERT INTO DependencyTypes VALUES (2, 'makedepends'); +INSERT INTO DependencyTypes VALUES (3, 'checkdepends'); +INSERT INTO DependencyTypes VALUES (4, 'optdepends'); +---- + +13. Add a field to store the dependency type to the PackageDepends table: + +---- +ALTER TABLE PackageDepends ADD COLUMN DepTypeID TINYINT UNSIGNED NOT NULL; +UPDATE PackageDepends SET DepTypeID = 1; +ALTER TABLE PackageDepends + ADD FOREIGN KEY (DepTypeID) REFERENCES DependencyTypes(ID) ON DELETE NO ACTION; +---- + +14. Resize the package dependency name field: + +---- +ALTER TABLE PackageDepends MODIFY DepName VARCHAR(255) NOT NULL; +---- + +15. Create a new table to store package relation types: + +---- +CREATE TABLE RelationTypes ( + ID TINYINT UNSIGNED NOT NULL AUTO_INCREMENT, + Name VARCHAR(32) NOT NULL DEFAULT '', + PRIMARY KEY (ID) +) ENGINE = InnoDB; +INSERT INTO RelationTypes VALUES (1, 'conflicts'); +INSERT INTO RelationTypes VALUES (2, 'provides'); +INSERT INTO RelationTypes VALUES (3, 'replaces'); +---- + +16. Create a new table to store package relations: + +---- +CREATE TABLE PackageRelations ( + PackageID INTEGER UNSIGNED NOT NULL, + RelTypeID TINYINT UNSIGNED NOT NULL, + RelName VARCHAR(255) NOT NULL, + RelCondition VARCHAR(20), + INDEX (PackageID), + INDEX (RelName), + FOREIGN KEY (PackageID) REFERENCES Packages(ID) ON DELETE CASCADE, + FOREIGN KEY (RelTypeID) REFERENCES RelationTypes(ID) ON DELETE NO ACTION +) ENGINE = InnoDB; +---- + +17. Create tables to store package groups: + +---- +CREATE TABLE Groups ( + ID INTEGER UNSIGNED NOT NULL AUTO_INCREMENT, + Name VARCHAR(64) NOT NULL, + PRIMARY KEY (ID), + UNIQUE (Name) +) ENGINE = InnoDB; +CREATE TABLE PackageGroups ( + PackageID INTEGER UNSIGNED NOT NULL, + GroupID INTEGER UNSIGNED NOT NULL, + PRIMARY KEY (PackageID, GroupID), + FOREIGN KEY (PackageID) REFERENCES Packages(ID) ON DELETE CASCADE, + FOREIGN KEY (GroupID) REFERENCES Groups(ID) ON DELETE CASCADE +) ENGINE = InnoDB; +---- + +18. Create tables to store package licenses: + +---- +CREATE TABLE Licenses ( + ID INTEGER UNSIGNED NOT NULL AUTO_INCREMENT, + Name VARCHAR(64) NOT NULL, + PRIMARY KEY (ID), + UNIQUE (Name) +) ENGINE = InnoDB; +CREATE TABLE PackageLicenses ( + PackageID INTEGER UNSIGNED NOT NULL, + LicenseID INTEGER UNSIGNED NOT NULL, + PRIMARY KEY (PackageID, LicenseID), + FOREIGN KEY (PackageID) REFERENCES Packages(ID) ON DELETE CASCADE, + FOREIGN KEY (LicenseID) REFERENCES Licenses(ID) ON DELETE CASCADE +) ENGINE = InnoDB; +---- + +19. Convert existing licenses to the new storage format: + +---- +INSERT INTO Licenses (Name) SELECT DISTINCT License FROM Packages; +INSERT INTO PackageLicenses (PackageID, LicenseID) + SELECT Packages.ID, Licenses.ID FROM Packages + INNER JOIN Licenses ON Licenses.Name = Packages.License; +---- + +20. Delete the license column from the Packages table: + +---- +ALTER TABLE Packages DROP COLUMN License; +---- diff --git a/upgrading/3.1.0.txt b/upgrading/3.1.0.txt new file mode 100644 index 0000000..2fc1614 --- /dev/null +++ b/upgrading/3.1.0.txt @@ -0,0 +1,13 @@ +1. Increase the size of all fields containing package names, license names, +group names or package versions: + +---- +ALTER TABLE PackageBases MODIFY Name VARCHAR(255) NOT NULL; +ALTER TABLE Packages + MODIFY Name VARCHAR(255) NOT NULL, + MODIFY Version VARCHAR(255) NOT NULL DEFAULT ''; +ALTER TABLE Licenses MODIFY Name VARCHAR(255) NOT NULL; +ALTER TABLE Groups MODIFY Name VARCHAR(255) NOT NULL; +ALTER TABLE PackageDepends MODIFY DepCondition VARCHAR(255); +ALTER TABLE PackageRelations MODIFY RelCondition VARCHAR(255); +---- diff --git a/upgrading/3.2.0.txt b/upgrading/3.2.0.txt new file mode 100644 index 0000000..cde9367 --- /dev/null +++ b/upgrading/3.2.0.txt @@ -0,0 +1,30 @@ +1. Add support for package requests to the database: + +---- +CREATE TABLE RequestTypes ( + ID TINYINT UNSIGNED NOT NULL AUTO_INCREMENT, + Name VARCHAR(32) NOT NULL DEFAULT '', + PRIMARY KEY (ID) +) ENGINE = InnoDB; +INSERT INTO RequestTypes VALUES (1, 'deletion'); +INSERT INTO RequestTypes VALUES (2, 'orphan'); +INSERT INTO RequestTypes VALUES (3, 'merge'); + +CREATE TABLE PackageRequests ( + ID BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, + ReqTypeID TINYINT UNSIGNED NOT NULL, + PackageBaseID INTEGER UNSIGNED NULL, + PackageBaseName VARCHAR(255) NOT NULL, + MergeBaseName VARCHAR(255) NULL, + UsersID INTEGER UNSIGNED NULL DEFAULT NULL, + Comments TEXT NOT NULL DEFAULT '', + RequestTS BIGINT UNSIGNED NOT NULL DEFAULT 0, + Status TINYINT UNSIGNED NOT NULL DEFAULT 0, + PRIMARY KEY (ID), + INDEX (UsersID), + INDEX (PackageBaseID), + FOREIGN KEY (ReqTypeID) REFERENCES RequestTypes(ID) ON DELETE NO ACTION, + FOREIGN KEY (UsersID) REFERENCES Users(ID) ON DELETE SET NULL, + FOREIGN KEY (PackageBaseID) REFERENCES PackageBases(ID) ON DELETE SET NULL +) ENGINE = InnoDB; +---- diff --git a/upgrading/longerpkgname.txt b/upgrading/longerpkgname.txt new file mode 100644 index 0000000..a627496 --- /dev/null +++ b/upgrading/longerpkgname.txt @@ -0,0 +1 @@ +ALTER TABLE Packages MODIFY Name CHAR(64) NOT NULL; diff --git a/web/html/css/aur.css b/web/html/css/aur.css index 78fd4ce..cbebb30 100644 --- a/web/html/css/aur.css +++ b/web/html/css/aur.css @@ -24,20 +24,6 @@ padding: 0; } -#actionlist .text-button { - color: #07b; - background: none; - border: none; - padding: 0; - cursor: pointer; - font-size: 100%; -} - -#actionlist .text-button:hover { - text-decoration: underline; - color: #666; -} - .arch-bio-entry ul { list-style: none; padding: 0; @@ -61,3 +47,19 @@ #pkg-updates td.pkg-date { text-align:right; } + +.text-button { + background: transparent; + border: none !important; + margin: 0 !important; + padding: 0 !important; + font: normal 100% sans-serif; + text-decoration: none; + color: #07b; + cursor: pointer; +} + +.text-button:hover { + text-decoration: underline; + color: #666; +} diff --git a/web/html/index.php b/web/html/index.php index 921839a..40063f0 100644 --- a/web/html/index.php +++ b/web/html/index.php @@ -75,6 +75,9 @@ if (!empty($tokens[1]) && '/' . $tokens[1] == get_pkg_route()) { $_GET['N'] = $tokens[2]; include('voters.php'); return; + case "request": + include('pkgreq.php'); + return; default: header("HTTP/1.0 404 Not Found"); include "./404.php"; diff --git a/web/html/pkgbase.php b/web/html/pkgbase.php index 0d1b74a..0b0f6ef 100644 --- a/web/html/pkgbase.php +++ b/web/html/pkgbase.php @@ -59,23 +59,25 @@ if (check_token()) { } elseif (current_action("do_UnFlag")) { list($ret, $output) = pkgbase_unflag($atype, $ids); } elseif (current_action("do_Adopt")) { - list($ret, $output) = pkgbase_adopt($atype, $ids, true); + list($ret, $output) = pkgbase_adopt($atype, $ids, true, NULL); } elseif (current_action("do_Disown")) { - list($ret, $output) = pkgbase_adopt($atype, $ids, false); + $via = isset($_POST['via']) ? $_POST['via'] : NULL; + list($ret, $output) = pkgbase_adopt($atype, $ids, false, $via); } elseif (current_action("do_Vote")) { list($ret, $output) = pkgbase_vote($atype, $ids, true); } elseif (current_action("do_UnVote")) { list($ret, $output) = pkgbase_vote($atype, $ids, false); } elseif (current_action("do_Delete")) { if (isset($_POST['confirm_Delete'])) { + $via = isset($_POST['via']) ? $_POST['via'] : NULL; if (!isset($_POST['merge_Into']) || empty($_POST['merge_Into'])) { - list($ret, $output) = pkgbase_delete($atype, $ids, NULL); + list($ret, $output) = pkgbase_delete($atype, $ids, NULL, $via); unset($_GET['ID']); } else { $merge_base_id = pkgbase_from_name($_POST['merge_Into']); if ($merge_base_id) { - list($ret, $output) = pkgbase_delete($atype, $ids, $merge_base_id); + list($ret, $output) = pkgbase_delete($atype, $ids, $merge_base_id, $via); unset($_GET['ID']); } else { @@ -94,6 +96,10 @@ if (check_token()) { list($ret, $output) = pkgbase_delete_comment($atype); } elseif (current_action("do_ChangeCategory")) { list($ret, $output) = pkgbase_change_category($base_id, $atype); + } elseif (current_action("do_FileRequest")) { + list($ret, $output) = pkgbase_file_request($ids, $_POST['type'], $_POST['merge_into'], $_POST['comments']); + } elseif (current_action("do_CloseRequest")) { + list($ret, $output) = pkgbase_close_request($_POST['reqid']); } if (isset($_REQUEST['comment'])) { @@ -103,7 +109,11 @@ if (check_token()) { } if ($ret) { - if (isset($base_id)) { + if (current_action("do_CloseRequest")) { + /* Redirect back to package request page on success. */ + header('Location: ' . get_pkgreq_route()); + exit(); + } if (isset($base_id)) { /* Redirect back to package base page on success. */ header('Location: ' . get_pkgbase_uri($pkgbase_name)); exit(); diff --git a/web/html/pkgdel.php b/web/html/pkgdel.php index 39fe81a..621c3c9 100644 --- a/web/html/pkgdel.php +++ b/web/html/pkgdel.php @@ -37,6 +37,9 @@ if ($atype == "Trusted User" || $atype == "Developer"): ?> <input type="hidden" name="IDs[<?= $base_id ?>]" value="1" /> <input type="hidden" name="ID" value="<?= $base_id ?>" /> <input type="hidden" name="token" value="<?= htmlspecialchars($_COOKIE['AURSID']) ?>" /> + <?php if (isset($_GET['via'])): ?> + <input type="hidden" name="via" value="<?= intval($_GET['via']) ?>" /> + <?php endif; ?> <p><input type="checkbox" name="confirm_Delete" value="1" /> <?= __("Confirm package deletion") ?></p> <p><input type="submit" class="button" name="do_Delete" value="<?= __("Delete") ?>" /></p> diff --git a/web/html/pkgmerge.php b/web/html/pkgmerge.php index dbc5eac..ba3f742 100644 --- a/web/html/pkgmerge.php +++ b/web/html/pkgmerge.php @@ -39,8 +39,11 @@ if ($atype == "Trusted User" || $atype == "Developer"): ?> <input type="hidden" name="IDs[<?= $base_id ?>]" value="1" /> <input type="hidden" name="ID" value="<?= $base_id ?>" /> <input type="hidden" name="token" value="<?= htmlspecialchars($_COOKIE['AURSID']) ?>" /> + <?php if (isset($_GET['via'])): ?> + <input type="hidden" name="via" value="<?= intval($_GET['via']) ?>" /> + <?php endif; ?> <p><label for="merge_Into" ><?= __("Merge into:") ?></label> - <input type="text" id="merge_Into" name="merge_Into" /></p> + <input type="text" id="merge_Into" name="merge_Into" value="<?= isset($_GET['into']) ? $_GET['into'] : '' ?>" /></p> <p><input type="checkbox" name="confirm_Delete" value="1" /> <?= __("Confirm package merge") ?></p> <p><input type="submit" class="button" name="do_Delete" value="<?= __("Merge") ?>" /></p> diff --git a/web/html/pkgreq.php b/web/html/pkgreq.php new file mode 100644 index 0000000..5d708fc --- /dev/null +++ b/web/html/pkgreq.php @@ -0,0 +1,77 @@ +<?php + +set_include_path(get_include_path() . PATH_SEPARATOR . '../lib'); + +include_once("aur.inc.php"); +include_once("pkgfuncs.inc.php"); + +set_lang(); +check_sid(); + +html_header(__("File Request")); + +if (!isset($base_id)) { + if (!check_user_privileges()) { + header('Location: /'); + exit(); + } + + $results = pkgbase_request_list(); + $total = count($results); + + /* Sanitize paging variables. */ + if (isset($_GET['O'])) { + $_GET['O'] = intval($_GET['O']); + if ($_GET['O'] < 0) + $_GET['O'] = 0; + } else { + $_GET['O'] = 0; + } + + if (isset($_GET["PP"])) { + $_GET["PP"] = intval($_GET["PP"]); + if ($_GET["PP"] < 50) + $_GET["PP"] = 50; + else if ($_GET["PP"] > 250) + $_GET["PP"] = 250; + } else { + $_GET["PP"] = 50; + } + + /* Calculate the results to use. */ + $first = $_GET['O'] + 1; + + /* Calculation of pagination links. */ + $per_page = ($_GET['PP'] > 0) ? $_GET['PP'] : 50; + $current = ceil($first / $per_page); + $pages = ceil($total / $per_page); + $templ_pages = array(); + + if ($current > 1) { + $templ_pages['« ' . __('First')] = 0; + $templ_pages['‹ ' . __('Previous')] = ($current - 2) * $per_page; + } + + if ($current - 5 > 1) + $templ_pages["..."] = false; + + for ($i = max($current - 5, 1); $i <= min($pages, $current + 5); $i++) { + $templ_pages[$i] = ($i - 1) * $per_page; + } + + if ($current + 5 < $pages) + $templ_pages["... "] = false; + + if ($current < $pages) { + $templ_pages[__('Next') . ' ›'] = $current * $per_page; + $templ_pages[__('Last') . ' »'] = ($pages - 1) * $per_page; + } + + $SID = $_COOKIE['AURSID']; + include('pkgreq_results.php'); +} else { + include('pkgreq_form.php'); +} + +html_footer(AUR_VERSION); + diff --git a/web/lib/aurjson.class.php b/web/lib/aurjson.class.php index 9abb2d6..8187bef 100644 --- a/web/lib/aurjson.class.php +++ b/web/lib/aurjson.class.php @@ -61,7 +61,7 @@ class AurJSON { if (isset($http_data['v'])) { $this->version = intval($http_data['v']); } - if ($this->version < 1 || $this->version > 2) { + if ($this->version < 1 || $this->version > 3) { return $this->json_error('Invalid version specified.'); } @@ -109,7 +109,11 @@ class AurJSON { */ private function json_error($msg) { header('content-type: application/json'); - return $this->json_results('error', 0, $msg); + if ($this->version < 3) { + return $this->json_results('error', 0, $msg, NULL); + } elseif ($this->version >= 3) { + return $this->json_results('error', 0, array(), $msg); + } } /* @@ -117,16 +121,23 @@ class AurJSON { * * @param $type The response method type. * @param $data The result data to return + * @param $error An error message to include in the response * * @return mixed A json formatted result response. */ - private function json_results($type, $count, $data) { - return json_encode(array( + private function json_results($type, $count, $data, $error) { + $json_array = array( 'version' => $this->version, 'type' => $type, 'resultcount' => $count, 'results' => $data - )); + ); + + if ($error) { + $json_array['error'] = $error; + } + + return json_encode($json_array); } private function get_extended_fields($pkgid) { @@ -195,7 +206,7 @@ class AurJSON { "WHERE ${where_condition} " . "GROUP BY Packages.ID " . "LIMIT $MAX_RPC_RESULTS"; - } elseif ($this->version == 2) { + } elseif ($this->version >= 2) { $fields = implode(',', self::$fields_v2); $query = "SELECT {$fields} " . "FROM Packages LEFT JOIN PackageBases " . @@ -225,14 +236,18 @@ class AurJSON { $row[$field] = intval($row[$field]); } - if ($this->version == 2 && ($type == 'info' || $type == 'multiinfo')) { + if ($this->version >= 2 && ($type == 'info' || $type == 'multiinfo')) { $row = array_merge($row, $this->get_extended_fields($row['ID'])); } - if ($type == 'info') { - $search_data = $row; - break; - } else { + if ($this->version < 3) { + if ($type == 'info') { + $search_data = $row; + break; + } else { + array_push($search_data, $row); + } + } elseif ($this->version >= 3) { array_push($search_data, $row); } } @@ -241,9 +256,9 @@ class AurJSON { return $this->json_error('Too many package results.'); } - return $this->json_results($type, $resultcount, $search_data); + return $this->json_results($type, $resultcount, $search_data, NULL); } else { - return $this->json_results($type, 0, array()); + return $this->json_results($type, 0, array(), NULL); } } diff --git a/web/lib/config.inc.php.proto b/web/lib/config.inc.php.proto index 1fe7dbc..cb71fa5 100644 --- a/web/lib/config.inc.php.proto +++ b/web/lib/config.inc.php.proto @@ -59,3 +59,9 @@ $USE_VIRTUAL_URLS = true; # Maximum number of package results to return through an RPC connection. # Avoid setting this too high and having a PHP too much memory error. $MAX_RPC_RESULTS = 5000; + +# Mailing list to send package request notifications to. +$AUR_REQUEST_ML = "aur-requests@archlinux.org"; + +# Time to wait until a package request is due. +$REQUEST_IDLE_TIME = 60 * 60 * 24 * 14; diff --git a/web/lib/pkgbasefuncs.inc.php b/web/lib/pkgbasefuncs.inc.php index 9f80ef2..9f3439d 100644 --- a/web/lib/pkgbasefuncs.inc.php +++ b/web/lib/pkgbasefuncs.inc.php @@ -438,10 +438,11 @@ function pkgbase_unflag($atype, $base_ids) { * @param string $atype Account type, output of account_from_sid * @param array $base_ids Array of package base IDs to delete * @param int $merge_base_id Package base to merge the deleted ones into + * @param int $via Package request to close upon deletion * * @return array Tuple of success/failure indicator and error message */ -function pkgbase_delete ($atype, $base_ids, $merge_base_id) { +function pkgbase_delete ($atype, $base_ids, $merge_base_id, $via) { if (!$atype) { return array(false, __("You must be logged in before you can delete packages.")); } @@ -537,6 +538,10 @@ function pkgbase_delete ($atype, $base_ids, $merge_base_id) { $q = "DELETE FROM PackageBases WHERE ID IN (" . implode(",", $base_ids) . ")"; $dbh->exec($q); + if ($via) { + pkgbase_close_request(intval($via)); + } + return array(true, __("The selected packages have been deleted.")); } @@ -546,10 +551,11 @@ function pkgbase_delete ($atype, $base_ids, $merge_base_id) { * @param string $atype Account type, output of account_from_sid * @param array $base_ids Array of package base IDs to adopt/disown * @param bool $action Adopts if true, disowns if false. Adopts by default + * @param int $via Package request to close upon adoption * * @return array Tuple of success/failure indicator and error message */ -function pkgbase_adopt ($atype, $base_ids, $action=true) { +function pkgbase_adopt ($atype, $base_ids, $action=true, $via) { if (!$atype) { if ($action) { return array(false, __("You must be logged in before you can adopt packages.")); @@ -590,6 +596,10 @@ function pkgbase_adopt ($atype, $base_ids, $action=true) { $dbh->exec($q); + if ($via) { + pkgbase_close_request(intval($via)); + } + if ($action) { pkgbase_notify(account_from_sid($_COOKIE["AURSID"]), $base_ids); return array(true, __("The selected packages have been adopted.")); @@ -962,3 +972,188 @@ function pkgbase_update_category($base_id, $category_id) { $category_id, $base_id); $dbh->exec($q); } + +/** + * Get a list of all package requests + * + * @return array List of pacakge requests with details + */ +function pkgbase_request_list() { + $dbh = DB::connect(); + + $q = "SELECT PackageRequests.ID, "; + $q.= "PackageRequests.PackageBaseID AS BaseID, "; + $q.= "PackageRequests.PackageBaseName AS Name, "; + $q.= "PackageRequests.MergeBaseName AS MergeInto, "; + $q.= "RequestTypes.Name AS Type, PackageRequests.Comments, "; + $q.= "Users.Username AS User, PackageRequests.RequestTS, "; + $q.= "PackageRequests.Status "; + $q.= "FROM PackageRequests INNER JOIN RequestTypes ON "; + $q.= "RequestTypes.ID = PackageRequests.ReqTypeID "; + $q.= "INNER JOIN Users ON Users.ID = PackageRequests.UsersID "; + $q.= "ORDER BY Status ASC, RequestTS DESC"; + + return $dbh->query($q)->fetchAll(); +} + +/** + * File a deletion/orphan request against a package base + * + * @global string $AUR_LOCATION The AUR's URL used for notification e-mails + * @global string $AUR_REQUEST_ML The request notification mailing list + * @param string $ids The package base IDs to file the request against + * @param string $type The type of the request + * @param string $merge_into The target of a merge operation + * @param string $comments The comments to be added to the request + * + * @return void + */ +function pkgbase_file_request($ids, $type, $merge_into, $comments) { + global $AUR_LOCATION; + global $AUR_REQUEST_ML; + + if (empty($comments)) { + return array(false, __("The comment field must not be empty.")); + } + + $dbh = DB::connect(); + $uid = uid_from_sid($_COOKIE["AURSID"]); + + /* TODO: Allow for filing multiple requests at once. */ + $base_id = $ids[0]; + $pkgbase_name = pkgbase_name_from_id($base_id); + + $q = "SELECT ID FROM RequestTypes WHERE Name = " . $dbh->quote($type); + $result = $dbh->query($q); + if ($row = $result->fetch(PDO::FETCH_ASSOC)) { + $type_id = $row['ID']; + } else { + return array(false, __("Invalid request type.")); + } + + $q = "INSERT INTO PackageRequests "; + $q.= "(ReqTypeID, PackageBaseID, PackageBaseName, MergeBaseName, "; + $q.= "UsersID, Comments, RequestTS) VALUES (" . $type_id . ", "; + $q.= intval($base_id) . ", " . $dbh->quote($pkgbase_name) . ", "; + $q.= $dbh->quote($merge_into) . ", " . $uid . ", "; + $q.= $dbh->quote($comments) . ", UNIX_TIMESTAMP())"; + $dbh->exec($q); + $request_id = $dbh->lastInsertId(); + + /* + * Send e-mail notifications. + * TODO: Move notification logic to separate function where it belongs. + */ + $q = "SELECT Users.Email "; + $q.= "FROM Users INNER JOIN PackageBases "; + $q.= "ON PackageBases.MaintainerUID = Users.ID "; + $q.= "WHERE PackageBases.ID = " . intval($base_id); + $result = $dbh->query($q); + if ($row = $result->fetch(PDO::FETCH_ASSOC)) { + $bcc = $row['Email']; + } else { + unset($bcc); + } + + $q = "SELECT Name FROM PackageBases WHERE ID = "; + $q.= intval($base_id); + $result = $dbh->query($q); + $row = $result->fetch(PDO::FETCH_ASSOC); + + /* + * TODO: Add native language emails for users, based on their + * preferences. Simply making these strings translatable won't + * work, users would be getting emails in the language that the + * user who posted the comment was in. + */ + $username = username_from_sid($_COOKIE['AURSID']); + $body = + $username . " [1] filed a " . $type . " request for " . + $row['Name'] . " [2]:\n\n" . $comments . "\n\n" . + "[1] " . $AUR_LOCATION . get_user_uri($username) . "\n" . + "[2] " . $AUR_LOCATION . get_pkgbase_uri($row['Name']) . "\n"; + $body = wordwrap($body, 70); + $headers = "MIME-Version: 1.0\r\n" . + "Content-type: text/plain; charset=UTF-8\r\n"; + if (!empty($bcc)) { + $headers .= "Bcc: $bcc\r\n"; + } + $thread_id = "<pkg-request-" . $request_id . "@aur.archlinux.org>"; + $headers .= "Reply-to: noreply@aur.archlinux.org\r\n" . + "From: notify@aur.archlinux.org\r\n" . + "In-Reply-To: $thread_id\r\n" . + "References: $thread_id\r\n" . + "X-Mailer: AUR"; + @mail($AUR_REQUEST_ML, "[PRQ#" . $request_id . "] " . ucfirst($type) . + " Request for " . $row['Name'], $body, + $headers); + + return array(true, __("Added request successfully.")); +} + +/** + * Close a deletion/orphan request + * + * @global string $AUR_LOCATION The AUR's URL used for notification e-mails + * @global string $AUR_REQUEST_ML The request notification mailing list + * @param int $id The package request to close + * + * @return void + */ +function pkgbase_close_request($id) { + global $AUR_LOCATION; + global $AUR_REQUEST_ML; + + $dbh = DB::connect(); + $id = intval($id); + + if (!check_user_privileges()) { + return array(false, __("Only TUs and developers can close requests.")); + } + + $q = "UPDATE PackageRequests SET Status = 1 WHERE ID = " . intval($id); + $dbh->exec($q); + + /* + * Send e-mail notifications. + * TODO: Move notification logic to separate function where it belongs. + */ + $q = "SELECT Users.Email "; + $q.= "FROM Users INNER JOIN PackageBases "; + $q.= "ON PackageBases.MaintainerUID = Users.ID "; + $q.= "INNER JOIN PackageRequests "; + $q.= "ON PackageRequests.PackageBaseID = PackageBases.ID "; + $q.= "WHERE PackageRequests.ID = " . $id; + $result = $dbh->query($q); + if ($row = $result->fetch(PDO::FETCH_ASSOC)) { + $bcc = $row['Email']; + } else { + unset($bcc); + } + + /* + * TODO: Add native language emails for users, based on their + * preferences. Simply making these strings translatable won't + * work, users would be getting emails in the language that the + * user who posted the comment was in. + */ + $username = username_from_sid($_COOKIE['AURSID']); + $body = $username . " [1] closed request #" . intval($id) . ".\n\n" . + "[1] " . $AUR_LOCATION . get_user_uri($username) . "\n"; + $body = wordwrap($body, 70); + $headers = "MIME-Version: 1.0\r\n" . + "Content-type: text/plain; charset=UTF-8\r\n"; + if (!empty($bcc)) { + $headers .= "Bcc: $bcc\r\n"; + } + $thread_id = "<pkg-request-" . $id . "@aur.archlinux.org>"; + $headers .= "Reply-to: noreply@aur.archlinux.org\r\n" . + "From: notify@aur.archlinux.org\r\n" . + "In-Reply-To: $thread_id\r\n" . + "References: $thread_id\r\n" . + "X-Mailer: AUR"; + @mail($AUR_REQUEST_ML, "[PRQ#" . $id . "] Request Closed", $body, + $headers); + + return array(true, __("Request closed successfully.")); +} diff --git a/web/lib/routing.inc.php b/web/lib/routing.inc.php index 1b2aa52..2fa3e1f 100644 --- a/web/lib/routing.inc.php +++ b/web/lib/routing.inc.php @@ -5,6 +5,7 @@ $ROUTES = array( '/index.php' => 'home.php', '/packages' => 'packages.php', '/pkgbase' => 'pkgbase.php', + '/requests' => 'pkgreq.php', '/register' => 'account.php', '/account' => 'account.php', '/accounts' => 'account.php', @@ -20,6 +21,7 @@ $ROUTES = array( $PKG_PATH = '/packages'; $PKGBASE_PATH = '/pkgbase'; +$PKGREQ_PATH = '/requests'; $USER_PATH = '/account'; function get_route($path) { @@ -54,6 +56,11 @@ function get_pkgbase_route() { return $PKGBASE_PATH; } +function get_pkgreq_route() { + global $PKGREQ_PATH; + return $PKGREQ_PATH; +} + function get_pkg_uri($pkgname) { global $USE_VIRTUAL_URLS; global $PKG_PATH; diff --git a/web/template/header.php b/web/template/header.php index df83995..03ce536 100644 --- a/web/template/header.php +++ b/web/template/header.php @@ -57,6 +57,9 @@ <li><a href="<?= get_uri('/packages/'); ?>"><?= __("Packages"); ?></a></li> <?php if (isset($_COOKIE['AURSID'])): ?> <li><a href="<?= get_uri('/packages/'); ?>?SeB=m&K=<?= username_from_sid($_COOKIE["AURSID"]); ?>"><?= __("My Packages"); ?></a></li> + <?php if (check_user_privileges()): ?> + <li><a href="<?= get_uri('/requests/') ; ?>"><?= __("Requests"); ?></a></li> + <?php endif; ?> <li><a href="<?= get_uri('/submit/'); ?>"><?= __("Submit"); ?></a></li> <?php if (check_user_privileges()): ?> <li><a href="<?= get_uri('/accounts/') ; ?>"><?= __("Accounts"); ?></a></li> diff --git a/web/template/pkg_details.php b/web/template/pkg_details.php index 6326d4e..065057a 100644 --- a/web/template/pkg_details.php +++ b/web/template/pkg_details.php @@ -106,6 +106,7 @@ $sources = pkg_sources($row["ID"]); </form> </li> <?php endif; ?> + <li><a href="<?= get_pkgbase_uri($row['BaseName']) . 'request/'; ?>"><?= __('File Request'); ?></a></li> <?php if ($atype == "Trusted User" || $atype == "Developer"): ?> <li><a href="<?= get_pkgbase_uri($row['BaseName']) . 'delete/'; ?>"><?= __('Delete Package'); ?></a></li> <li><a href="<?= get_pkgbase_uri($row['BaseName']) . 'merge/'; ?>"><?= __('Merge Package'); ?></a></li> diff --git a/web/template/pkgbase_details.php b/web/template/pkgbase_details.php index 6c617bf..1b40b84 100644 --- a/web/template/pkgbase_details.php +++ b/web/template/pkgbase_details.php @@ -81,6 +81,7 @@ $pkgs = pkgbase_get_pkgnames($base_id); </form> </li> <?php endif; ?> + <li><a href="<?= get_pkgbase_uri($row['BaseName']) . 'request/'; ?>"><?= __('File Request'); ?></a></li> <?php if ($atype == "Trusted User" || $atype == "Developer"): ?> <li><a href="<?= get_pkgbase_uri($row['Name']) . 'delete/'; ?>"><?= __('Delete Package'); ?></a></li> <li><a href="<?= get_pkgbase_uri($row['Name']) . 'merge/'; ?>"><?= __('Merge Package'); ?></a></li> diff --git a/web/template/pkgreq_form.php b/web/template/pkgreq_form.php new file mode 100644 index 0000000..cc45f29 --- /dev/null +++ b/web/template/pkgreq_form.php @@ -0,0 +1,52 @@ +<div class="box"> + <h2><?= __('File Request: %s', htmlspecialchars($pkgbase_name)) ?></h2> + <p> + <?= __('Use this form to file a request against package base %s%s%s which includes the following packages:', + '<strong>', htmlspecialchars($pkgbase_name), '</strong>'); ?> + </p> + <ul> + <?php foreach(pkgbase_get_pkgnames($base_id) as $pkgname): ?> + <li><?= htmlspecialchars($pkgname) ?></li> + <?php endforeach; ?> + </ul> + <form action="<?= get_uri('/pkgbase/'); ?>" method="post"> + <fieldset> + <input type="hidden" name="IDs[<?= $base_id ?>]" value="1" /> + <input type="hidden" name="ID" value="<?= $base_id ?>" /> + <input type="hidden" name="token" value="<?= htmlspecialchars($_COOKIE['AURSID']) ?>" /> + <p> + <label for="id_type"><?= __("Request type") ?>:</label> + <select name="type" id="id_type" onchange="showHideMergeSection()"> + <option value="deletion"><?= __('Deletion') ?></option> + <option value="merge"><?= __('Merge') ?></option> + <option value="orphan"><?= __('Orphan') ?></option> + </select> + </p> + <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script> + <script type="text/javascript"> + function showHideMergeSection() { + if ($('#id_type').val() == 'merge') { + $('#merge_section').show(); + } else { + $('#merge_section').hide(); + } + } + + $(document).ready(function() { + showHideMergeSection(); + }); + </script> + <p id="merge_section"> + <label for="id_merge_into"><?= __("Merge into") ?>:</label> + <input type="text" name="merge_into" id="id_merge_into" /> + </p> + <p> + <label for="id_comments"><?= __("Comments") ?>:</label> + <textarea name="comments" id="id_comments" rows="5" cols="50"></textarea> + </p> + <p> + <input type="submit" class="button" name="do_FileRequest" value="<?= __("File Request") ?>" /> + </p> + </fieldset> + </form> +</div> diff --git a/web/template/pkgreq_results.php b/web/template/pkgreq_results.php new file mode 100644 index 0000000..7933964 --- /dev/null +++ b/web/template/pkgreq_results.php @@ -0,0 +1,101 @@ +<div id="pkglist-results" class="box"> + <div class="pkglist-stats"> + <p><?= __('%d package requests found. Page %d of %d.', $total, $current, $pages) ?></p> + <?php if (count($templ_pages) > 1): ?> + <p class="pkglist-nav"> + <?php foreach ($templ_pages as $pagenr => $pagestart): ?> + <?php if ($pagestart === false): ?> + <span class="page"><?= $pagenr ?></span> + <?php elseif ($pagestart + 1 == $first): ?> + <span class="page"><?= $pagenr ?></span> + <?php else: ?> + <a class="page" href="<?= get_uri('/requests/'); ?>?<?= mkurl('O=' . $pagestart) ?>"><?= $pagenr ?></a> + <?php endif; ?> + <?php endforeach; ?> + </p> + <?php endif; ?> + </div> + + <table class="results"> + <thead> + <tr> + <th><?= __("Package") ?></th> + <th><?= __("Type") ?></th> + <th><?= __("Comments") ?></th> + <th><?= __("Filed by") ?></th> + <th><?= __("Date") ?></th> + <th><?= __("Status") ?></th> + </tr> + </thead> + <tbody> + + <?php while (list($indx, $row) = each($results)): ?> + <tr class="<?= ($indx % 2 == 0) ? 'odd' : 'even' ?>"> + <?php if ($row['BaseID']): ?> + <td><a href="<?= htmlspecialchars(get_pkgbase_uri($row["Name"]), ENT_QUOTES); ?>"><?= htmlspecialchars($row["Name"]) ?></a></td> + <?php else: ?> + <td><?= htmlspecialchars($row["Name"]) ?></td> + <?php endif; ?> + <?php if ($row['Type'] == 'merge'): ?> + <td><?= htmlspecialchars(ucfirst($row['Type']), ENT_QUOTES); ?> (<?= htmlspecialchars(ucfirst($row['MergeInto']), ENT_QUOTES); ?>)</td> + <?php else: ?> + <td><?= htmlspecialchars(ucfirst($row['Type']), ENT_QUOTES); ?></td> + <?php endif; ?> + <td class="wrap"><?= htmlspecialchars($row['Comments'], ENT_QUOTES); ?></td> + <td> + <a href="<?= get_uri('/account/') . htmlspecialchars($row['User'], ENT_QUOTES) ?>" title="<?= __('View account information for %s', htmlspecialchars($row['User'])) ?>"><?= htmlspecialchars($row['User']) ?></a> + </td> + <td<?php if ($row['Status'] == 0 && time() - intval($row['RequestTS']) > $REQUEST_IDLE_TIME): ?> class="flagged"<?php endif; ?>><?= gmdate("Y-m-d H:i", intval($row['RequestTS'])) ?></td> + <?php if ($row['Status'] == 0): ?> + <td> + <?php if ($row['BaseID']): ?> + <?php if ($row['Type'] == 'deletion'): ?> + <a href="<?= get_pkgbase_uri($row['Name']) ?>delete/?via=<?= intval($row['ID']) ?>"><?= __('Accept') ?></a> + <?php elseif ($row['Type'] == 'merge'): ?> + <a href="<?= get_pkgbase_uri($row['Name']) ?>merge/?into=<?= urlencode($row['MergeInto']) ?>&via=<?= intval($row['ID']) ?>"><?= __('Accept') ?></a> + <?php elseif ($row['Type'] == 'orphan'): ?> + <form action="<?= get_pkgbase_uri($row['Name']) . 'disown/'; ?>" method="post"> + <input type="hidden" name="token" value="<?= htmlspecialchars($_COOKIE['AURSID']) ?>" /> + <input type="hidden" name="via" value="<?= intval($row['ID']) ?>" /> + <input type="submit" class="button text-button" name="do_Disown" value="<?= __('Accept') ?>" /> + </form> + <?php endif; ?> + <?php endif; ?> + <form action="<?= get_uri('/pkgbase/'); ?>" method="post"> + <fieldset> + <input type="hidden" name="IDs[<?= $row['BaseID'] ?>]" value="1" /> + <input type="hidden" name="ID" value="<?= $row['BaseID'] ?>" /> + <input type="hidden" name="token" value="<?= htmlspecialchars($_COOKIE['AURSID']) ?>" /> + <input type="hidden" name="reqid" value="<?= $row['ID'] ?>" /> + <div> + <input type="submit" class="button text-button" name="do_CloseRequest" value="<?= __("Close") ?>" /> + </div> + </fieldset> + </form> + </td> + <?php else: ?> + <td><?= __("Closed") ?></td> + <?php endif; ?> + </tr> + <?php endwhile; ?> + + </tbody> + </table> + + <div class="pkglist-stats"> + <p><?= __('%d package requests found. Page %d of %d.', $total, $current, $pages) ?></p> + <?php if (count($templ_pages) > 1): ?> + <p class="pkglist-nav"> + <?php foreach ($templ_pages as $pagenr => $pagestart): ?> + <?php if ($pagestart === false): ?> + <span class="page"><?= $pagenr ?></span> + <?php elseif ($pagestart + 1 == $first): ?> + <span class="page"><?= $pagenr ?></span> + <?php else: ?> + <a class="page" href="<?= get_uri('/requests/'); ?>?<?= mkurl('O=' . $pagestart) ?>"><?= $pagenr ?></a> + <?php endif; ?> + <?php endforeach; ?> + </p> + <?php endif; ?> + </div> +</div> |