Compare commits
72 Commits
feature-is
...
feature.is
Author | SHA1 | Date | |
---|---|---|---|
|
bbc185bf3b | ||
|
6d55602ef3 | ||
|
6e7c9f7c4b | ||
|
5427aab456 | ||
|
dab8ea63fc | ||
|
b03d7a04a0 | ||
|
ef5b93e3f7 | ||
|
69ae1c08ef | ||
|
8e4f828cc6 | ||
|
c4f92f4569 | ||
|
c4d2b99656 | ||
|
d4fe88adab | ||
|
69d0e8313a | ||
|
11a234e135 | ||
|
2f30e4e2f6 | ||
|
118ca9f11f | ||
|
24fc41ee0d | ||
|
c00dbac5e0 | ||
|
d7857c5126 | ||
|
ac6be0d3c0 | ||
|
7ff6f09f67 | ||
|
00b576c5a3 | ||
|
2a33510c96 | ||
|
d1f79d906d | ||
|
aa043f14ac | ||
|
638b28399e | ||
|
1d86f036a3 | ||
|
2f6e0f0a22 | ||
|
1b1b00a10c | ||
|
8693418d39 | ||
|
8ff15368ce | ||
|
32cde534bd | ||
|
c0e26133bd | ||
|
592c2ff9ff | ||
|
30efd0a2db | ||
|
20c3f14cc8 | ||
|
80313c88c8 | ||
|
cab1c09ffc | ||
|
c421919092 | ||
|
d350876bc1 | ||
|
de09c8af56 | ||
|
998f4576fe | ||
|
06c57f7da6 | ||
|
4d5418a601 | ||
|
95cc7f627f | ||
|
2aab4eea3b | ||
|
5bbff9f5a6 | ||
|
b5fcf1636a | ||
|
13012be5d7 | ||
|
ca2ef814fb | ||
|
b9407f6aee | ||
|
9bcb5f9456 | ||
|
f412099f69 | ||
|
0aa5999bb3 | ||
|
16dda0743c | ||
|
d079838818 | ||
|
81ce4688df | ||
|
ee33cc1832 | ||
|
82bb18fe10 | ||
|
8987ca7db6 | ||
|
8066fd8982 | ||
|
a96d8c05a7 | ||
|
4238a5dd50 | ||
|
94da55d15e | ||
|
09979b8551 | ||
|
5b82efa0be | ||
|
8502a36481 | ||
|
bcba64b2a1 | ||
|
e40d922eef | ||
|
7e226b43d3 | ||
|
bbf1a1882a | ||
|
5322cdf609 |
1
AUTHORS
1
AUTHORS
@@ -12,6 +12,7 @@ Much appreciated contributors (in alphabetical order):
|
||||
Brian Armstrong <brianar>
|
||||
Charles Melbye <charlie@yourwiki.net>
|
||||
Ciaran Gultnieks <ciaran@ciarang.com>
|
||||
Daniel Steudler <steudlerdaniel@gmail.com>
|
||||
David Feeney <davidf>
|
||||
Denis Kot <denis.kot@gmail.com> - Russian translation
|
||||
Dmitry Dulepov <dmitryd>
|
||||
|
9
Makefile
9
Makefile
@@ -37,6 +37,10 @@ help:
|
||||
@printf "\tpo-push - Send the all PO files to the transifex server.\n"
|
||||
@printf "\tpo-pull - Get all PO files from the transifex server.\n"
|
||||
@printf "\tpo-stats - Show translation statistics of all PO files.\n"
|
||||
@printf "\nMisc Rules :\n";
|
||||
@printf "\tdb-install - Install the database schema.\n"
|
||||
@printf "\tdb-update - Update the database schema.\n"
|
||||
|
||||
|
||||
#
|
||||
# Internationalization rule, POT & PO file manipulation
|
||||
@@ -139,3 +143,8 @@ po-stats:
|
||||
> indefero-$(@:-zipfile=)-`git log $(@:-zipfile=) -n 1 \
|
||||
--pretty=format:%h`.zip
|
||||
|
||||
db-install:
|
||||
@cd src && php $(PLUF_PATH)/migrate.php --conf=IDF/conf/idf.php -a -d -i
|
||||
|
||||
db-update:
|
||||
@cd src && php $(PLUF_PATH)/migrate.php --conf=IDF/conf/idf.php -a -d
|
||||
|
46
NEWS.mdtext
46
NEWS.mdtext
@@ -1,17 +1,59 @@
|
||||
# InDefero 1.2 - xxx xxx xx xx:xx 2011 UTC
|
||||
|
||||
ATTENTION: You need Pluf [324ae60b](http://projects.ceondo.com/p/pluf/source/commit/324ae60b)
|
||||
or newer to properly run this version of Indefero!
|
||||
|
||||
## New Features
|
||||
|
||||
## Bugfixes
|
||||
- Indefero's issue tracker can now bi-directionally link issues with variable, configurable
|
||||
terms, such as "is related to", "is blocked by" or "is duplicated by" (issue 638)
|
||||
- Mercurial source views now show parent revisions (if any) and detailed change information
|
||||
- Subversion source views now show detailed change information (issue 622)
|
||||
- File download URLs now contain the file name rather than the upload id; old links still work though (issues 559 and 686)
|
||||
- Display monotone file and directory attributes in the tree and file view
|
||||
(needs a monotone with an interface version of 13.1 or newer)
|
||||
- The context area is now kept in view when a page scrolls down several pages
|
||||
|
||||
## Bugfixes
|
||||
|
||||
- The SVN interface acts more robust if an underlying repository has been restructured (issue 364)
|
||||
- monotone zip archive entries now all carry the revision date as mtime (issue 645)
|
||||
- Timeline only displays filter options for items a user has actually access to (issue 655)
|
||||
- Fix the self-link of the RSS feed (issue 666)
|
||||
- The log, tags and branches parsers for Mercurial are more robust now (issue 663)
|
||||
- Fix SSH public key parsing issues and improve the check for existing, uploaded keys (issue 679)
|
||||
- Diff views now show empty context lines for git and hg again (issue 688)
|
||||
- Let the SVN command line client not store the login credentials we give him as arguments
|
||||
- The usher section in the forge administration no longer displays a bogus
|
||||
server enty in case no monotone server is configured in the connected
|
||||
usher instance
|
||||
- Prevent a timeout from popping up when Usher is restarted (issue 695)
|
||||
- The SyncMonotone plugin now cleans up partial artifacts it created during the addition of
|
||||
a new project or monotone key, in case an error popped up in the middle (issue 697)
|
||||
- Better error detection and reporting in the SyncMonotone plugin
|
||||
ATTENTION: This needs Pluf 46b7f251 or newer!
|
||||
- Fix the branch links users of the Subversion frontend get when they enter a wrong revision
|
||||
and only display this list if there are any branches available for all SCMs
|
||||
|
||||
## Documentation
|
||||
|
||||
- The documentation on the setup of the monotone plugin has been improved.
|
||||
|
||||
## Translations
|
||||
|
||||
# InDefero 1.1.2 - Thu May 26 07:42:25 2011 UTC
|
||||
|
||||
## Bugfixes
|
||||
|
||||
- Fix tags extraction from git repository (issue 675)
|
||||
- Fix SSH validation method (issue 671)
|
||||
- Fix malformed URL in the RSS (issue 666)
|
||||
- Fix validateRevision call for Mercurial Scm (issue 657)
|
||||
|
||||
## Translations
|
||||
|
||||
- Missing word in French translation (issue 672)
|
||||
- Update Spanish translation
|
||||
|
||||
# InDefero 1.1.1 - Mon Mar 28 15:52 2011 UTC
|
||||
|
||||
## Bugfixes
|
||||
|
@@ -25,7 +25,7 @@ If you install monotone from source (<http://monotone.ca/downloads.php>),
|
||||
please follow the `INSTALL` document which comes with the software.
|
||||
It contains detailed instructions, including all needed dependencies.
|
||||
|
||||
## Choose your indefero setup
|
||||
## Choose your indefero (IDF) setup
|
||||
|
||||
The monotone plugin can be used in several different ways:
|
||||
|
||||
@@ -112,14 +112,40 @@ The monotone plugin can be used in several different ways:
|
||||
^D
|
||||
$ chmod 600 usher.conf
|
||||
|
||||
**ATTENTION:** Do _not_ configure a default monotone server key in `usher.conf`,
|
||||
otherwise the individual server key that IDF creates for each project is
|
||||
not used and this could cause problems.
|
||||
|
||||
Your indefero www user needs later write access to `usher.conf` and
|
||||
`projects/`. There are two ways of setting this up:
|
||||
|
||||
* Make the usher user the web user, for example via Apache's `suexec`
|
||||
* Use acls, like this:
|
||||
* Make the usher user the web user, for example via Apache's `suexec`.
|
||||
This is however a bit clumsy.
|
||||
* Preferred: Use Access Control Lists (ACLs), like this:
|
||||
|
||||
#
|
||||
# Linux
|
||||
#
|
||||
$ setfacl -m u:www:rw usher.conf
|
||||
$ setfacl -m d:u:www:rwx projects/
|
||||
$ setfacl -m d:u:usher:rwx projects/
|
||||
#
|
||||
# FreeBSD
|
||||
#
|
||||
$ setfacl -m user:www:rw::allow usher.conf
|
||||
$ setfacl -m user:www:rwxp:fd:allow projects/
|
||||
$ setfacl -m user:usher:rwxp:fd:allow projects/
|
||||
#
|
||||
# Mac OS X
|
||||
#
|
||||
chmod +a '_www allow read,write' usher.conf
|
||||
chmod +a '_www allow read,write,delete,add_file,add_subdirectory,file_inherit,directory_inherit' projects/
|
||||
chmod +a 'usher allow read,write,delete,add_file,add_subdirectory,file_inherit,directory_inherit' projects/
|
||||
|
||||
In each example's last line, `usher` is the user which is executing
|
||||
the usher instance. **It is very important to add this line, otherwise
|
||||
usher won't be able to read and write into the initial file system
|
||||
setup IDF creates!**
|
||||
|
||||
5. Wrap a daemonizer around usher, for example supervise from daemontools
|
||||
(<http://cr.yp.to/damontools.html>):
|
||||
|
@@ -101,7 +101,7 @@ class IDF_Diff
|
||||
$files[$current_file]['chunks'][] = array();
|
||||
|
||||
while ($i < $diffsize && ($addlines >= 0 || $dellines >= 0)) {
|
||||
$linetype = $this->lines[$i] != '' ? $this->lines[$i][0] : ' ';
|
||||
$linetype = $this->lines[$i] != '' ? $this->lines[$i][0] : false;
|
||||
switch ($linetype) {
|
||||
case ' ':
|
||||
$files[$current_file]['chunks'][$current_chunk][] =
|
||||
|
@@ -36,6 +36,7 @@ class IDF_Form_IssueCreate extends Pluf_Form
|
||||
public $user = null;
|
||||
public $project = null;
|
||||
public $show_full = false;
|
||||
public $relation_types = null;
|
||||
|
||||
public function initFields($extra=array())
|
||||
{
|
||||
@@ -45,9 +46,12 @@ class IDF_Form_IssueCreate extends Pluf_Form
|
||||
or $this->user->hasPerm('IDF.project-member', $this->project)) {
|
||||
$this->show_full = true;
|
||||
}
|
||||
$this->relation_types = $this->project->getRelationsFromConfig();
|
||||
|
||||
$contentTemplate = $this->project->getConf()->getVal(
|
||||
'labels_issue_template', IDF_Form_IssueTrackingConf::init_template
|
||||
);
|
||||
|
||||
$this->fields['summary'] = new Pluf_Form_Field_Varchar(
|
||||
array('required' => true,
|
||||
'label' => __('Summary'),
|
||||
@@ -109,15 +113,14 @@ class IDF_Form_IssueCreate extends Pluf_Form
|
||||
),
|
||||
));
|
||||
|
||||
$relation_types = $extra['project']->getRelationsFromConfig();
|
||||
$this->fields['relation_type'] = new Pluf_Form_Field_Varchar(
|
||||
$this->fields['relation_type0'] = new Pluf_Form_Field_Varchar(
|
||||
array('required' => false,
|
||||
'label' => __('This issue'),
|
||||
'initial' => $relation_types[0],
|
||||
'initial' => current($this->relation_types),
|
||||
'widget_attrs' => array('size' => 15),
|
||||
));
|
||||
|
||||
$this->fields['relation_issue'] = new Pluf_Form_Field_Varchar(
|
||||
$this->fields['relation_issue0'] = new Pluf_Form_Field_Varchar(
|
||||
array('required' => false,
|
||||
'label' => null,
|
||||
'initial' => '',
|
||||
@@ -250,6 +253,63 @@ class IDF_Form_IssueCreate extends Pluf_Form
|
||||
return $this->cleaned_data['status'];
|
||||
}
|
||||
|
||||
// this method is not called from Pluf_Form directly, but shared for
|
||||
// among all similar fields
|
||||
function clean_relation_type($value)
|
||||
{
|
||||
$relation_type = trim($value);
|
||||
if (empty($relation_type))
|
||||
return '';
|
||||
|
||||
$found = false;
|
||||
foreach ($this->relation_types as $type) {
|
||||
if ($type == $relation_type) {
|
||||
$found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!$found) {
|
||||
throw new Pluf_Form_Invalid(__('You provided an invalid relation type.'));
|
||||
}
|
||||
return $relation_type;
|
||||
}
|
||||
|
||||
function clean_relation_type0()
|
||||
{
|
||||
return $this->clean_relation_type($this->cleaned_data['relation_type0']);
|
||||
}
|
||||
|
||||
// this method is not called from Pluf_Form directly, but shared for
|
||||
// among all similar fields
|
||||
function clean_relation_issue($value)
|
||||
{
|
||||
$issues = trim($value);
|
||||
if (empty($issues))
|
||||
return '';
|
||||
|
||||
$issue_ids = preg_split('/\s*,\s*/', $issues, -1, PREG_SPLIT_NO_EMPTY);
|
||||
foreach ($issue_ids as $issue_id) {
|
||||
if (!ctype_digit($issue_id) || (int)$issue_id < 1) {
|
||||
throw new Pluf_Form_Invalid(sprintf(
|
||||
__('The value "%s" is not a valid issue id.'), $issue_id
|
||||
));
|
||||
}
|
||||
$issue = new IDF_Issue($issue_id);
|
||||
if ($issue->id != $issue_id || $issue->project != $this->project->id) {
|
||||
throw new Pluf_Form_Invalid(sprintf(
|
||||
__('The issue "%s" does not exist.'), $issue_id
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
return implode(', ', $issue_ids);
|
||||
}
|
||||
|
||||
function clean_relation_issue0()
|
||||
{
|
||||
return $this->clean_relation_issue($this->cleaned_data['relation_issue0']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clean the attachments post failure.
|
||||
*/
|
||||
@@ -313,6 +373,30 @@ class IDF_Form_IssueCreate extends Pluf_Form
|
||||
foreach ($tags as $tag) {
|
||||
$issue->setAssoc($tag);
|
||||
}
|
||||
// add relations (if any)
|
||||
if (!empty($this->cleaned_data['relation_type0'])) {
|
||||
$verb = $this->cleaned_data['relation_type0'];
|
||||
$other_verb = $this->relation_types[$verb];
|
||||
$related_issues = preg_split('/\s*,\s*/', $this->cleaned_data['relation_issue0'], -1, PREG_SPLIT_NO_EMPTY);
|
||||
|
||||
foreach ($related_issues as $related_issue_id) {
|
||||
$related_issue = new IDF_Issue($related_issue_id);
|
||||
$rel = new IDF_IssueRelation();
|
||||
$rel->issue = $issue;
|
||||
$rel->verb = $verb;
|
||||
$rel->other_issue = $related_issue;
|
||||
$rel->submitter = $this->user;
|
||||
$rel->create();
|
||||
|
||||
$other_rel = new IDF_IssueRelation();
|
||||
$other_rel->issue = $related_issue;
|
||||
$other_rel->verb = $other_verb;
|
||||
$other_rel->other_issue = $issue;
|
||||
$other_rel->submitter = $this->user;
|
||||
$other_rel->create();
|
||||
}
|
||||
}
|
||||
|
||||
// add the first comment
|
||||
$comment = new IDF_IssueComment();
|
||||
$comment->issue = $issue;
|
||||
|
@@ -72,15 +72,29 @@ Performance = Performance issue
|
||||
Usability = Affects program usability
|
||||
Maintainability = Hinders future changes';
|
||||
const init_one_max = 'Type, Priority, Milestone';
|
||||
// ATTENTION: if you change something here, change the values below as well!
|
||||
const init_relations = 'is related to
|
||||
blocks, is blocked by
|
||||
duplicates, is duplicated by';
|
||||
|
||||
// These are actually all noop's, but we have no other chance to
|
||||
// tell IDF's translation mechanism to mark the strings as translatable
|
||||
// FIXME: IDF should get a internal translation system for strings like
|
||||
// that, that can also be easily expanded by users
|
||||
private function noop()
|
||||
{
|
||||
__('is related to');
|
||||
__('blocks');
|
||||
__('is blocked by');
|
||||
__('duplicates');
|
||||
__('is duplicated by');
|
||||
}
|
||||
|
||||
public function initFields($extra=array())
|
||||
{
|
||||
$this->fields['labels_issue_template'] = new Pluf_Form_Field_Varchar(
|
||||
array('required' => false,
|
||||
'label' => __('Define an issue template to hint to the reporter to provide certain information'),
|
||||
'label' => __('Define an issue template to hint the reporter to provide certain information'),
|
||||
'initial' => self::init_template,
|
||||
'widget_attrs' => array('rows' => 7,
|
||||
'cols' => 75),
|
||||
|
@@ -39,6 +39,7 @@ class IDF_Form_IssueUpdate extends IDF_Form_IssueCreate
|
||||
or $this->user->hasPerm('IDF.project-member', $this->project)) {
|
||||
$this->show_full = true;
|
||||
}
|
||||
$this->relation_types = $this->project->getRelationsFromConfig();
|
||||
if ($this->show_full) {
|
||||
$this->fields['summary'] = new Pluf_Form_Field_Varchar(
|
||||
array('required' => true,
|
||||
@@ -69,11 +70,11 @@ class IDF_Form_IssueUpdate extends IDF_Form_IssueCreate
|
||||
// case of someone allowing the upload path to be accessible
|
||||
// to everybody.
|
||||
for ($i=1;$i<4;$i++) {
|
||||
$filename = substr($md5, 0, 2).'/'.substr($md5, 2, 2).'/'.substr($md5, 4).'/%s.dummy';
|
||||
$filename = substr($md5, 0, 2).'/'.substr($md5, 2, 2).'/'.substr($md5, 4).'/%s.dummy';
|
||||
$this->fields['attachment'.$i] = new Pluf_Form_Field_File(
|
||||
array('required' => false,
|
||||
'label' => __('Attach a file'),
|
||||
'move_function_params' =>
|
||||
'move_function_params' =>
|
||||
array('upload_path' => $upload_path,
|
||||
'upload_path_create' => true,
|
||||
'file_name' => $filename,
|
||||
@@ -102,6 +103,52 @@ class IDF_Form_IssueUpdate extends IDF_Form_IssueCreate
|
||||
'size' => 15,
|
||||
),
|
||||
));
|
||||
|
||||
$idx = 0;
|
||||
// note: clean_relation_type0 and clean_relation_issue0 already
|
||||
// exist in the base class
|
||||
$this->fields['relation_type'.$idx] = new Pluf_Form_Field_Varchar(
|
||||
array('required' => false,
|
||||
'label' => __('This issue'),
|
||||
'initial' => current($this->relation_types),
|
||||
'widget_attrs' => array('size' => 15),
|
||||
));
|
||||
|
||||
$this->fields['relation_issue'.$idx] = new Pluf_Form_Field_Varchar(
|
||||
array('required' => false,
|
||||
'label' => null,
|
||||
'initial' => '',
|
||||
'widget_attrs' => array('size' => 10),
|
||||
));
|
||||
|
||||
++$idx;
|
||||
$relatedIssues = $this->issue->getGroupedRelatedIssues(array(), true);
|
||||
foreach ($relatedIssues as $verb => $ids) {
|
||||
$this->fields['relation_type'.$idx] = new Pluf_Form_Field_Varchar(
|
||||
array('required' => false,
|
||||
'label' => __('This issue'),
|
||||
'initial' => $verb,
|
||||
'widget_attrs' => array('size' => 15),
|
||||
));
|
||||
$m = 'clean_relation_type'.$idx;
|
||||
$this->$m = create_function('$form', '
|
||||
return $form->clean_relation_type($form->cleaned_data["relation_type'.$idx.'"]);
|
||||
');
|
||||
|
||||
$this->fields['relation_issue'.$idx] = new Pluf_Form_Field_Varchar(
|
||||
array('required' => false,
|
||||
'label' => null,
|
||||
'initial' => implode(', ', $ids),
|
||||
'widget_attrs' => array('size' => 10),
|
||||
));
|
||||
$m = 'clean_relation_issue'.$idx;
|
||||
$this->$m = create_function('$form', '
|
||||
return $form->clean_relation_issue($form->cleaned_data["relation_issue'.$idx.'"]);
|
||||
');
|
||||
|
||||
++$idx;
|
||||
}
|
||||
|
||||
$tags = $this->issue->get_tags_list();
|
||||
for ($i=1;$i<7;$i++) {
|
||||
$initial = '';
|
||||
@@ -155,6 +202,51 @@ class IDF_Form_IssueUpdate extends IDF_Form_IssueCreate
|
||||
public function clean()
|
||||
{
|
||||
$this->cleaned_data = parent::clean();
|
||||
|
||||
// normalize the user's input by removing dublettes and by combining
|
||||
// ids from identical verbs in different input fields into one array
|
||||
$normRelatedIssues = array();
|
||||
for ($idx = 0; isset($this->cleaned_data['relation_type'.$idx]); ++$idx) {
|
||||
$verb = $this->cleaned_data['relation_type'.$idx];
|
||||
if (empty($verb))
|
||||
continue;
|
||||
|
||||
$ids = preg_split('/\s*,\s*/', $this->cleaned_data['relation_issue'.$idx],
|
||||
-1, PREG_SPLIT_NO_EMPTY);
|
||||
if (count($ids) == 0)
|
||||
continue;
|
||||
|
||||
if (!array_key_exists($verb, $normRelatedIssues))
|
||||
$normRelatedIssues[$verb] = array();
|
||||
foreach ($ids as $id) {
|
||||
if (!in_array($id, $normRelatedIssues[$verb]))
|
||||
$normRelatedIssues[$verb][] = $id;
|
||||
}
|
||||
}
|
||||
|
||||
// now look at any added / removed ids
|
||||
$added = $removed = array();
|
||||
$relatedIssues = $this->issue->getGroupedRelatedIssues(array(), true);
|
||||
$added = array_diff_key($normRelatedIssues, $relatedIssues);
|
||||
$removed = array_diff_key($relatedIssues, $normRelatedIssues);
|
||||
|
||||
$keysToLookAt = array_keys(
|
||||
array_intersect_key($relatedIssues, $normRelatedIssues)
|
||||
);
|
||||
foreach ($keysToLookAt as $key) {
|
||||
$a = array_diff($normRelatedIssues[$key], $relatedIssues[$key]);
|
||||
if (count($a) > 0)
|
||||
$added[$key] = $a;
|
||||
$r = array_diff($relatedIssues[$key], $normRelatedIssues[$key]);
|
||||
if (count($r) > 0)
|
||||
$removed[$key] = $r;
|
||||
}
|
||||
|
||||
// cache the added / removed data, so we do not have to
|
||||
// calculate that again
|
||||
$this->cleaned_data['_added_issue_relations'] = $added;
|
||||
$this->cleaned_data['_removed_issue_relations'] = $removed;
|
||||
|
||||
// As soon as we know that at least one change was done, we
|
||||
// return the cleaned data and do not go further.
|
||||
if (strlen(trim($this->cleaned_data['content']))) {
|
||||
@@ -214,6 +306,11 @@ class IDF_Form_IssueUpdate extends IDF_Form_IssueCreate
|
||||
return $this->cleaned_data;
|
||||
}
|
||||
}
|
||||
|
||||
if (count($this->cleaned_data['_added_issue_relations']) != 0 ||
|
||||
count($this->cleaned_data['_removed_issue_relations']) != 0) {
|
||||
return $this->cleaned_data;
|
||||
}
|
||||
}
|
||||
// no changes!
|
||||
throw new Pluf_Form_Invalid(__('No changes were entered.'));
|
||||
@@ -255,20 +352,22 @@ class IDF_Form_IssueUpdate extends IDF_Form_IssueCreate
|
||||
foreach ($tags as $tag) {
|
||||
if (!Pluf_Model_InArray($tag, $oldtags)) {
|
||||
if (!isset($changes['lb'])) $changes['lb'] = array();
|
||||
if (!isset($changes['lb']['add'])) $changes['lb']['add'] = array();
|
||||
if ($tag->class != 'Other') {
|
||||
$changes['lb'][] = (string) $tag; //new tag
|
||||
$changes['lb']['add'][] = (string) $tag; //new tag
|
||||
} else {
|
||||
$changes['lb'][] = (string) $tag->name;
|
||||
$changes['lb']['add'][] = (string) $tag->name;
|
||||
}
|
||||
}
|
||||
}
|
||||
foreach ($oldtags as $tag) {
|
||||
if (!Pluf_Model_InArray($tag, $tags)) {
|
||||
if (!isset($changes['lb'])) $changes['lb'] = array();
|
||||
if (!isset($changes['lb']['rem'])) $changes['lb']['rem'] = array();
|
||||
if ($tag->class != 'Other') {
|
||||
$changes['lb'][] = '-'.(string) $tag; //new tag
|
||||
$changes['lb']['rem'][] = (string) $tag; //new tag
|
||||
} else {
|
||||
$changes['lb'][] = '-'.(string) $tag->name;
|
||||
$changes['lb']['rem'][] = (string) $tag->name;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -286,6 +385,47 @@ class IDF_Form_IssueUpdate extends IDF_Form_IssueCreate
|
||||
or ((!is_null($owner) and !is_null($this->issue->get_owner())) and $owner->id != $this->issue->get_owner()->id)) {
|
||||
$changes['ow'] = (is_null($owner)) ? '---' : $owner->login;
|
||||
}
|
||||
// Issue relations - additions
|
||||
foreach ($this->cleaned_data['_added_issue_relations'] as $verb => $ids) {
|
||||
$other_verb = $this->relation_types[$verb];
|
||||
foreach ($ids as $id) {
|
||||
$related_issue = new IDF_Issue($id);
|
||||
$rel = new IDF_IssueRelation();
|
||||
$rel->issue = $this->issue;
|
||||
$rel->verb = $verb;
|
||||
$rel->other_issue = $related_issue;
|
||||
$rel->submitter = $this->user;
|
||||
$rel->create();
|
||||
|
||||
$other_rel = new IDF_IssueRelation();
|
||||
$other_rel->issue = $related_issue;
|
||||
$other_rel->verb = $other_verb;
|
||||
$other_rel->other_issue = $this->issue;
|
||||
$other_rel->submitter = $this->user;
|
||||
$other_rel->create();
|
||||
}
|
||||
if (!isset($changes['rel'])) $changes['rel'] = array();
|
||||
if (!isset($changes['rel']['add'])) $changes['rel']['add'] = array();
|
||||
$changes['rel']['add'][] = $verb.' '.implode(', ', $ids);
|
||||
}
|
||||
// Issue relations - removals
|
||||
foreach ($this->cleaned_data['_removed_issue_relations'] as $verb => $ids) {
|
||||
foreach ($ids as $id) {
|
||||
$db = &Pluf::db();
|
||||
$table = Pluf::factory('IDF_IssueRelation')->getSqlTable();
|
||||
$sql = new Pluf_SQL('verb=%s AND (
|
||||
(issue=%s AND other_issue=%s) OR
|
||||
(other_issue=%s AND issue=%s))',
|
||||
array($verb,
|
||||
$this->issue->id, $id,
|
||||
$this->issue->id, $id));
|
||||
$db->execute('DELETE FROM '.$table.' WHERE '.$sql->gen());
|
||||
}
|
||||
|
||||
if (!isset($changes['rel'])) $changes['rel'] = array();
|
||||
if (!isset($changes['rel']['rem'])) $changes['rel']['rem'] = array();
|
||||
$changes['rel']['rem'][] = $verb.' '.implode(', ', $ids);
|
||||
}
|
||||
// Update the issue
|
||||
$this->issue->batchAssoc('IDF_Tag', $tagids);
|
||||
$this->issue->summary = trim($this->cleaned_data['summary']);
|
||||
|
@@ -317,8 +317,15 @@ class IDF_Form_UserAccount extends Pluf_Form
|
||||
return '';
|
||||
}
|
||||
|
||||
if (preg_match('#^ssh\-[a-z]{3}\s\S+(\s\S+)?$#', $key)) {
|
||||
$key = str_replace(array("\n", "\r"), '', $key);
|
||||
$keysearch = '';
|
||||
if (preg_match('#^(ssh\-(?:dss|rsa)\s+\S+)(.*)#', $key, $m)) {
|
||||
$basekey = preg_replace('/\s+/', ' ', $m[1]);
|
||||
$comment = trim(preg_replace('/[\r\n]/', ' ', $m[2]));
|
||||
|
||||
$keysearch = $basekey.'%';
|
||||
$key = $basekey;
|
||||
if (!empty($comment))
|
||||
$key .= ' '.$comment;
|
||||
|
||||
if (Pluf::f('idf_strong_key_check', false)) {
|
||||
|
||||
@@ -337,7 +344,9 @@ class IDF_Form_UserAccount extends Pluf_Form
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (preg_match('#^\[pubkey [^\]]+\]\s*\S+\s*\[end\]$#', $key)) {
|
||||
else if (preg_match('#^\[pubkey [^\]]+\]\s*(\S+)\s*\[end\]$#', $key, $m)) {
|
||||
$keysearch = '%'.$m[1].'%';
|
||||
|
||||
if (Pluf::f('idf_strong_key_check', false)) {
|
||||
|
||||
// if monotone can read it, it should be valid
|
||||
@@ -367,7 +376,7 @@ class IDF_Form_UserAccount extends Pluf_Form
|
||||
if ($user) {
|
||||
$ruser = Pluf::factory('Pluf_User', $user);
|
||||
if ($ruser->id > 0) {
|
||||
$sql = new Pluf_SQL('content=%s', array($key));
|
||||
$sql = new Pluf_SQL('content LIKE %s AND user=%s', array($keysearch, $ruser->id));
|
||||
$keys = Pluf::factory('IDF_Key')->getList(array('filter' => $sql->gen()));
|
||||
if (count($keys) > 0) {
|
||||
throw new Pluf_Form_Invalid(
|
||||
|
@@ -169,6 +169,24 @@ class IDF_Issue extends Pluf_Model
|
||||
}
|
||||
}
|
||||
|
||||
function getGroupedRelatedIssues($opts = array(), $idsOnly = false)
|
||||
{
|
||||
$rels = $this->get_related_issues_list(array_merge($opts, array(
|
||||
'view' => 'with_other_issue',
|
||||
)));
|
||||
|
||||
$res = array();
|
||||
foreach ($rels as $rel) {
|
||||
$verb = $rel->verb;
|
||||
if (!array_key_exists($verb, $res)) {
|
||||
$res[$verb] = array();
|
||||
}
|
||||
$res[$verb][] = $idsOnly ? $rel->other_issue : $rel;
|
||||
}
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an HTML fragment used to display this issue in the
|
||||
* timeline.
|
||||
|
@@ -155,10 +155,19 @@ class IDF_IssueComment extends Pluf_Model
|
||||
$out .= __('Owner:'); break;
|
||||
case 'lb':
|
||||
$out .= __('Labels:'); break;
|
||||
case 'rel':
|
||||
$out .= __('Relations:'); break;
|
||||
}
|
||||
$out .= '</strong> ';
|
||||
if ($w == 'lb') {
|
||||
$out .= Pluf_esc(implode(', ', $v));
|
||||
if ($w == 'lb' || $w == 'rel') {
|
||||
foreach ($v as $t => $ls) {
|
||||
foreach ($ls as $l) {
|
||||
if ($t == 'rem') $out .= '<s>';
|
||||
$out .= Pluf_esc($l);
|
||||
if ($t == 'rem') $out .= '</s>';
|
||||
$out .= ' ';
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$out .= Pluf_esc($v);
|
||||
}
|
||||
|
100
src/IDF/IssueRelation.php
Normal file
100
src/IDF/IssueRelation.php
Normal file
@@ -0,0 +1,100 @@
|
||||
<?php
|
||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# This file is part of InDefero, an open source project management application.
|
||||
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
|
||||
#
|
||||
# InDefero 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.
|
||||
#
|
||||
# InDefero 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 St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/**
|
||||
* A relation of one issue to another
|
||||
*/
|
||||
class IDF_IssueRelation extends Pluf_Model
|
||||
{
|
||||
public $_model = __CLASS__;
|
||||
|
||||
function init()
|
||||
{
|
||||
$this->_a['table'] = 'idf_issuerelations';
|
||||
$this->_a['model'] = __CLASS__;
|
||||
$this->_a['cols'] = array(
|
||||
// It is mandatory to have an "id" column.
|
||||
'id' =>
|
||||
array(
|
||||
'type' => 'Pluf_DB_Field_Sequence',
|
||||
'blank' => true,
|
||||
),
|
||||
'issue' =>
|
||||
array(
|
||||
'type' => 'Pluf_DB_Field_Foreignkey',
|
||||
'model' => 'IDF_Issue',
|
||||
'blank' => false,
|
||||
'verbose' => __('issue'),
|
||||
'relate_name' => 'related_issues',
|
||||
),
|
||||
'verb' =>
|
||||
array(
|
||||
'type' => 'Pluf_DB_Field_Text',
|
||||
'blank' => false,
|
||||
'verbose' => __('verb'),
|
||||
),
|
||||
'other_issue' =>
|
||||
array(
|
||||
'type' => 'Pluf_DB_Field_Foreignkey',
|
||||
'model' => 'IDF_Issue',
|
||||
'blank' => false,
|
||||
'verbose' => __('other issue'),
|
||||
'relate_name' => 'related_other_issues',
|
||||
),
|
||||
'submitter' =>
|
||||
array(
|
||||
'type' => 'Pluf_DB_Field_Foreignkey',
|
||||
'model' => 'Pluf_User',
|
||||
'blank' => false,
|
||||
'verbose' => __('submitter'),
|
||||
),
|
||||
'creation_dtime' =>
|
||||
array(
|
||||
'type' => 'Pluf_DB_Field_Datetime',
|
||||
'blank' => true,
|
||||
'verbose' => __('creation date'),
|
||||
),
|
||||
);
|
||||
$this->_a['idx'] = array(
|
||||
'creation_dtime_idx' =>
|
||||
array(
|
||||
'col' => 'creation_dtime',
|
||||
'type' => 'normal',
|
||||
),
|
||||
);
|
||||
$issuetbl = $this->_con->pfx.'idf_issues';
|
||||
$this->_a['views'] = array(
|
||||
'with_other_issue' => array(
|
||||
'join' => 'INNER JOIN '.$issuetbl.' ON other_issue='.$issuetbl.'.id',
|
||||
'select' => $this->getSelect().', summary',
|
||||
'props' => array('summary' => 'other_summary'),
|
||||
));
|
||||
}
|
||||
|
||||
function preSave($create=false)
|
||||
{
|
||||
if ($this->id == '') {
|
||||
$this->creation_dtime = gmdate('Y-m-d H:i:s');
|
||||
}
|
||||
}
|
||||
}
|
@@ -80,7 +80,7 @@ class IDF_Key extends Pluf_Model
|
||||
if (preg_match('#^\[pubkey ([^\]]+)\]\s*(\S+)\s*\[end\]$#', $this->content, $m)) {
|
||||
return array('mtn', $m[1], $m[2]);
|
||||
}
|
||||
else if (preg_match('#^ssh\-[a-z]{3}\s(\S+)(?:\s(\S*))?$#', $this->content, $m)) {
|
||||
else if (preg_match('#^ssh\-(?:dss|rsa)\s(\S+)(?:\s(.*))?$#', $this->content, $m)) {
|
||||
if (!isset($m[2])) {
|
||||
$m[2] = "";
|
||||
}
|
||||
|
90
src/IDF/Migrations/17AddIssueRelations.php
Normal file
90
src/IDF/Migrations/17AddIssueRelations.php
Normal file
@@ -0,0 +1,90 @@
|
||||
<?php
|
||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# This file is part of InDefero, an open source project management application.
|
||||
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
|
||||
#
|
||||
# InDefero 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.
|
||||
#
|
||||
# InDefero 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 St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/**
|
||||
* Add the new IDF_IssueRelation model.
|
||||
*
|
||||
*/
|
||||
|
||||
function IDF_Migrations_17AddIssueRelations_up($params=null)
|
||||
{
|
||||
$db = Pluf::db();
|
||||
$schema = new Pluf_DB_Schema($db);
|
||||
$schema->model = new IDF_IssueRelation();
|
||||
$schema->createTables();
|
||||
|
||||
// change the serialization format for added / removed labels in IDF_IssueComment
|
||||
$comments = Pluf::factory('IDF_IssueComment')->getList();
|
||||
foreach ($comments as $comment) {
|
||||
if (!isset($comment->changes['lb'])) continue;
|
||||
$changes = $comment->changes;
|
||||
$adds = $removals = array();
|
||||
foreach ($comment->changes['lb'] as $lb) {
|
||||
if (substr($lb, 0, 1) == '-')
|
||||
$removals[] = substr($lb, 1);
|
||||
else
|
||||
$adds[] = $lb;
|
||||
}
|
||||
$changes['lb'] = array();
|
||||
if (count($adds) > 0)
|
||||
$changes['lb']['add'] = $adds;
|
||||
if (count($removals) > 0)
|
||||
$changes['lb']['rem'] = $removals;
|
||||
$comment->changes = $changes;
|
||||
$comment->update();
|
||||
}
|
||||
}
|
||||
|
||||
function IDF_Migrations_17AddIssueRelations_down($params=null)
|
||||
{
|
||||
$db = Pluf::db();
|
||||
$schema = new Pluf_DB_Schema($db);
|
||||
$schema->model = new IDF_IssueRelation();
|
||||
$schema->dropTables();
|
||||
|
||||
// change the serialization format for added / removed labels in IDF_IssueComment
|
||||
$comments = Pluf::factory('IDF_IssueComment')->getList();
|
||||
foreach ($comments as $comment) {
|
||||
$changes = $comment->changes;
|
||||
if (empty($changes))
|
||||
continue;
|
||||
if (isset($changes['lb'])) {
|
||||
$labels = array();
|
||||
foreach ($changes['lb'] as $type => $lbs) {
|
||||
if (!is_array($lbs)) {
|
||||
$labels[] = $lbs;
|
||||
continue;
|
||||
}
|
||||
foreach ($lbs as $lb) {
|
||||
$labels[] = ($type == 'rem' ? '-' : '') . $lb;
|
||||
}
|
||||
}
|
||||
$changes['lb'] = $labels;
|
||||
}
|
||||
// while we're at it, remove any 'rel' changes
|
||||
unset($changes['rel']);
|
||||
$comment->changes = $changes;
|
||||
$comment->update();
|
||||
}
|
||||
}
|
||||
|
63
src/IDF/Migrations/18DownloadMD5.php
Normal file
63
src/IDF/Migrations/18DownloadMD5.php
Normal file
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# This file is part of InDefero, an open source project management application.
|
||||
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
|
||||
#
|
||||
# InDefero 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.
|
||||
#
|
||||
# InDefero 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 St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/**
|
||||
* Add the md5 column for the download model.
|
||||
*/
|
||||
|
||||
function IDF_Migrations_18DownloadMD5_up($params=null)
|
||||
{
|
||||
// Add the row
|
||||
$table = Pluf::factory('IDF_Upload')->getSqlTable();
|
||||
$sql = array();
|
||||
$sql['PostgreSQL'] = 'ALTER TABLE '.$table.' ADD COLUMN "md5" VARCHAR(32) DEFAULT \'\'';
|
||||
$sql['MySQL'] = 'ALTER TABLE '.$table.' ADD COLUMN `md5` VARCHAR(32) DEFAULT \'\'';
|
||||
$db = Pluf::db();
|
||||
$engine = Pluf::f('db_engine');
|
||||
if (!isset($sql[$engine])) {
|
||||
throw new Exception('SQLite complex migration not supported.');
|
||||
}
|
||||
$db->execute($sql[$engine]);
|
||||
|
||||
// Process md5 of already uploaded file
|
||||
$files = Pluf::factory('IDF_Upload')->getList();
|
||||
foreach ($files as $f) {
|
||||
$f->md5 = md5_file (Pluf::f('upload_path') . '/' . $f->get_project()->shortname . '/files/' . $f->file);
|
||||
$f->update();
|
||||
}
|
||||
}
|
||||
|
||||
function IDF_Migrations_18DownloadMD5_down($params=null)
|
||||
{
|
||||
// Remove the row
|
||||
$table = Pluf::factory('IDF_Upload')->getSqlTable();
|
||||
$sql = array();
|
||||
$sql['PostgreSQL'] = 'ALTER TABLE '.$table.' DROP COLUMN "md5"';
|
||||
$sql['MySQL'] = 'ALTER TABLE '.$table.' DROP COLUMN `md5`';
|
||||
$db = Pluf::db();
|
||||
$engine = Pluf::f('db_engine');
|
||||
if (!isset($sql[$engine])) {
|
||||
throw new Exception('SQLite complex migration not supported.');
|
||||
}
|
||||
$db->execute($sql[$engine]);
|
||||
}
|
@@ -54,6 +54,7 @@ function IDF_Migrations_Backup_run($folder, $name=null)
|
||||
'IDF_Queue',
|
||||
'IDF_Gconf',
|
||||
'IDF_EmailAddress',
|
||||
'IDF_IssueRelation',
|
||||
);
|
||||
$db = Pluf::db();
|
||||
// Now, for each table, we dump the content in json, this is a
|
||||
@@ -100,6 +101,7 @@ function IDF_Migrations_Backup_restore($folder, $name)
|
||||
'IDF_Queue',
|
||||
'IDF_Gconf',
|
||||
'IDF_EmailAddress',
|
||||
'IDF_IssueRelation',
|
||||
);
|
||||
$db = Pluf::db();
|
||||
$schema = new Pluf_DB_Schema($db);
|
||||
|
@@ -51,6 +51,7 @@ function IDF_Migrations_Install_setup($params=null)
|
||||
'IDF_Queue',
|
||||
'IDF_Gconf',
|
||||
'IDF_EmailAddress',
|
||||
'IDF_IssueRelation',
|
||||
);
|
||||
$db = Pluf::db();
|
||||
$schema = new Pluf_DB_Schema($db);
|
||||
@@ -109,6 +110,7 @@ function IDF_Migrations_Install_teardown($params=null)
|
||||
'IDF_Commit',
|
||||
'IDF_Project',
|
||||
'IDF_EmailAddress',
|
||||
'IDF_IssueRelation',
|
||||
);
|
||||
$db = Pluf::db();
|
||||
$schema = new Pluf_DB_Schema($db);
|
||||
|
@@ -27,6 +27,18 @@
|
||||
*/
|
||||
class IDF_Plugin_SyncMonotone
|
||||
{
|
||||
private $old_err_rep = 0;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->old_err_rep = error_reporting(0);
|
||||
}
|
||||
|
||||
public function __destruct()
|
||||
{
|
||||
error_reporting($this->old_err_rep);
|
||||
}
|
||||
|
||||
/**
|
||||
* Entry point of the plugin.
|
||||
*/
|
||||
@@ -80,24 +92,33 @@ class IDF_Plugin_SyncMonotone
|
||||
return;
|
||||
}
|
||||
|
||||
// This guard cleans up on any kind of error, and here is how it works:
|
||||
// As long as the guard is not committed, it keeps a reference to
|
||||
// the given project. When the guard is destroyed and the reference
|
||||
// is still present, it deletes the object. The deletion indirectly
|
||||
// also calls into this plugin again, as the project delete hook
|
||||
// will be called, that removes any changes we've made during the
|
||||
// process.
|
||||
$projectGuard = new IDF_Plugin_SyncMonotone_ModelGuard($project);
|
||||
|
||||
$projecttempl = Pluf::f('mtn_repositories', false);
|
||||
if ($projecttempl === false) {
|
||||
throw new IDF_Scm_Exception(
|
||||
__('"mtn_repositories" must be defined in your configuration file.')
|
||||
$this->_diagnoseProblem(
|
||||
__('"mtn_repositories" must be defined in your configuration file')
|
||||
);
|
||||
}
|
||||
|
||||
$usher_config = Pluf::f('mtn_usher_conf', false);
|
||||
if (!$usher_config || !is_writable($usher_config)) {
|
||||
throw new IDF_Scm_Exception(
|
||||
__('"mtn_usher_conf" does not exist or is not writable.')
|
||||
$this->_diagnoseProblem(
|
||||
__('"mtn_usher_conf" does not exist or is not writable')
|
||||
);
|
||||
}
|
||||
|
||||
$mtnpostpush = realpath(dirname(__FILE__) . '/../../../scripts/mtn-post-push');
|
||||
if (!file_exists($mtnpostpush)) {
|
||||
throw new IDF_Scm_Exception(sprintf(
|
||||
__('Could not find mtn-post-push script "%s".'), $mtnpostpush
|
||||
$this->_diagnoseProblem(sprintf(
|
||||
__('Could not find mtn-post-push script "%s"'), $mtnpostpush
|
||||
));
|
||||
}
|
||||
|
||||
@@ -110,13 +131,12 @@ class IDF_Plugin_SyncMonotone
|
||||
'monotonerc.in',
|
||||
'remote-automate-permissions.in',
|
||||
'hooks.d/',
|
||||
// this is linked and not copied to be able to update
|
||||
// the list of read-only commands on upgrades
|
||||
'hooks.d/indefero_authorize_remote_automate.conf',
|
||||
'hooks.d/indefero_authorize_remote_automate.lua',
|
||||
'hooks.d/indefero_post_push.conf.in',
|
||||
'hooks.d/indefero_post_push.lua',
|
||||
);
|
||||
// enable remote command execution of read-only commands
|
||||
// only for public projects
|
||||
if (!$project->private) {
|
||||
// this is linked and not copied to be able to update
|
||||
// the list of read-only commands on upgrades
|
||||
@@ -131,8 +151,8 @@ class IDF_Plugin_SyncMonotone
|
||||
}
|
||||
foreach ($confdir_contents as $content) {
|
||||
if (!file_exists($confdir.$content)) {
|
||||
throw new IDF_Scm_Exception(sprintf(
|
||||
__('The configuration file %s is missing.'), $content
|
||||
$this->_diagnoseProblem(sprintf(
|
||||
__('The configuration file "%s" is missing'), $content
|
||||
));
|
||||
}
|
||||
}
|
||||
@@ -140,14 +160,15 @@ class IDF_Plugin_SyncMonotone
|
||||
$shortname = $project->shortname;
|
||||
$projectpath = sprintf($projecttempl, $shortname);
|
||||
if (file_exists($projectpath)) {
|
||||
throw new IDF_Scm_Exception(sprintf(
|
||||
__('The project path %s already exists.'), $projectpath
|
||||
$this->_diagnoseProblem(sprintf(
|
||||
__('The project path "%s" already exists'), $projectpath
|
||||
));
|
||||
}
|
||||
|
||||
if (!mkdir($projectpath)) {
|
||||
throw new IDF_Scm_Exception(sprintf(
|
||||
__('The project path %s could not be created.'), $projectpath
|
||||
if (!@mkdir($projectpath)) {
|
||||
$this->_diagnoseProblem(sprintf(
|
||||
__('The project path "%s" could not be created'),
|
||||
$projectpath
|
||||
));
|
||||
}
|
||||
|
||||
@@ -156,7 +177,7 @@ class IDF_Plugin_SyncMonotone
|
||||
//
|
||||
$dbfile = $projectpath.'/database.mtn';
|
||||
$cmd = sprintf('db init -d %s', escapeshellarg($dbfile));
|
||||
self::_mtn_exec($cmd);
|
||||
$this->_mtn_exec($cmd);
|
||||
|
||||
//
|
||||
// step 2) create a server key
|
||||
@@ -175,16 +196,17 @@ class IDF_Plugin_SyncMonotone
|
||||
escapeshellarg($projectpath),
|
||||
escapeshellarg($serverkey)
|
||||
);
|
||||
self::_mtn_exec($cmd);
|
||||
$this->_mtn_exec($cmd);
|
||||
|
||||
//
|
||||
// step 3) create a client key, and save it in IDF
|
||||
//
|
||||
$keydir = Pluf::f('tmp_folder').'/mtn-client-keys';
|
||||
if (!file_exists($keydir)) {
|
||||
if (!mkdir($keydir)) {
|
||||
throw new IDF_Scm_Exception(sprintf(
|
||||
__('The key directory %s could not be created.'), $keydir
|
||||
if (!@mkdir($keydir)) {
|
||||
$this->_diagnoseProblem(sprintf(
|
||||
__('The key directory "%s" could not be created'),
|
||||
$keydir
|
||||
));
|
||||
}
|
||||
}
|
||||
@@ -194,14 +216,14 @@ class IDF_Plugin_SyncMonotone
|
||||
escapeshellarg($keydir),
|
||||
escapeshellarg($clientkey_name)
|
||||
);
|
||||
$keyinfo = self::_mtn_exec($cmd);
|
||||
$keyinfo = $this->_mtn_exec($cmd);
|
||||
|
||||
$parsed_keyinfo = array();
|
||||
try {
|
||||
$parsed_keyinfo = IDF_Scm_Monotone_BasicIO::parse($keyinfo);
|
||||
}
|
||||
catch (Exception $e) {
|
||||
throw new IDF_Scm_Exception(sprintf(
|
||||
$this->_diagnoseProblem(sprintf(
|
||||
__('Could not parse key information: %s'), $e->getMessage()
|
||||
));
|
||||
}
|
||||
@@ -219,13 +241,13 @@ class IDF_Plugin_SyncMonotone
|
||||
escapeshellarg($keydir),
|
||||
escapeshellarg($clientkey_hash)
|
||||
);
|
||||
$clientkey_pubdata = self::_mtn_exec($cmd);
|
||||
$clientkey_pubdata = $this->_mtn_exec($cmd);
|
||||
|
||||
$cmd = sprintf('au put_public_key --db=%s %s',
|
||||
escapeshellarg($dbfile),
|
||||
escapeshellarg($clientkey_pubdata)
|
||||
);
|
||||
self::_mtn_exec($cmd);
|
||||
$this->_mtn_exec($cmd);
|
||||
|
||||
//
|
||||
// step 4) setup the configuration
|
||||
@@ -238,18 +260,20 @@ class IDF_Plugin_SyncMonotone
|
||||
foreach ($confdir_contents as $content) {
|
||||
$filepath = $projectpath.'/'.$content;
|
||||
if (substr($content, -1) == '/') {
|
||||
if (!mkdir($filepath)) {
|
||||
throw new IDF_Scm_Exception(sprintf(
|
||||
__('Could not create configuration directory "%s"'), $filepath
|
||||
if (!@mkdir($filepath)) {
|
||||
$this->_diagnoseProblem(sprintf(
|
||||
__('Could not create configuration directory "%s"'),
|
||||
$filepath
|
||||
));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (substr($content, -3) != '.in') {
|
||||
if (!symlink($confdir.$content, $filepath)) {
|
||||
IDF_Scm_Exception(sprintf(
|
||||
__('Could not create symlink "%s"'), $filepath
|
||||
if (!@symlink($confdir.$content, $filepath)) {
|
||||
$this->_diagnoseProblem(sprintf(
|
||||
__('Could not create symlink for configuration file "%s"'),
|
||||
$filepath
|
||||
));
|
||||
}
|
||||
continue;
|
||||
@@ -264,9 +288,10 @@ class IDF_Plugin_SyncMonotone
|
||||
|
||||
// remove the .in
|
||||
$filepath = substr($filepath, 0, -3);
|
||||
if (file_put_contents($filepath, $filecontents, LOCK_EX) === false) {
|
||||
throw new IDF_Scm_Exception(sprintf(
|
||||
__('Could not write configuration file "%s"'), $filepath
|
||||
if (@file_put_contents($filepath, $filecontents, LOCK_EX) === false) {
|
||||
$this->_diagnoseProblem(sprintf(
|
||||
__('Could not write configuration file "%s"'),
|
||||
$filepath
|
||||
));
|
||||
}
|
||||
}
|
||||
@@ -280,7 +305,7 @@ class IDF_Plugin_SyncMonotone
|
||||
$parsed_config = IDF_Scm_Monotone_BasicIO::parse($usher_rc);
|
||||
}
|
||||
catch (Exception $e) {
|
||||
throw new IDF_Scm_Exception(sprintf(
|
||||
$this->_diagnoseProblem(sprintf(
|
||||
__('Could not parse usher configuration in "%s": %s'),
|
||||
$usher_config, $e->getMessage()
|
||||
));
|
||||
@@ -291,7 +316,7 @@ class IDF_Plugin_SyncMonotone
|
||||
foreach ($stanzas as $stanza_line) {
|
||||
if ($stanza_line['key'] == 'server' &&
|
||||
$stanza_line['values'][0] == $shortname) {
|
||||
throw new IDF_Scm_Exception(sprintf(
|
||||
$this->_diagnoseProblem(sprintf(
|
||||
__('usher configuration already contains a server '.
|
||||
'entry named "%s"'),
|
||||
$shortname
|
||||
@@ -315,9 +340,10 @@ class IDF_Plugin_SyncMonotone
|
||||
|
||||
// FIXME: more sanity - what happens on failing writes? we do not
|
||||
// have a backup copy of usher.conf around...
|
||||
if (file_put_contents($usher_config, $usher_rc, LOCK_EX) === false) {
|
||||
throw new IDF_Scm_Exception(sprintf(
|
||||
__('Could not write usher configuration file "%s"'), $usher_config
|
||||
if (@file_put_contents($usher_config, $usher_rc, LOCK_EX) === false) {
|
||||
$this->_diagnoseProblem(sprintf(
|
||||
__('Could not write usher configuration file "%s"'),
|
||||
$usher_config
|
||||
));
|
||||
}
|
||||
|
||||
@@ -325,6 +351,9 @@ class IDF_Plugin_SyncMonotone
|
||||
// step 6) reload usher to pick up the new configuration
|
||||
//
|
||||
IDF_Scm_Monotone_Usher::reload();
|
||||
|
||||
// commit the guard, so the newly created project is not deleted
|
||||
$projectGuard->commit();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -345,8 +374,8 @@ class IDF_Plugin_SyncMonotone
|
||||
$mtn = IDF_Scm_Monotone::factory($project);
|
||||
$stdio = $mtn->getStdio();
|
||||
|
||||
$projectpath = self::_get_project_path($project);
|
||||
$auth_ids = self::_get_authorized_user_ids($project);
|
||||
$projectpath = $this->_get_project_path($project);
|
||||
$auth_ids = $this->_get_authorized_user_ids($project);
|
||||
$key_ids = array();
|
||||
foreach ($auth_ids as $auth_id) {
|
||||
$sql = new Pluf_SQL('user=%s', array($auth_id));
|
||||
@@ -361,9 +390,10 @@ class IDF_Plugin_SyncMonotone
|
||||
|
||||
$write_permissions = implode("\n", $key_ids);
|
||||
$rcfile = $projectpath.'/write-permissions';
|
||||
if (file_put_contents($rcfile, $write_permissions, LOCK_EX) === false) {
|
||||
throw new IDF_Scm_Exception(sprintf(
|
||||
__('Could not write write-permissions file "%s"'), $rcfile
|
||||
if (@file_put_contents($rcfile, $write_permissions, LOCK_EX) === false) {
|
||||
$this->_diagnoseProblem(sprintf(
|
||||
__('Could not write write-permissions file "%s"'),
|
||||
$rcfile
|
||||
));
|
||||
}
|
||||
|
||||
@@ -382,11 +412,13 @@ class IDF_Plugin_SyncMonotone
|
||||
array('key' => 'allow', 'values' => array('*')),
|
||||
);
|
||||
}
|
||||
|
||||
$read_permissions = IDF_Scm_Monotone_BasicIO::compile(array($stanza));
|
||||
$rcfile = $projectpath.'/read-permissions';
|
||||
if (file_put_contents($rcfile, $read_permissions, LOCK_EX) === false) {
|
||||
throw new IDF_Scm_Exception(sprintf(
|
||||
__('Could not write read-permissions file "%s"'), $rcfile
|
||||
if (@file_put_contents($rcfile, $read_permissions, LOCK_EX) === false) {
|
||||
$this->_diagnoseProblem(sprintf(
|
||||
__('Could not write read-permissions file "%s"'),
|
||||
$rcfile
|
||||
));
|
||||
}
|
||||
|
||||
@@ -401,16 +433,16 @@ class IDF_Plugin_SyncMonotone
|
||||
|
||||
$serverRestartRequired = false;
|
||||
if ($project->private && file_exists($projectfile) && is_link($projectfile)) {
|
||||
if (!unlink($projectfile)) {
|
||||
IDF_Scm_Exception(sprintf(
|
||||
if (!@unlink($projectfile)) {
|
||||
$this->_diagnoseProblem(sprintf(
|
||||
__('Could not remove symlink "%s"'), $projectfile
|
||||
));
|
||||
}
|
||||
$serverRestartRequired = true;
|
||||
} else
|
||||
if (!$project->private && !file_exists($projectfile)) {
|
||||
if (!symlink($templatefile, $projectfile)) {
|
||||
throw new IDF_Scm_Exception(sprintf(
|
||||
if (!@symlink($templatefile, $projectfile)) {
|
||||
$this->_diagnoseProblem(sprintf(
|
||||
__('Could not create symlink "%s"'), $projectfile
|
||||
));
|
||||
}
|
||||
@@ -422,6 +454,9 @@ class IDF_Plugin_SyncMonotone
|
||||
// seems to be ignored when the server should be started
|
||||
// again immediately afterwards
|
||||
IDF_Scm_Monotone_Usher::killServer($project->shortname);
|
||||
// give usher some time to cool down, otherwise it might hang
|
||||
// (see https://code.monotone.ca/p/contrib/issues/175/)
|
||||
sleep(2);
|
||||
IDF_Scm_Monotone_Usher::startServer($project->shortname);
|
||||
}
|
||||
}
|
||||
@@ -443,8 +478,8 @@ class IDF_Plugin_SyncMonotone
|
||||
|
||||
$usher_config = Pluf::f('mtn_usher_conf', false);
|
||||
if (!$usher_config || !is_writable($usher_config)) {
|
||||
throw new IDF_Scm_Exception(
|
||||
__('"mtn_usher_conf" does not exist or is not writable.')
|
||||
$this->_diagnoseProblem(
|
||||
__('"mtn_usher_conf" does not exist or is not writable')
|
||||
);
|
||||
}
|
||||
|
||||
@@ -453,16 +488,16 @@ class IDF_Plugin_SyncMonotone
|
||||
|
||||
$projecttempl = Pluf::f('mtn_repositories', false);
|
||||
if ($projecttempl === false) {
|
||||
throw new IDF_Scm_Exception(
|
||||
__('"mtn_repositories" must be defined in your configuration file.')
|
||||
$this->_diagnoseProblem(
|
||||
__('"mtn_repositories" must be defined in your configuration file')
|
||||
);
|
||||
}
|
||||
|
||||
$projectpath = sprintf($projecttempl, $shortname);
|
||||
if (file_exists($projectpath)) {
|
||||
if (!self::_delete_recursive($projectpath)) {
|
||||
throw new IDF_Scm_Exception(sprintf(
|
||||
__('One or more paths underknees %s could not be deleted.'), $projectpath
|
||||
if (!$this->_delete_recursive($projectpath)) {
|
||||
$this->_diagnoseProblem(sprintf(
|
||||
__('One or more paths underneath %s could not be deleted'), $projectpath
|
||||
));
|
||||
}
|
||||
}
|
||||
@@ -473,8 +508,9 @@ class IDF_Plugin_SyncMonotone
|
||||
if ($keyname && $keyhash &&
|
||||
file_exists($keydir .'/'. $keyname . '.' . $keyhash)) {
|
||||
if (!@unlink($keydir .'/'. $keyname . '.' . $keyhash)) {
|
||||
throw new IDF_Scm_Exception(sprintf(
|
||||
__('Could not delete client private key %s'), $keyname
|
||||
$this->_diagnoseProblem(sprintf(
|
||||
__('Could not delete client private key "%s"'),
|
||||
$keyname
|
||||
));
|
||||
}
|
||||
}
|
||||
@@ -485,7 +521,7 @@ class IDF_Plugin_SyncMonotone
|
||||
$parsed_config = IDF_Scm_Monotone_BasicIO::parse($usher_rc);
|
||||
}
|
||||
catch (Exception $e) {
|
||||
throw new IDF_Scm_Exception(sprintf(
|
||||
$this->_diagnoseProblem(sprintf(
|
||||
__('Could not parse usher configuration in "%s": %s'),
|
||||
$usher_config, $e->getMessage()
|
||||
));
|
||||
@@ -505,9 +541,10 @@ class IDF_Plugin_SyncMonotone
|
||||
|
||||
// FIXME: more sanity - what happens on failing writes? we do not
|
||||
// have a backup copy of usher.conf around...
|
||||
if (file_put_contents($usher_config, $usher_rc, LOCK_EX) === false) {
|
||||
throw new IDF_Scm_Exception(sprintf(
|
||||
__('Could not write usher configuration file "%s"'), $usher_config
|
||||
if (@file_put_contents($usher_config, $usher_rc, LOCK_EX) === false) {
|
||||
$this->_diagnoseProblem(sprintf(
|
||||
__('Could not write usher configuration file "%s"'),
|
||||
$usher_config
|
||||
));
|
||||
}
|
||||
|
||||
@@ -528,6 +565,8 @@ class IDF_Plugin_SyncMonotone
|
||||
return;
|
||||
}
|
||||
|
||||
$keyGuard = new IDF_Plugin_SyncMonotone_ModelGuard($key);
|
||||
|
||||
foreach (Pluf::factory('IDF_Project')->getList() as $project) {
|
||||
$conf = new IDF_Conf();
|
||||
$conf->setProject($project);
|
||||
@@ -535,8 +574,8 @@ class IDF_Plugin_SyncMonotone
|
||||
if ($scm != 'mtn')
|
||||
continue;
|
||||
|
||||
$projectpath = self::_get_project_path($project);
|
||||
$auth_ids = self::_get_authorized_user_ids($project);
|
||||
$projectpath = $this->_get_project_path($project);
|
||||
$auth_ids = $this->_get_authorized_user_ids($project);
|
||||
if (!in_array($key->user, $auth_ids))
|
||||
continue;
|
||||
|
||||
@@ -556,7 +595,7 @@ class IDF_Plugin_SyncMonotone
|
||||
$parsed_read_perms = IDF_Scm_Monotone_BasicIO::parse($read_perms);
|
||||
}
|
||||
catch (Exception $e) {
|
||||
throw new IDF_Scm_Exception(sprintf(
|
||||
$this->_diagnoseProblem(sprintf(
|
||||
__('Could not parse read-permissions for project "%s": %s'),
|
||||
$shortname, $e->getMessage()
|
||||
));
|
||||
@@ -598,10 +637,11 @@ class IDF_Plugin_SyncMonotone
|
||||
|
||||
$read_perms = IDF_Scm_Monotone_BasicIO::compile($parsed_read_perms);
|
||||
|
||||
if (file_put_contents($projectpath.'/read-permissions',
|
||||
if (@file_put_contents($projectpath.'/read-permissions',
|
||||
$read_perms, LOCK_EX) === false) {
|
||||
throw new IDF_Scm_Exception(sprintf(
|
||||
__('Could not write read-permissions for project "%s"'), $shortname
|
||||
$this->_diagnoseProblem(sprintf(
|
||||
__('Could not write read-permissions for project "%s"'),
|
||||
$shortname
|
||||
));
|
||||
}
|
||||
}
|
||||
@@ -611,9 +651,9 @@ class IDF_Plugin_SyncMonotone
|
||||
if (!in_array('*', $lines) && !in_array($mtn_key_id, $lines)) {
|
||||
$lines[] = $mtn_key_id;
|
||||
}
|
||||
if (file_put_contents($projectpath.'/write-permissions',
|
||||
if (@file_put_contents($projectpath.'/write-permissions',
|
||||
implode("\n", $lines) . "\n", LOCK_EX) === false) {
|
||||
throw new IDF_Scm_Exception(sprintf(
|
||||
$this->_diagnoseProblem(sprintf(
|
||||
__('Could not write write-permissions file for project "%s"'),
|
||||
$shortname
|
||||
));
|
||||
@@ -623,6 +663,8 @@ class IDF_Plugin_SyncMonotone
|
||||
$stdio = $mtn->getStdio();
|
||||
$stdio->exec(array('put_public_key', $key->content));
|
||||
}
|
||||
|
||||
$keyGuard->commit();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -651,8 +693,8 @@ class IDF_Plugin_SyncMonotone
|
||||
if ($scm != 'mtn')
|
||||
continue;
|
||||
|
||||
$projectpath = self::_get_project_path($project);
|
||||
$auth_ids = self::_get_authorized_user_ids($project);
|
||||
$projectpath = $this->_get_project_path($project);
|
||||
$auth_ids = $this->_get_authorized_user_ids($project);
|
||||
if (!in_array($key->user, $auth_ids))
|
||||
continue;
|
||||
|
||||
@@ -672,7 +714,7 @@ class IDF_Plugin_SyncMonotone
|
||||
$parsed_read_perms = IDF_Scm_Monotone_BasicIO::parse($read_perms);
|
||||
}
|
||||
catch (Exception $e) {
|
||||
throw new IDF_Scm_Exception(sprintf(
|
||||
$this->_diagnoseProblem(sprintf(
|
||||
__('Could not parse read-permissions for project "%s": %s'),
|
||||
$shortname, $e->getMessage()
|
||||
));
|
||||
@@ -693,10 +735,11 @@ class IDF_Plugin_SyncMonotone
|
||||
|
||||
$read_perms = IDF_Scm_Monotone_BasicIO::compile($parsed_read_perms);
|
||||
|
||||
if (file_put_contents($projectpath.'/read-permissions',
|
||||
if (@file_put_contents($projectpath.'/read-permissions',
|
||||
$read_perms, LOCK_EX) === false) {
|
||||
throw new IDF_Scm_Exception(sprintf(
|
||||
__('Could not write read-permissions for project "%s"'), $shortname
|
||||
$this->_diagnoseProblem(sprintf(
|
||||
__('Could not write read-permissions for project "%s"'),
|
||||
$shortname
|
||||
));
|
||||
}
|
||||
}
|
||||
@@ -711,9 +754,9 @@ class IDF_Plugin_SyncMonotone
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (file_put_contents($projectpath.'/write-permissions',
|
||||
implode("\n", $lines) . "\n", LOCK_EX) === false) {
|
||||
throw new IDF_Scm_Exception(sprintf(
|
||||
if (@file_put_contents($projectpath.'/write-permissions',
|
||||
implode("\n", $lines) . "\n", LOCK_EX) === false) {
|
||||
$this->_diagnoseProblem(sprintf(
|
||||
__('Could not write write-permissions file for project "%s"'),
|
||||
$shortname
|
||||
));
|
||||
@@ -762,7 +805,43 @@ class IDF_Plugin_SyncMonotone
|
||||
));
|
||||
}
|
||||
|
||||
private static function _get_authorized_user_ids($project)
|
||||
private function _get_project_path($project)
|
||||
{
|
||||
$projecttempl = Pluf::f('mtn_repositories', false);
|
||||
if ($projecttempl === false) {
|
||||
$this->_diagnoseProblem(
|
||||
__('"mtn_repositories" must be defined in your configuration file.')
|
||||
);
|
||||
}
|
||||
|
||||
$projectpath = sprintf($projecttempl, $project->shortname);
|
||||
if (!file_exists($projectpath)) {
|
||||
$this->_diagnoseProblem(sprintf(
|
||||
__('The project path %s does not exists.'), $projectpath
|
||||
));
|
||||
}
|
||||
return $projectpath;
|
||||
}
|
||||
|
||||
private function _mtn_exec($cmd)
|
||||
{
|
||||
$fullcmd = sprintf('%s %s %s',
|
||||
Pluf::f('idf_exec_cmd_prefix', ''),
|
||||
Pluf::f('mtn_path', 'mtn'),
|
||||
$cmd
|
||||
);
|
||||
|
||||
$output = $return = null;
|
||||
exec($fullcmd, $output, $return);
|
||||
if ($return != 0) {
|
||||
$this->_diagnoseProblem(sprintf(
|
||||
__('The command "%s" could not be executed.'), $cmd
|
||||
));
|
||||
}
|
||||
return implode("\n", $output);
|
||||
}
|
||||
|
||||
private function _get_authorized_user_ids($project)
|
||||
{
|
||||
$mem = $project->getMembershipData();
|
||||
$members = array_merge((array)$mem['members'],
|
||||
@@ -775,43 +854,7 @@ class IDF_Plugin_SyncMonotone
|
||||
return $userids;
|
||||
}
|
||||
|
||||
private static function _get_project_path($project)
|
||||
{
|
||||
$projecttempl = Pluf::f('mtn_repositories', false);
|
||||
if ($projecttempl === false) {
|
||||
throw new IDF_Scm_Exception(
|
||||
__('"mtn_repositories" must be defined in your configuration file.')
|
||||
);
|
||||
}
|
||||
|
||||
$projectpath = sprintf($projecttempl, $project->shortname);
|
||||
if (!file_exists($projectpath)) {
|
||||
throw new IDF_Scm_Exception(sprintf(
|
||||
__('The project path %s does not exists.'), $projectpath
|
||||
));
|
||||
}
|
||||
return $projectpath;
|
||||
}
|
||||
|
||||
private static function _mtn_exec($cmd)
|
||||
{
|
||||
$fullcmd = sprintf('%s %s %s',
|
||||
Pluf::f('idf_exec_cmd_prefix', ''),
|
||||
Pluf::f('mtn_path', 'mtn'),
|
||||
$cmd
|
||||
);
|
||||
|
||||
$output = $return = null;
|
||||
exec($fullcmd, $output, $return);
|
||||
if ($return != 0) {
|
||||
throw new IDF_Scm_Exception(sprintf(
|
||||
__('The command "%s" could not be executed.'), $cmd
|
||||
));
|
||||
}
|
||||
return implode("\n", $output);
|
||||
}
|
||||
|
||||
private static function _delete_recursive($path)
|
||||
private function _delete_recursive($path)
|
||||
{
|
||||
if (is_file($path) || is_link($path)) {
|
||||
return @unlink($path);
|
||||
@@ -821,10 +864,48 @@ class IDF_Plugin_SyncMonotone
|
||||
$scan = glob(rtrim($path, '/') . '/*');
|
||||
$status = 0;
|
||||
foreach ($scan as $subpath) {
|
||||
$status |= self::_delete_recursive($subpath);
|
||||
$status |= $this->_delete_recursive($subpath);
|
||||
}
|
||||
$status |= rmdir($path);
|
||||
$status |= @rmdir($path);
|
||||
return $status;
|
||||
}
|
||||
}
|
||||
|
||||
private function _diagnoseProblem($msg)
|
||||
{
|
||||
$system_err = error_get_last();
|
||||
if (!empty($system_err)) {
|
||||
$msg .= ': '.$system_err['message'];
|
||||
}
|
||||
|
||||
error_reporting($this->old_err_rep);
|
||||
throw new IDF_Scm_Exception($msg);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A simple helper class that deletes the model instance if
|
||||
* it is not committed
|
||||
*/
|
||||
class IDF_Plugin_SyncMonotone_ModelGuard
|
||||
{
|
||||
private $model;
|
||||
|
||||
public function __construct(Pluf_Model $m)
|
||||
{
|
||||
$this->model = $m;
|
||||
}
|
||||
|
||||
public function __destruct()
|
||||
{
|
||||
if ($this->model == null)
|
||||
return;
|
||||
$this->model->delete();
|
||||
}
|
||||
|
||||
public function commit()
|
||||
{
|
||||
$this->model = null;
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -132,6 +132,47 @@ class IDF_Project extends Pluf_Model
|
||||
}
|
||||
return $projects[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of open/closed issues.
|
||||
*
|
||||
* @param string Status ('open'), 'closed'
|
||||
* @param IDF_Tag Subfilter with a label (null)
|
||||
* @return int Count
|
||||
*/
|
||||
public function getIssueCountByOwner($status='open')
|
||||
{
|
||||
switch ($status) {
|
||||
case 'open':
|
||||
$tags = implode(',', $this->getTagIdsByStatus('open'));
|
||||
break;
|
||||
case 'closed':
|
||||
default:
|
||||
$tags = implode(',', $this->getTagIdsByStatus('closed'));
|
||||
break;
|
||||
}
|
||||
$sqlIssueTable = Pluf::factory('IDF_Issue')->getSqlTable();
|
||||
$query = <<<"QUERY"
|
||||
SELECT uid AS id,COUNT(uid) AS nb
|
||||
FROM (
|
||||
SELECT COALESCE(owner, -1) AS uid
|
||||
FROM $sqlIssueTable
|
||||
WHERE status IN ($tags)
|
||||
) AS ff
|
||||
GROUP BY uid
|
||||
QUERY;
|
||||
$db = Pluf::db();
|
||||
$dbData = $db->select($query);
|
||||
$ownerStatistics = array();
|
||||
foreach ($dbData as $k => $v) {
|
||||
$key = ($v['id'] === '-1') ? null : $v['id'];
|
||||
$ownerStatistics[$key] = (int)$v['nb'];
|
||||
}
|
||||
|
||||
arsort($ownerStatistics);
|
||||
|
||||
return $ownerStatistics;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of open/closed issues.
|
||||
@@ -234,7 +275,10 @@ class IDF_Project extends Pluf_Model
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of relations which are available in this project
|
||||
* Returns a list of relations which are available in this project as
|
||||
* associative array. Each key-value pair marks a set of orthogonal
|
||||
* relations. To ease processing, each of these pairs is included twice
|
||||
* in the array, once as key1 => key2 and once as key2 => key1.
|
||||
*
|
||||
* @return array List of relation names
|
||||
*/
|
||||
@@ -244,7 +288,11 @@ class IDF_Project extends Pluf_Model
|
||||
$rel = $conf->getVal('issue_relations', IDF_Form_IssueTrackingConf::init_relations);
|
||||
$relations = array();
|
||||
foreach (preg_split("/\015\012|\015|\012/", $rel, -1, PREG_SPLIT_NO_EMPTY) as $s) {
|
||||
$relations = array_merge($relations, preg_split("/\s*,\s*/", $s, 2));
|
||||
$verbs = preg_split("/\s*,\s*/", $s, 2);
|
||||
if (count($verbs) == 1)
|
||||
$relations += array($verbs[0] => $verbs[0]);
|
||||
else
|
||||
$relations += array($verbs[0] => $verbs[1], $verbs[1] => $verbs[0]);
|
||||
}
|
||||
return $relations;
|
||||
}
|
||||
|
@@ -88,22 +88,36 @@ class IDF_Scm
|
||||
}
|
||||
|
||||
/**
|
||||
* Run exec and log some information.
|
||||
* Runs the given command and log some information.
|
||||
*
|
||||
* A previous version used plain exec(), but this should not be used
|
||||
* for various reasons, one being that this command does not preserve
|
||||
* trailing whitespace, which is essential for proper diff parsing.
|
||||
*
|
||||
* @param $caller Calling method
|
||||
* @param $cmd Command to run
|
||||
* @param &$out Array of output
|
||||
* @param &$return Return value
|
||||
* @return string Last line of the command
|
||||
*/
|
||||
public static function exec($caller, $cmd, &$out=null, &$return=null)
|
||||
{
|
||||
$return = -1;
|
||||
Pluf_Log::stime('timer');
|
||||
$ret = exec($cmd, $out, $return);
|
||||
$fp = popen($cmd, 'r');
|
||||
$buf = '';
|
||||
if ($fp !== false) {
|
||||
while (!feof($fp)) {
|
||||
$buf .= fread($fp, 1024);
|
||||
}
|
||||
$return = pclose($fp);
|
||||
}
|
||||
$out = preg_split('/\r\n|\r|\n/', $buf);
|
||||
$elem = count($out);
|
||||
if ($elem > 0 && $out[$elem-1] === '')
|
||||
unset($out[$elem-1]);
|
||||
Pluf_Log::perf(array($caller, $cmd, Pluf_Log::etime('timer', 'total_exec')));
|
||||
Pluf_Log::debug(array($caller, $cmd, $out));
|
||||
Pluf_Log::inc('exec_calls');
|
||||
return $ret;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -325,7 +339,8 @@ class IDF_Scm
|
||||
* stdClass object {
|
||||
* 'additions' => array('path/to/file', 'path/to/directory', ...),
|
||||
* 'deletions' => array('path/to/file', 'path/to/directory', ...),
|
||||
* 'renames' => array('old/path/to/file' => 'new/path/to/file', ...)
|
||||
* 'renames' => array('old/path/to/file' => 'new/path/to/file', ...),
|
||||
* 'copies' => array('path/to/source' => 'path/to/target', ...),
|
||||
* 'patches' => array('path/to/file', ...),
|
||||
* 'properties' => array('path/to/file' => array(
|
||||
* 'propname' => 'propvalue', 'deletedprop' => null, ...)
|
||||
|
@@ -67,6 +67,7 @@ class IDF_Scm_Git extends IDF_Scm
|
||||
'additions' => array(),
|
||||
'deletions' => array(),
|
||||
'renames' => array(),
|
||||
'copies' => array(),
|
||||
'patches' => array(),
|
||||
'properties' => array(),
|
||||
);
|
||||
@@ -209,7 +210,7 @@ class IDF_Scm_Git extends IDF_Scm
|
||||
return $this->cache['tags'];
|
||||
}
|
||||
$cmd = Pluf::f('idf_exec_cmd_prefix', '')
|
||||
.sprintf('GIT_DIR=%s %s for-each-ref --format="%%(taggerdate:iso)%%(committerdate:iso) %%(objectname) %%(refname)" refs/tags',
|
||||
.sprintf('GIT_DIR=%s %s for-each-ref --format="%%(objectname) %%(refname)" refs/tags',
|
||||
escapeshellarg($this->repo),
|
||||
Pluf::f('git_path', 'git'));
|
||||
self::exec('IDF_Scm_Git::getTags', $cmd, $out, $return);
|
||||
@@ -218,18 +219,15 @@ class IDF_Scm_Git extends IDF_Scm
|
||||
$cmd, $return,
|
||||
implode("\n", $out)));
|
||||
}
|
||||
rsort($out);
|
||||
$res = array();
|
||||
foreach ($out as $b) {
|
||||
$elts = explode(' ', $b, 5);
|
||||
$tag = substr(trim($elts[4]), 10);
|
||||
if (false !== strpos($tag, '/')) {
|
||||
$res[$elts[3]] = $b;
|
||||
} else {
|
||||
$res[$tag] = '';
|
||||
}
|
||||
$elts = explode(' ', $b, 2);
|
||||
$tag = substr(trim($elts[1]), 10); // Remove refs/tags/ prefix
|
||||
$res[$tag] = '';
|
||||
}
|
||||
krsort($res);
|
||||
$this->cache['tags'] = $res;
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
|
@@ -22,19 +22,77 @@
|
||||
# ***** END LICENSE BLOCK ***** */
|
||||
|
||||
/**
|
||||
* Mercurial utils.
|
||||
* A simple RAII helper that manages style files to format hg's log output
|
||||
*/
|
||||
class IDF_Scm_Mercurial_LogStyle
|
||||
{
|
||||
const FULL_LOG = 1;
|
||||
const CHANGES = 2;
|
||||
|
||||
public function __construct($type)
|
||||
{
|
||||
$this->file = tempnam(Pluf::f('tmp_folder'), 'hg-log-style-');
|
||||
|
||||
if ($type == self::FULL_LOG) {
|
||||
$style = 'changeset = "'
|
||||
. 'changeset: {node|short}\n'
|
||||
. 'branch: {branch}\n'
|
||||
. 'author: {author}\n'
|
||||
. 'date: {date|isodate}\n'
|
||||
. 'parents: {parents}\n\n'
|
||||
. '{desc}\n'
|
||||
. '\0\n"'
|
||||
. "\n"
|
||||
. 'parent = "{node|short} "'
|
||||
. "\n";
|
||||
} elseif ($type == self::CHANGES) {
|
||||
$style = 'changeset = "'
|
||||
. 'file_mods: {file_mods}\n'
|
||||
. 'file_adds: {file_adds}\n'
|
||||
. 'file_dels: {file_dels}\n'
|
||||
. 'file_copies: {file_copies}\n\n'
|
||||
. '\0\n"'
|
||||
. "\n"
|
||||
. 'file_mod = "{file_mod}\0"'
|
||||
. "\n"
|
||||
. 'file_add = "{file_add}\0"'
|
||||
. "\n"
|
||||
. 'file_del = "{file_del}\0"'
|
||||
. "\n"
|
||||
. 'file_copy = "{source}\0{name}\0"'
|
||||
. "\n";
|
||||
} else {
|
||||
throw new IDF_Scm_Exception('invalid type ' . $type);
|
||||
}
|
||||
|
||||
file_put_contents($this->file, $style);
|
||||
}
|
||||
|
||||
public function __destruct()
|
||||
{
|
||||
@unlink($this->file);
|
||||
}
|
||||
|
||||
public function get()
|
||||
{
|
||||
return $this->file;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Main SCM class for Mercurial
|
||||
*
|
||||
* Note: Some commands take a --debug option, this is not lousy coding, but
|
||||
* totally wanted, as hg returns additional / different data in this
|
||||
* mode on which this largely depends.
|
||||
*/
|
||||
class IDF_Scm_Mercurial extends IDF_Scm
|
||||
{
|
||||
protected $hg_log_template;
|
||||
|
||||
public function __construct($repo, $project=null)
|
||||
{
|
||||
$this->repo = $repo;
|
||||
$this->project = $project;
|
||||
$this->hg_log_template = "'".'changeset: {rev}:{node|short}\nauthor: {author}\ndate: {date|isodate}\nfiles: {files}\n{desc}\n'."'";
|
||||
}
|
||||
}
|
||||
|
||||
public function getRepositorySize()
|
||||
{
|
||||
@@ -158,7 +216,8 @@ class IDF_Scm_Mercurial extends IDF_Scm
|
||||
throw new Exception(sprintf(__('Not a valid tree: %s.'), $tree));
|
||||
}
|
||||
$cmd_tmpl = Pluf::f('hg_path', 'hg').' manifest -R %s --debug -r %s';
|
||||
$cmd = sprintf($cmd_tmpl, escapeshellarg($this->repo), $tree, ($recurse) ? '' : '');
|
||||
$cmd = sprintf($cmd_tmpl, escapeshellarg($this->repo),
|
||||
escapeshellarg($tree));
|
||||
$out = array();
|
||||
$res = array();
|
||||
$cmd = Pluf::f('idf_exec_cmd_prefix', '').$cmd;
|
||||
@@ -208,7 +267,8 @@ class IDF_Scm_Mercurial extends IDF_Scm
|
||||
public function getPathInfo($totest, $commit='tip')
|
||||
{
|
||||
$cmd_tmpl = Pluf::f('hg_path', 'hg').' manifest -R %s --debug -r %s';
|
||||
$cmd = sprintf($cmd_tmpl, escapeshellarg($this->repo), $commit);
|
||||
$cmd = sprintf($cmd_tmpl, escapeshellarg($this->repo),
|
||||
escapeshellarg($commit));
|
||||
$out = array();
|
||||
$cmd = Pluf::f('idf_exec_cmd_prefix', '').$cmd;
|
||||
self::exec('IDF_Scm_Mercurial::getPathInfo', $cmd, $out);
|
||||
@@ -284,7 +344,7 @@ class IDF_Scm_Mercurial extends IDF_Scm
|
||||
self::exec('IDF_Scm_Mercurial::getBranches', $cmd, $out);
|
||||
$res = array();
|
||||
foreach ($out as $b) {
|
||||
preg_match('/(\S+).*\S+:(\S+)/', $b, $match);
|
||||
preg_match('/(.+?)\s+\S+:(\S+)/', $b, $match);
|
||||
$res[$match[1]] = '';
|
||||
}
|
||||
$this->cache['branches'] = $res;
|
||||
@@ -308,7 +368,7 @@ class IDF_Scm_Mercurial extends IDF_Scm
|
||||
self::exec('IDF_Scm_Mercurial::getTags', $cmd, $out);
|
||||
$res = array();
|
||||
foreach ($out as $b) {
|
||||
preg_match('/(\S+).*\S+:(\S+)/', $b, $match);
|
||||
preg_match('/(.+?)\s+\S+:(\S+)/', $b, $match);
|
||||
$res[$match[1]] = '';
|
||||
}
|
||||
$this->cache['tags'] = $res;
|
||||
@@ -339,14 +399,15 @@ class IDF_Scm_Mercurial extends IDF_Scm
|
||||
if ($this->validateRevision($commit) != IDF_Scm::REVISION_VALID) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$logStyle = new IDF_Scm_Mercurial_LogStyle(IDF_Scm_Mercurial_LogStyle::FULL_LOG);
|
||||
$tmpl = ($getdiff)
|
||||
? Pluf::f('hg_path', 'hg').' log -p -r %s -R %s --template %s'
|
||||
: Pluf::f('hg_path', 'hg').' log -r %s -R %s --template %s';
|
||||
? Pluf::f('hg_path', 'hg').' log --debug -p -r %s -R %s --style %s'
|
||||
: Pluf::f('hg_path', 'hg').' log --debug -r %s -R %s --style %s';
|
||||
$cmd = sprintf($tmpl,
|
||||
escapeshellarg($commit),
|
||||
escapeshellarg($this->repo),
|
||||
$this->hg_log_template);
|
||||
|
||||
escapeshellarg($logStyle->get()));
|
||||
$out = array();
|
||||
$cmd = Pluf::f('idf_exec_cmd_prefix', '').$cmd;
|
||||
self::exec('IDF_Scm_Mercurial::getCommit', $cmd, $out);
|
||||
@@ -363,11 +424,70 @@ class IDF_Scm_Mercurial extends IDF_Scm
|
||||
$log[] = $line;
|
||||
}
|
||||
}
|
||||
$out = self::parseLog($log, 4);
|
||||
$out = self::parseLog($log);
|
||||
$out[0]->diff = implode("\n", $change);
|
||||
return $out[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* @see IDF_Scm::getChanges()
|
||||
*/
|
||||
public function getChanges($commit)
|
||||
{
|
||||
if ($this->validateRevision($commit) != IDF_Scm::REVISION_VALID) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$logStyle = new IDF_Scm_Mercurial_LogStyle(IDF_Scm_Mercurial_LogStyle::CHANGES);
|
||||
$tmpl = Pluf::f('hg_path', 'hg').' log --debug -r %s -R %s --style %s';
|
||||
$cmd = sprintf($tmpl,
|
||||
escapeshellarg($commit),
|
||||
escapeshellarg($this->repo),
|
||||
escapeshellarg($logStyle->get()));
|
||||
$out = array();
|
||||
$cmd = Pluf::f('idf_exec_cmd_prefix', '').$cmd;
|
||||
self::exec('IDF_Scm_Mercurial::getChanges', $cmd, $out);
|
||||
$log = self::parseLog($out);
|
||||
// we expect only one log entry that contains all the needed information
|
||||
$log = $log[0];
|
||||
|
||||
$return = (object) array(
|
||||
'additions' => preg_split('/\0/', $log->file_adds, -1, PREG_SPLIT_NO_EMPTY),
|
||||
'deletions' => preg_split('/\0/', $log->file_dels, -1, PREG_SPLIT_NO_EMPTY),
|
||||
'patches' => preg_split('/\0/', $log->file_mods, -1, PREG_SPLIT_NO_EMPTY),
|
||||
// hg has no support for built-in attributes, so this keeps empty
|
||||
'properties' => array(),
|
||||
// these two are filled below
|
||||
'copies' => array(),
|
||||
'renames' => array(),
|
||||
);
|
||||
|
||||
$file_copies = preg_split('/\0/', $log->file_copies, -1, PREG_SPLIT_NO_EMPTY);
|
||||
|
||||
// copies are treated as renames if they have an add _and_ a drop;
|
||||
// only if they only have an add, but no drop, they're treated as copies
|
||||
for ($i=0; $i<count($file_copies); $i+=2) {
|
||||
$src = $file_copies[$i];
|
||||
$trg = $file_copies[$i+1];
|
||||
$srcidx = array_search($src, $return->deletions);
|
||||
$trgidx = array_search($trg, $return->additions);
|
||||
if ($srcidx !== false && $trgidx !== false) {
|
||||
$return->renames[$src] = $trg;
|
||||
unset($return->deletions[$srcidx]);
|
||||
unset($return->additions[$trgidx]);
|
||||
continue;
|
||||
}
|
||||
if ($srcidx === false && $trgidx !== false) {
|
||||
$return->copies[$src] = $trg;
|
||||
unset($return->additions[$trgidx]);
|
||||
continue;
|
||||
}
|
||||
// file sutures (counter-operation to copy) not supported
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a commit is big.
|
||||
*
|
||||
@@ -388,54 +508,65 @@ class IDF_Scm_Mercurial extends IDF_Scm
|
||||
*/
|
||||
public function getChangeLog($commit='tip', $n=10)
|
||||
{
|
||||
$cmd = sprintf(Pluf::f('hg_path', 'hg').' log -R %s -l%s --template %s', escapeshellarg($this->repo), $n, $this->hg_log_template, $commit);
|
||||
$logStyle = new IDF_Scm_Mercurial_LogStyle(IDF_Scm_Mercurial_LogStyle::FULL_LOG);
|
||||
|
||||
// hg accepts revision IDs as arguments to --branch / -b as well and
|
||||
// uses the branch of the revision in question to filter the other
|
||||
// revisions
|
||||
$cmd = sprintf(Pluf::f('hg_path', 'hg').' log --debug -R %s -l%s --style %s -b %s',
|
||||
escapeshellarg($this->repo),
|
||||
$n,
|
||||
escapeshellarg($logStyle->get()),
|
||||
escapeshellarg($commit));
|
||||
$out = array();
|
||||
$cmd = Pluf::f('idf_exec_cmd_prefix', '').$cmd;
|
||||
self::exec('IDF_Scm_Mercurial::getChangeLog', $cmd, $out);
|
||||
return self::parseLog($out, 4);
|
||||
return self::parseLog($out);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the log lines of a --pretty=medium log output.
|
||||
* Parse the log lines of our custom style format.
|
||||
*
|
||||
* @param array Lines.
|
||||
* @param int Number of lines in the headers (3)
|
||||
* @return array Change log.
|
||||
*/
|
||||
|
||||
public static function parseLog($lines, $hdrs=3)
|
||||
public static function parseLog($lines)
|
||||
{
|
||||
$res = array();
|
||||
$c = array();
|
||||
$i = 0;
|
||||
$hdrs += 1;
|
||||
$headers_processed = false;
|
||||
foreach ($lines as $line) {
|
||||
$i++;
|
||||
if (0 === strpos($line, 'changeset:')) {
|
||||
if ($line == "\0") {
|
||||
$headers_processed = false;
|
||||
if (count($c) > 0) {
|
||||
$c['full_message'] = trim($c['full_message']);
|
||||
if (array_key_exists('full_message', $c))
|
||||
$c['full_message'] = trim($c['full_message']);
|
||||
$res[] = (object) $c;
|
||||
}
|
||||
$c = array();
|
||||
$c['commit'] = substr(strrchr($line, ':'), 1);
|
||||
$c['full_message'] = '';
|
||||
$i=1;
|
||||
continue;
|
||||
|
||||
}
|
||||
if ($i == $hdrs) {
|
||||
$c['title'] = trim($line);
|
||||
continue;
|
||||
}
|
||||
$match = array();
|
||||
if (preg_match('/^(\S+):\s*(.*)/', $line, $match)) {
|
||||
if (!$headers_processed && empty($line)) {
|
||||
$headers_processed = true;
|
||||
continue;
|
||||
}
|
||||
if (!$headers_processed && preg_match('/^(\S+):\s*(.*)/', $line, $match)) {
|
||||
$match[1] = strtolower($match[1]);
|
||||
if ($match[1] == 'user') {
|
||||
if ($match[1] == 'changeset') {
|
||||
$c = array();
|
||||
$c['commit'] = $match[2];
|
||||
$c['tree'] = $c['commit'];
|
||||
$c['full_message'] = '';
|
||||
} elseif ($match[1] == 'author') {
|
||||
$c['author'] = $match[2];
|
||||
} elseif ($match[1] == 'summary') {
|
||||
$c['title'] = $match[2];
|
||||
} elseif ($match[1] == 'branch') {
|
||||
$c['branch'] = $match[2];
|
||||
$c['branch'] = empty($match[2]) ? 'default' : $match[2];
|
||||
} elseif ($match[1] == 'parents') {
|
||||
$parents = preg_split('/\s+/', $match[2], -1, PREG_SPLIT_NO_EMPTY);
|
||||
for ($i=0, $j=count($parents); $i<$j; ++$i) {
|
||||
if ($parents[$i] == '000000000000')
|
||||
unset($parents[$i]);
|
||||
}
|
||||
$c['parents'] = $parents;
|
||||
} else {
|
||||
$c[$match[1]] = trim($match[2]);
|
||||
}
|
||||
@@ -444,15 +575,14 @@ class IDF_Scm_Mercurial extends IDF_Scm
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if ($i > ($hdrs+1)) {
|
||||
$c['full_message'] .= trim($line)."\n";
|
||||
if ($headers_processed) {
|
||||
if (empty($c['title']))
|
||||
$c['title'] = trim($line);
|
||||
else
|
||||
$c['full_message'] .= trim($line)."\n";
|
||||
continue;
|
||||
}
|
||||
}
|
||||
$c['tree'] = !empty($c['commit']) ? trim($c['commit']) : '';
|
||||
$c['branch'] = empty($c['branch']) ? 'default' : $c['branch'];
|
||||
$c['full_message'] = !empty($c['full_message']) ? trim($c['full_message']) : '';
|
||||
$res[] = (object) $c;
|
||||
return $res;
|
||||
}
|
||||
|
||||
|
@@ -31,10 +31,10 @@ class IDF_Scm_Monotone extends IDF_Scm
|
||||
/** the minimum supported interface version */
|
||||
public static $MIN_INTERFACE_VERSION = 13.0;
|
||||
|
||||
private $stdio;
|
||||
|
||||
private static $instances = array();
|
||||
|
||||
private $stdio;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
@@ -609,6 +609,7 @@ class IDF_Scm_Monotone extends IDF_Scm
|
||||
'additions' => array(),
|
||||
'deletions' => array(),
|
||||
'renames' => array(),
|
||||
'copies' => array(),
|
||||
'patches' => array(),
|
||||
'properties' => array(),
|
||||
);
|
||||
@@ -698,6 +699,29 @@ class IDF_Scm_Monotone extends IDF_Scm
|
||||
return (object) $res;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see IDF_Scm::getProperties()
|
||||
*/
|
||||
public function getProperties($rev, $path='')
|
||||
{
|
||||
$out = $this->stdio->exec(array('interface_version'));
|
||||
// support for querying file attributes of committed revisions
|
||||
// was added for mtn 1.1 (interface version 13.1)
|
||||
if (floatval($out) < 13.1)
|
||||
return array();
|
||||
|
||||
$out = $this->stdio->exec(array('get_attributes', $path), array('r' => $rev));
|
||||
$stanzas = IDF_Scm_Monotone_BasicIO::parse($out);
|
||||
$res = array();
|
||||
|
||||
foreach ($stanzas as $stanza) {
|
||||
$line = $stanza[0];
|
||||
$res[$line['values'][0]] = $line['values'][1];
|
||||
}
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see IDF_Scm::getExtraProperties
|
||||
*/
|
||||
|
@@ -48,7 +48,7 @@ class IDF_Scm_Monotone_Usher
|
||||
if ($conn == 'none')
|
||||
return array();
|
||||
|
||||
return preg_split('/[ ]/', $conn);
|
||||
return preg_split('/[ ]/', $conn, -1, PREG_SPLIT_NO_EMPTY);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -73,10 +73,10 @@ class IDF_Scm_Monotone_Usher
|
||||
if ($conn == 'none')
|
||||
return array();
|
||||
|
||||
$single_conns = preg_split('/[ ]/', $conn);
|
||||
$single_conns = preg_split('/[ ]/', $conn, -1, PREG_SPLIT_NO_EMPTY);
|
||||
$ret = array();
|
||||
foreach ($single_conns as $conn) {
|
||||
preg_match('/\((\w+)\)([^:]+):(\d+)/', $conn, $matches);
|
||||
preg_match('/\(([^)]+)\)([^:]+):(\d+)/', $conn, $matches);
|
||||
$ret[$matches[1]][] = (object)array(
|
||||
'server' => $matches[1],
|
||||
'address' => $matches[2],
|
||||
|
@@ -48,7 +48,7 @@ class IDF_Scm_Svn extends IDF_Scm
|
||||
|
||||
public function isAvailable()
|
||||
{
|
||||
$cmd = sprintf(Pluf::f('svn_path', 'svn').' info --xml --username=%s --password=%s %s',
|
||||
$cmd = sprintf(Pluf::f('svn_path', 'svn').' info --no-auth-cache --xml --username=%s --password=%s %s',
|
||||
escapeshellarg($this->username),
|
||||
escapeshellarg($this->password),
|
||||
escapeshellarg($this->repo));
|
||||
@@ -163,11 +163,11 @@ class IDF_Scm_Svn extends IDF_Scm
|
||||
return IDF_Scm::REVISION_VALID;
|
||||
}
|
||||
|
||||
$cmd = sprintf(Pluf::f('svn_path', 'svn').' info --username=%s --password=%s %s@%s',
|
||||
$cmd = sprintf(Pluf::f('svn_path', 'svn').' info --no-auth-cache --username=%s --password=%s --revision=%s %s',
|
||||
escapeshellarg($this->username),
|
||||
escapeshellarg($this->password),
|
||||
escapeshellarg($this->repo),
|
||||
escapeshellarg($rev));
|
||||
escapeshellarg($rev),
|
||||
escapeshellarg($this->repo));
|
||||
$cmd = Pluf::f('idf_exec_cmd_prefix', '').$cmd;
|
||||
self::exec('IDF_Scm_Svn::validateRevision', $cmd, $out, $ret);
|
||||
|
||||
@@ -176,7 +176,6 @@ class IDF_Scm_Svn extends IDF_Scm
|
||||
return IDF_Scm::REVISION_INVALID;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Test a given object hash.
|
||||
*
|
||||
@@ -191,11 +190,11 @@ class IDF_Scm_Svn extends IDF_Scm
|
||||
}
|
||||
|
||||
// Else, test the path on revision
|
||||
$cmd = sprintf(Pluf::f('svn_path', 'svn').' info --xml --username=%s --password=%s %s@%s',
|
||||
$cmd = sprintf(Pluf::f('svn_path', 'svn').' info --no-auth-cache --xml --username=%s --password=%s --revision=%s %s',
|
||||
escapeshellarg($this->username),
|
||||
escapeshellarg($this->password),
|
||||
escapeshellarg($this->repo.'/'.self::smartEncode($path)),
|
||||
escapeshellarg($rev));
|
||||
escapeshellarg($rev),
|
||||
escapeshellarg($this->repo.'/'.self::smartEncode($path)));
|
||||
$cmd = Pluf::f('idf_exec_cmd_prefix', '').$cmd;
|
||||
$xmlInfo = self::shell_exec('IDF_Scm_Svn::testHash', $cmd);
|
||||
|
||||
@@ -218,11 +217,11 @@ class IDF_Scm_Svn extends IDF_Scm
|
||||
|
||||
public function getTree($commit, $folder='/', $branch=null)
|
||||
{
|
||||
$cmd = sprintf(Pluf::f('svn_path', 'svn').' ls --xml --username=%s --password=%s %s@%s',
|
||||
$cmd = sprintf(Pluf::f('svn_path', 'svn').' ls --no-auth-cache --xml --username=%s --password=%s --revision=%s %s',
|
||||
escapeshellarg($this->username),
|
||||
escapeshellarg($this->password),
|
||||
escapeshellarg($this->repo.'/'.self::smartEncode($folder)),
|
||||
escapeshellarg($commit));
|
||||
escapeshellarg($commit),
|
||||
escapeshellarg($this->repo.'/'.self::smartEncode($folder)));
|
||||
$cmd = Pluf::f('idf_exec_cmd_prefix', '').$cmd;
|
||||
$xml = simplexml_load_string(self::shell_exec('IDF_Scm_Svn::getTree', $cmd));
|
||||
$res = array();
|
||||
@@ -248,7 +247,6 @@ class IDF_Scm_Svn extends IDF_Scm
|
||||
return $res;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the commit message of a revision revision.
|
||||
*
|
||||
@@ -260,11 +258,11 @@ class IDF_Scm_Svn extends IDF_Scm
|
||||
if (isset($this->cache['commitmess'][$rev])) {
|
||||
return $this->cache['commitmess'][$rev];
|
||||
}
|
||||
$cmd = sprintf(Pluf::f('svn_path', 'svn').' log --xml --limit 1 --username=%s --password=%s %s@%s',
|
||||
$cmd = sprintf(Pluf::f('svn_path', 'svn').' log --no-auth-cache --xml --limit 1 --username=%s --password=%s --revision=%s %s',
|
||||
escapeshellarg($this->username),
|
||||
escapeshellarg($this->password),
|
||||
escapeshellarg($this->repo),
|
||||
escapeshellarg($rev));
|
||||
escapeshellarg($rev),
|
||||
escapeshellarg($this->repo));
|
||||
$cmd = Pluf::f('idf_exec_cmd_prefix', '').$cmd;
|
||||
try {
|
||||
$xml = simplexml_load_string(self::shell_exec('IDF_Scm_Svn::getCommitMessage', $cmd));
|
||||
@@ -281,11 +279,11 @@ class IDF_Scm_Svn extends IDF_Scm
|
||||
if ($rev == null) {
|
||||
$rev = 'HEAD';
|
||||
}
|
||||
$cmd = sprintf(Pluf::f('svn_path', 'svn').' info --xml --username=%s --password=%s %s@%s',
|
||||
$cmd = sprintf(Pluf::f('svn_path', 'svn').' info --no-auth-cache --xml --username=%s --password=%s --revision=%s %s',
|
||||
escapeshellarg($this->username),
|
||||
escapeshellarg($this->password),
|
||||
escapeshellarg($this->repo.'/'.self::smartEncode($filename)),
|
||||
escapeshellarg($rev));
|
||||
escapeshellarg($rev),
|
||||
escapeshellarg($this->repo.'/'.self::smartEncode($filename)));
|
||||
$cmd = Pluf::f('idf_exec_cmd_prefix', '').$cmd;
|
||||
$xml = simplexml_load_string(self::shell_exec('IDF_Scm_Svn::getPathInfo', $cmd));
|
||||
if (!isset($xml->entry)) {
|
||||
@@ -308,11 +306,11 @@ class IDF_Scm_Svn extends IDF_Scm
|
||||
|
||||
public function getFile($def, $cmd_only=false)
|
||||
{
|
||||
$cmd = sprintf(Pluf::f('svn_path', 'svn').' cat --username=%s --password=%s %s@%s',
|
||||
$cmd = sprintf(Pluf::f('svn_path', 'svn').' cat --no-auth-cache --username=%s --password=%s --revision=%s %s',
|
||||
escapeshellarg($this->username),
|
||||
escapeshellarg($this->password),
|
||||
escapeshellarg($this->repo.'/'.self::smartEncode($def->fullpath)),
|
||||
escapeshellarg($def->rev));
|
||||
escapeshellarg($def->rev),
|
||||
escapeshellarg($this->repo.'/'.self::smartEncode($def->fullpath)));
|
||||
$cmd = Pluf::f('idf_exec_cmd_prefix', '').$cmd;
|
||||
return ($cmd_only) ?
|
||||
$cmd : self::shell_exec('IDF_Scm_Svn::getFile', $cmd);
|
||||
@@ -329,7 +327,7 @@ class IDF_Scm_Svn extends IDF_Scm
|
||||
return $this->cache['branches'];
|
||||
}
|
||||
$res = array();
|
||||
$cmd = sprintf(Pluf::f('svn_path', 'svn').' ls --username=%s --password=%s %s@HEAD',
|
||||
$cmd = sprintf(Pluf::f('svn_path', 'svn').' ls --no-auth-cache --username=%s --password=%s --revision=HEAD %s',
|
||||
escapeshellarg($this->username),
|
||||
escapeshellarg($this->password),
|
||||
escapeshellarg($this->repo.'/branches'));
|
||||
@@ -344,7 +342,7 @@ class IDF_Scm_Svn extends IDF_Scm
|
||||
}
|
||||
}
|
||||
ksort($res);
|
||||
$cmd = sprintf(Pluf::f('svn_path', 'svn').' info --username=%s --password=%s %s@HEAD',
|
||||
$cmd = sprintf(Pluf::f('svn_path', 'svn').' info --no-auth-cache --username=%s --password=%s --revision=HEAD %s',
|
||||
escapeshellarg($this->username),
|
||||
escapeshellarg($this->password),
|
||||
escapeshellarg($this->repo.'/trunk'));
|
||||
@@ -368,7 +366,7 @@ class IDF_Scm_Svn extends IDF_Scm
|
||||
return $this->cache['tags'];
|
||||
}
|
||||
$res = array();
|
||||
$cmd = sprintf(Pluf::f('svn_path', 'svn').' ls --username=%s --password=%s %s@HEAD',
|
||||
$cmd = sprintf(Pluf::f('svn_path', 'svn').' ls --no-auth-cache --username=%s --password=%s --revision=HEAD %s',
|
||||
escapeshellarg($this->username),
|
||||
escapeshellarg($this->password),
|
||||
escapeshellarg($this->repo.'/tags'));
|
||||
@@ -412,7 +410,6 @@ class IDF_Scm_Svn extends IDF_Scm
|
||||
return array();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get commit details.
|
||||
*
|
||||
@@ -426,11 +423,11 @@ class IDF_Scm_Svn extends IDF_Scm
|
||||
return false;
|
||||
}
|
||||
$res = array();
|
||||
$cmd = sprintf(Pluf::f('svn_path', 'svn').' log --xml --limit 1 -v --username=%s --password=%s %s@%s',
|
||||
$cmd = sprintf(Pluf::f('svn_path', 'svn').' log --no-auth-cache --xml --limit 1 -v --username=%s --password=%s --revision=%s %s',
|
||||
escapeshellarg($this->username),
|
||||
escapeshellarg($this->password),
|
||||
escapeshellarg($this->repo),
|
||||
escapeshellarg($commit));
|
||||
escapeshellarg($commit),
|
||||
escapeshellarg($this->repo));
|
||||
$cmd = Pluf::f('idf_exec_cmd_prefix', '').$cmd;
|
||||
$xmlRes = self::shell_exec('IDF_Scm_Svn::getCommit', $cmd);
|
||||
$xml = simplexml_load_string($xmlRes);
|
||||
@@ -473,7 +470,7 @@ class IDF_Scm_Svn extends IDF_Scm
|
||||
private function getDiff($rev='HEAD')
|
||||
{
|
||||
$res = array();
|
||||
$cmd = sprintf(Pluf::f('svn_path', 'svn').' diff -c %s --username=%s --password=%s %s',
|
||||
$cmd = sprintf(Pluf::f('svn_path', 'svn').' diff --no-auth-cache -c %s --username=%s --password=%s %s',
|
||||
escapeshellarg($rev),
|
||||
escapeshellarg($this->username),
|
||||
escapeshellarg($this->password),
|
||||
@@ -482,6 +479,88 @@ class IDF_Scm_Svn extends IDF_Scm
|
||||
return self::shell_exec('IDF_Scm_Svn::getDiff', $cmd);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see IDF_Scm::getChanges()
|
||||
*/
|
||||
public function getChanges($commit)
|
||||
{
|
||||
if ($this->validateRevision($commit) != IDF_Scm::REVISION_VALID) {
|
||||
return null;
|
||||
}
|
||||
$cmd = sprintf(Pluf::f('svn_path', 'svn').' log --xml -v --no-auth-cache -r %s --username=%s --password=%s %s',
|
||||
escapeshellarg($commit),
|
||||
escapeshellarg($this->username),
|
||||
escapeshellarg($this->password),
|
||||
escapeshellarg($this->repo));
|
||||
$out = array();
|
||||
$cmd = Pluf::f('idf_exec_cmd_prefix', '').$cmd;
|
||||
$out = self::shell_exec('IDF_Scm_Svn::getChanges', $cmd);
|
||||
$xml = simplexml_load_string($out);
|
||||
if (count($xml) == 0) {
|
||||
return null;
|
||||
}
|
||||
$entry = current($xml);
|
||||
|
||||
$return = (object) array(
|
||||
'additions' => array(),
|
||||
'deletions' => array(),
|
||||
'patches' => array(),
|
||||
// while SVN has support for attributes, we cannot see their changes
|
||||
// in the log's XML unfortunately
|
||||
'properties' => array(),
|
||||
'copies' => array(),
|
||||
'renames' => array(),
|
||||
);
|
||||
|
||||
foreach ($entry->paths->path as $p) {
|
||||
$path = (string) $p;
|
||||
foreach ($p->attributes() as $k => $v) {
|
||||
$key = (string) $k;
|
||||
$val = (string) $v;
|
||||
if ($key != 'action')
|
||||
continue;
|
||||
if ($val == 'M')
|
||||
$return->patches[] = $path;
|
||||
else if ($val == 'A')
|
||||
$return->additions[] = $path;
|
||||
else if ($val == 'D')
|
||||
$return->deletions[] = $path;
|
||||
}
|
||||
}
|
||||
|
||||
// copies are treated as renames if they have an add _and_ a drop;
|
||||
// only if they only have an add, but no drop, they're treated as copies
|
||||
foreach ($entry->paths->path as $p) {
|
||||
$trg = (string) $p;
|
||||
$src = null;
|
||||
foreach ($p->attributes() as $k => $v) {
|
||||
if ((string) $k == 'copyfrom-path') {
|
||||
$src = (string) $v;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ($src == null)
|
||||
continue;
|
||||
|
||||
$srcidx = array_search($src, $return->deletions);
|
||||
$trgidx = array_search($trg, $return->additions);
|
||||
if ($srcidx !== false && $trgidx !== false) {
|
||||
$return->renames[$src] = $trg;
|
||||
unset($return->deletions[$srcidx]);
|
||||
unset($return->additions[$trgidx]);
|
||||
continue;
|
||||
}
|
||||
if ($srcidx === false && $trgidx !== false) {
|
||||
$return->copies[$src] = $trg;
|
||||
unset($return->additions[$trgidx]);
|
||||
continue;
|
||||
}
|
||||
// file sutures (counter-operation to copy) not supported
|
||||
}
|
||||
|
||||
return $return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get latest changes.
|
||||
@@ -498,12 +577,12 @@ class IDF_Scm_Svn extends IDF_Scm
|
||||
$branch = 'HEAD';
|
||||
}
|
||||
$res = array();
|
||||
$cmd = sprintf(Pluf::f('svn_path', 'svn').' log --xml -v --limit %s --username=%s --password=%s %s@%s',
|
||||
$cmd = sprintf(Pluf::f('svn_path', 'svn').' log --no-auth-cache --xml -v --limit %s --username=%s --password=%s --revision=%s %s',
|
||||
escapeshellarg($n),
|
||||
escapeshellarg($this->username),
|
||||
escapeshellarg($this->password),
|
||||
escapeshellarg($this->repo),
|
||||
escapeshellarg($branch));
|
||||
escapeshellarg($branch),
|
||||
escapeshellarg($this->repo));
|
||||
$cmd = Pluf::f('idf_exec_cmd_prefix', '').$cmd;
|
||||
$xmlRes = self::shell_exec('IDF_Scm_Svn::getChangeLog', $cmd);
|
||||
$xml = simplexml_load_string($xmlRes);
|
||||
@@ -520,7 +599,6 @@ class IDF_Scm_Svn extends IDF_Scm
|
||||
return $res;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get additionnals properties on path and revision
|
||||
*
|
||||
@@ -531,11 +609,11 @@ class IDF_Scm_Svn extends IDF_Scm
|
||||
public function getProperties($rev, $path='')
|
||||
{
|
||||
$res = array();
|
||||
$cmd = sprintf(Pluf::f('svn_path', 'svn').' proplist --xml --username=%s --password=%s %s@%s',
|
||||
$cmd = sprintf(Pluf::f('svn_path', 'svn').' proplist --no-auth-cache --xml --username=%s --password=%s --revision=%s %s',
|
||||
escapeshellarg($this->username),
|
||||
escapeshellarg($this->password),
|
||||
escapeshellarg($this->repo.'/'.self::smartEncode($path)),
|
||||
escapeshellarg($rev));
|
||||
escapeshellarg($rev),
|
||||
escapeshellarg($this->repo.'/'.self::smartEncode($path)));
|
||||
$cmd = Pluf::f('idf_exec_cmd_prefix', '').$cmd;
|
||||
$xmlProps = self::shell_exec('IDF_Scm_Svn::getProperties', $cmd);
|
||||
$props = simplexml_load_string($xmlProps);
|
||||
@@ -554,7 +632,6 @@ class IDF_Scm_Svn extends IDF_Scm
|
||||
return $res;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get a specific additionnal property on path and revision
|
||||
*
|
||||
@@ -566,12 +643,12 @@ class IDF_Scm_Svn extends IDF_Scm
|
||||
private function getProperty($property, $rev, $path='')
|
||||
{
|
||||
$res = array();
|
||||
$cmd = sprintf(Pluf::f('svn_path', 'svn').' propget --xml %s --username=%s --password=%s %s@%s',
|
||||
$cmd = sprintf(Pluf::f('svn_path', 'svn').' propget --no-auth-cache --xml %s --username=%s --password=%s --revision=%s %s',
|
||||
escapeshellarg($property),
|
||||
escapeshellarg($this->username),
|
||||
escapeshellarg($this->password),
|
||||
escapeshellarg($this->repo.'/'.self::smartEncode($path)),
|
||||
escapeshellarg($rev));
|
||||
escapeshellarg($rev),
|
||||
escapeshellarg($this->repo.'/'.self::smartEncode($path)));
|
||||
$cmd = Pluf::f('idf_exec_cmd_prefix', '').$cmd;
|
||||
$xmlProp = self::shell_exec('IDF_Scm_Svn::getProperty', $cmd);
|
||||
$prop = simplexml_load_string($xmlProp);
|
||||
@@ -579,7 +656,6 @@ class IDF_Scm_Svn extends IDF_Scm
|
||||
return (string) $prop->target->property;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the number of the last commit in the repository.
|
||||
*
|
||||
@@ -590,11 +666,11 @@ class IDF_Scm_Svn extends IDF_Scm
|
||||
public function getLastCommit($rev='HEAD')
|
||||
{
|
||||
$xmlInfo = '';
|
||||
$cmd = sprintf(Pluf::f('svn_path', 'svn').' info --xml --username=%s --password=%s %s@%s',
|
||||
$cmd = sprintf(Pluf::f('svn_path', 'svn').' info --no-auth-cache --xml --username=%s --password=%s --revision=%s %s',
|
||||
escapeshellarg($this->username),
|
||||
escapeshellarg($this->password),
|
||||
escapeshellarg($this->repo),
|
||||
escapeshellarg($rev));
|
||||
escapeshellarg($rev),
|
||||
escapeshellarg($this->repo));
|
||||
$cmd = Pluf::f('idf_exec_cmd_prefix', '').$cmd;
|
||||
$xmlInfo = self::shell_exec('IDF_Scm_Svn::getLastCommit', $cmd);
|
||||
|
||||
|
@@ -90,40 +90,69 @@ class IDF_Template_MarkdownPrefilter extends Pluf_Text_HTML_Filter
|
||||
);
|
||||
|
||||
public $allowed = array(
|
||||
'a' => array('href', 'title', 'rel'),
|
||||
'abbr' => array('title'),
|
||||
'address' => array(),
|
||||
'b' => array(),
|
||||
'blockquote' => array(),
|
||||
'br' => array(),
|
||||
'caption' => array(),
|
||||
'code' => array(),
|
||||
'dd' => array(),
|
||||
'del' => array('cite', 'class', 'datetime', 'dir', 'id', 'title'),
|
||||
'div' => array('align', 'class'),
|
||||
'dl' => array(),
|
||||
'dt' => array(),
|
||||
'em' => array(),
|
||||
'h1' => array('id'),
|
||||
'h2' => array('id'),
|
||||
'h3' => array('id'),
|
||||
'h4' => array('id'),
|
||||
'h5' => array('id'),
|
||||
'h6' => array('id'),
|
||||
'hr' => array(),
|
||||
'i' => array(),
|
||||
'img' => array('src', 'class', 'alt', 'height', 'width', 'style'),
|
||||
'ins' => array('cite', 'class', 'datetime', 'dir', 'id', 'title'),
|
||||
'li' => array(),
|
||||
'ol' => array(),
|
||||
'p' => array('align', 'class'),
|
||||
'pre' => array(),
|
||||
'strong' => array(),
|
||||
'table' => array('summary'),
|
||||
'td' => array('style'),
|
||||
'th' => array(),
|
||||
'tr' => array(),
|
||||
'ul' => array(),
|
||||
'a' => array('class', 'dir', 'id', 'style', 'title',
|
||||
'href', 'hreflang', 'rel'),
|
||||
'abbr' => array('class', 'dir', 'id', 'style', 'title'),
|
||||
'address' => array('class', 'dir', 'id', 'style', 'title'),
|
||||
'b' => array('class', 'dir', 'id', 'style', 'title'),
|
||||
'blockquote' => array('class', 'dir', 'id', 'style', 'title',
|
||||
'cite'),
|
||||
'br' => array('class', 'id', 'style', 'title'),
|
||||
'caption' => array('class', 'dir', 'id', 'style', 'title',
|
||||
'align'), // deprecated attribute),
|
||||
'code' => array('class', 'dir', 'id', 'style', 'title'),
|
||||
'dd' => array('class', 'dir', 'id', 'style', 'title'),
|
||||
'del' => array('class', 'dir', 'id', 'style', 'title',
|
||||
'cite', 'datetime'),
|
||||
'div' => array('class', 'dir', 'id', 'style', 'title',
|
||||
'align'), // deprecated attribute
|
||||
'dl' => array('class', 'dir', 'id', 'style', 'title'),
|
||||
'dt' => array('class', 'dir', 'id', 'style', 'title'),
|
||||
'em' => array('class', 'dir', 'id', 'style', 'title'),
|
||||
'font' => array('class', 'dir', 'id', 'style', 'title', // deprecated element
|
||||
'color', 'face', 'size'), // deprecated attribute
|
||||
'h1' => array('class', 'dir', 'id', 'style', 'title',
|
||||
'align'), // deprecated attribute
|
||||
'h2' => array('class', 'dir', 'id', 'style', 'title',
|
||||
'align'), // deprecated attribute
|
||||
'h3' => array('class', 'dir', 'id', 'style', 'title',
|
||||
'align'), // deprecated attribute
|
||||
'h4' => array('class', 'dir', 'id', 'style', 'title',
|
||||
'align'), // deprecated attribute
|
||||
'h5' => array('class', 'dir', 'id', 'style', 'title',
|
||||
'align'), // deprecated attribute
|
||||
'h6' => array('class', 'dir', 'id', 'style', 'title',
|
||||
'align'), // deprecated attribute
|
||||
'hr' => array('class', 'dir', 'id', 'style', 'title',
|
||||
'align', 'noshade', 'size', 'width'), // deprecated attribute
|
||||
'i' => array('class', 'dir', 'id', 'style', 'title'),
|
||||
'img' => array('class', 'dir', 'id', 'style', 'title',
|
||||
'src', 'alt', 'height', 'width'),
|
||||
'ins' => array('class', 'dir', 'id', 'style', 'title',
|
||||
'cite', 'datetime'),
|
||||
'li' => array('class', 'dir', 'id', 'style', 'title',
|
||||
'type'), // deprecated attribute
|
||||
'ol' => array('class', 'dir', 'id', 'style', 'title',
|
||||
'type'), // deprecated attribute
|
||||
'p' => array('class', 'dir', 'id', 'style', 'title',
|
||||
'align'), // deprecated attribute
|
||||
'pre' => array('class', 'dir', 'id', 'style', 'title',
|
||||
'width'), // deprecated attribute
|
||||
'strong' => array('class', 'dir', 'id', 'style', 'title'),
|
||||
'table' => array('class', 'dir', 'id', 'style', 'title',
|
||||
'border', 'cellpadding', 'cellspacing', 'frame', 'rules', 'summary', 'width',
|
||||
'align', 'bgcolor'), // deprecated attribute
|
||||
'td' => array('class', 'dir', 'id', 'style', 'title',
|
||||
'align', 'colspan', 'headers', 'rowspan', 'scope', 'valign',
|
||||
'bgcolor', 'height', 'nowrap', 'width'), // deprecated attribute
|
||||
'th' => array('class', 'dir', 'id', 'style', 'title',
|
||||
'align', 'colspan', 'rowspan', 'scope', 'valign',
|
||||
'bgcolor', 'height', 'nowrap', 'width'), // deprecated attribute
|
||||
'tr' => array('class', 'dir', 'id', 'style', 'title',
|
||||
'align', 'valign',
|
||||
'bgcolor'), // deprecated attribute
|
||||
'ul' => array('class', 'dir', 'id', 'style', 'title',
|
||||
'type'), // deprecated attribute
|
||||
);
|
||||
// tags which should always be self-closing (e.g. "<img />")
|
||||
public $no_close = array(
|
||||
|
@@ -77,6 +77,12 @@ class IDF_Upload extends Pluf_Model
|
||||
'default' => 0,
|
||||
'verbose' => __('file size in bytes'),
|
||||
),
|
||||
'md5' =>
|
||||
array(
|
||||
'type' => 'Pluf_DB_Field_Text',
|
||||
'blank' => true,
|
||||
'verbose' => __('MD5'),
|
||||
),
|
||||
'submitter' =>
|
||||
array(
|
||||
'type' => 'Pluf_DB_Field_Foreignkey',
|
||||
@@ -144,6 +150,7 @@ class IDF_Upload extends Pluf_Model
|
||||
if ($this->id == '') {
|
||||
$this->creation_dtime = gmdate('Y-m-d H:i:s');
|
||||
$this->modif_dtime = gmdate('Y-m-d H:i:s');
|
||||
$this->md5 = md5_file (Pluf::f('upload_path') . '/' . $this->get_project()->shortname . '/files/' . $this->file);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -59,7 +59,7 @@ class IDF_Views_Download
|
||||
$sql .= ' AND id NOT IN ('.implode(',', $ids).')';
|
||||
}
|
||||
$pag->forced_where = new Pluf_SQL($sql, array($prj->id));
|
||||
|
||||
|
||||
$list_display = array(
|
||||
'file' => __('File'),
|
||||
array('summary', 'IDF_Views_Download_SummaryAndLabels', __('Summary')),
|
||||
@@ -79,7 +79,7 @@ class IDF_Views_Download
|
||||
'dlabel' => $dtag,
|
||||
),
|
||||
$request);
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -99,17 +99,17 @@ class IDF_Views_Download
|
||||
$deprecated = Pluf_Model_InArray($dtag, $tags);
|
||||
if ($request->method == 'POST' and
|
||||
true === IDF_Precondition::projectMemberOrOwner($request)) {
|
||||
|
||||
|
||||
$form = new IDF_Form_UpdateUpload($request->POST,
|
||||
array('project' => $prj,
|
||||
'upload' => $upload,
|
||||
'user' => $request->user));
|
||||
if ($form->isValid()) {
|
||||
$upload = $form->save();
|
||||
$urlfile = Pluf_HTTP_URL_urlForView('IDF_Views_Download::view',
|
||||
$urlfile = Pluf_HTTP_URL_urlForView('IDF_Views_Download::view',
|
||||
array($prj->shortname, $upload->id));
|
||||
$request->user->setMessage(sprintf(__('The file <a href="%1$s">%2$s</a> has been updated.'), $urlfile, Pluf_esc($upload->file)));
|
||||
$url = Pluf_HTTP_URL_urlForView('IDF_Views_Download::index',
|
||||
$url = Pluf_HTTP_URL_urlForView('IDF_Views_Download::index',
|
||||
array($prj->shortname));
|
||||
return new Pluf_HTTP_Response_Redirect($url);
|
||||
}
|
||||
@@ -162,7 +162,7 @@ class IDF_Views_Download
|
||||
* [description]
|
||||
*
|
||||
* This signal allows an application to perform a set of tasks
|
||||
* just before the deletion of the corresponding object in the
|
||||
* just before the deletion of the corresponding object in the
|
||||
* database but just after the deletion from the storage.
|
||||
*
|
||||
* [parameters]
|
||||
@@ -171,11 +171,11 @@ class IDF_Views_Download
|
||||
*
|
||||
*/
|
||||
$params = array('upload' => $upload);
|
||||
Pluf_Signal::send('IDF_Upload::delete',
|
||||
Pluf_Signal::send('IDF_Upload::delete',
|
||||
'IDF_Views_Download', $params);
|
||||
$upload->delete();
|
||||
$request->user->setMessage(__('The file has been deleted.'));
|
||||
$url = Pluf_HTTP_URL_urlForView('IDF_Views_Download::index',
|
||||
$url = Pluf_HTTP_URL_urlForView('IDF_Views_Download::index',
|
||||
array($prj->shortname));
|
||||
return new Pluf_HTTP_Response_Redirect($url);
|
||||
}
|
||||
@@ -190,19 +190,35 @@ class IDF_Views_Download
|
||||
}
|
||||
|
||||
/**
|
||||
* Download a file.
|
||||
* Download the file with the given name.
|
||||
*/
|
||||
public $download_precond = array('IDF_Precondition::accessDownloads');
|
||||
public function download($request, $match)
|
||||
{
|
||||
$prj = $request->project;
|
||||
$upload = Pluf_Shortcuts_GetObjectOr404('IDF_Upload', $match[2]);
|
||||
$sql = new Pluf_SQL('file=%s', array($match[2]));
|
||||
$upload = Pluf::factory('IDF_Upload')->getOne(array('filter' => $sql->gen()));
|
||||
if (!$upload) throw new Pluf_HTTP_Error404();
|
||||
$prj->inOr404($upload);
|
||||
$upload->downloads += 1;
|
||||
$upload->update();
|
||||
return new Pluf_HTTP_Response_Redirect($upload->getAbsoluteUrl($prj));
|
||||
}
|
||||
|
||||
/**
|
||||
* Download the file with the given ID (for legacy links).
|
||||
*/
|
||||
public $downloadById_precond = array('IDF_Precondition::accessDownloads');
|
||||
public function downloadById($request, $match)
|
||||
{
|
||||
$upload = Pluf_Shortcuts_GetObjectOr404('IDF_Upload', $match[2]);
|
||||
return new Pluf_HTTP_Response_Redirect(
|
||||
Pluf_HTTP_URL_urlForView('IDF_Views_Download::download', array(
|
||||
$match[1], $upload->file
|
||||
)), 301
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Submit a new file for download.
|
||||
*/
|
||||
@@ -218,10 +234,10 @@ class IDF_Views_Download
|
||||
'user' => $request->user));
|
||||
if ($form->isValid()) {
|
||||
$upload = $form->save();
|
||||
$urlfile = Pluf_HTTP_URL_urlForView('IDF_Views_Download::view',
|
||||
$urlfile = Pluf_HTTP_URL_urlForView('IDF_Views_Download::view',
|
||||
array($prj->shortname, $upload->id));
|
||||
$request->user->setMessage(sprintf(__('The <a href="%s">file</a> has been uploaded.'), $urlfile));
|
||||
$url = Pluf_HTTP_URL_urlForView('IDF_Views_Download::index',
|
||||
$url = Pluf_HTTP_URL_urlForView('IDF_Views_Download::index',
|
||||
array($prj->shortname));
|
||||
return new Pluf_HTTP_Response_Redirect($url);
|
||||
}
|
||||
@@ -246,7 +262,7 @@ class IDF_Views_Download
|
||||
{
|
||||
$conf = new IDF_Conf();
|
||||
$conf->setProject($project);
|
||||
$st = preg_split("/\015\012|\015|\012/",
|
||||
$st = preg_split("/\015\012|\015|\012/",
|
||||
$conf->getVal('labels_download_predefined', IDF_Form_UploadConf::init_predefined), -1, PREG_SPLIT_NO_EMPTY);
|
||||
$auto = '';
|
||||
foreach ($st as $s) {
|
||||
@@ -354,7 +370,7 @@ function IDF_Views_Download_SummaryAndLabels($field, $down, $extra='')
|
||||
{
|
||||
$tags = array();
|
||||
foreach ($down->get_tags_list() as $tag) {
|
||||
$url = Pluf_HTTP_URL_urlForView('IDF_Views_Download::listLabel',
|
||||
$url = Pluf_HTTP_URL_urlForView('IDF_Views_Download::listLabel',
|
||||
array($down->shortname, $tag->id));
|
||||
$tags[] = sprintf('<a href="%s" class="label">%s</a>', $url, Pluf_esc((string) $tag));
|
||||
}
|
||||
|
@@ -77,6 +77,79 @@ class IDF_Views_Issue
|
||||
$params, $request);
|
||||
}
|
||||
|
||||
/**
|
||||
* View the issue summary.
|
||||
* TODO Add thoses data in cache, and process it only after an issue update
|
||||
*/
|
||||
public $summary_precond = array('IDF_Precondition::accessIssues');
|
||||
public function summary($request, $match)
|
||||
{
|
||||
$tagStatistics = array();
|
||||
$ownerStatistics = array();
|
||||
$status = array();
|
||||
$isTrackerEmpty = false;
|
||||
|
||||
$prj = $request->project;
|
||||
$opened = $prj->getIssueCountByStatus('open');
|
||||
$closed = $prj->getIssueCountByStatus('closed');
|
||||
|
||||
// Check if the tracker is empty
|
||||
if ($opened === 0 && $closed === 0) {
|
||||
$isTrackerEmpty = true;
|
||||
} else {
|
||||
if ($opened > 0 || $closed > 0) {
|
||||
// Issue status statistics
|
||||
$status['Open'] = array($opened, (int)(100 * $opened / ($opened + $closed)));
|
||||
$status['Closed'] = array($closed, (int)(100 * $closed / ($opened + $closed)));
|
||||
}
|
||||
|
||||
if ($opened > 0) {
|
||||
// Issue owner statistics
|
||||
$owners = $prj->getIssueCountByOwner('open');
|
||||
foreach ($owners as $user => $nb) {
|
||||
if ($user === '') {
|
||||
$key = __('Not assigned');
|
||||
} else {
|
||||
$obj = Pluf::factory('Pluf_User')->getOne(array('filter'=>'id='.$user));
|
||||
$key = $obj->first_name . ' ' . $obj->last_name;
|
||||
}
|
||||
$ownerStatistics[$key] = array($nb, (int)(100 * $nb / $opened));
|
||||
}
|
||||
|
||||
// Issue class tag statistics
|
||||
$tags = $prj->getTagCloud();
|
||||
foreach ($tags as $t) {
|
||||
$tagStatistics[$t->class][$t->name] = array($t->nb_use, $t->id);
|
||||
}
|
||||
foreach($tagStatistics as $k => $v) {
|
||||
$nbIssueInClass = 0;
|
||||
foreach ($v as $val) {
|
||||
$nbIssueInClass += $val[0];
|
||||
}
|
||||
foreach ($v as $kk => $vv) {
|
||||
$tagStatistics[$k][$kk] = array($vv[0], (int)(100 * $vv[0] / $nbIssueInClass), $vv[1]);
|
||||
}
|
||||
}
|
||||
|
||||
// Sort
|
||||
krsort($tagStatistics);
|
||||
arsort($ownerStatistics);
|
||||
}
|
||||
}
|
||||
|
||||
$title = sprintf(__('Summary of tracked issues in %s.'), (string) $prj);
|
||||
|
||||
return Pluf_Shortcuts_RenderToResponse('idf/issues/summary.html',
|
||||
array('page_title' => $title,
|
||||
'trackerEmpty' => $isTrackerEmpty,
|
||||
'project' => $prj,
|
||||
'tagStatistics' => $tagStatistics,
|
||||
'ownerStatistics' => $ownerStatistics,
|
||||
'status' => $status,
|
||||
),
|
||||
$request);
|
||||
}
|
||||
|
||||
/**
|
||||
* View the issues watch list of a given user.
|
||||
* Limited to a specified project
|
||||
@@ -345,6 +418,7 @@ class IDF_Views_Issue
|
||||
'form' => $form,
|
||||
'page_title' => $title,
|
||||
'preview' => $preview,
|
||||
'issue' => new IDF_Issue(),
|
||||
),
|
||||
self::autoCompleteArrays($prj)
|
||||
);
|
||||
@@ -403,6 +477,8 @@ class IDF_Views_Issue
|
||||
$issue = Pluf_Shortcuts_GetObjectOr404('IDF_Issue', $match[2]);
|
||||
$prj->inOr404($issue);
|
||||
$comments = $issue->get_comments_list(array('order' => 'id ASC'));
|
||||
$related_issues = $issue->getGroupedRelatedIssues(array('order' => 'other_issue ASC'));
|
||||
|
||||
$url = Pluf_HTTP_URL_urlForView('IDF_Views_Issue::view',
|
||||
array($prj->shortname, $issue->id));
|
||||
$title = Pluf_Template::markSafe(sprintf(__('Issue <a href="%s">%d</a>: %s'), $url, $issue->id, $issue->summary));
|
||||
@@ -470,7 +546,8 @@ class IDF_Views_Issue
|
||||
'preview' => $preview,
|
||||
'interested' => $interested->count(),
|
||||
'previous_issue_id' => $previous_issue_id,
|
||||
'next_issue_id' => $next_issue_id
|
||||
'next_issue_id' => $next_issue_id,
|
||||
'related_issues' => $related_issues,
|
||||
),
|
||||
$arrays),
|
||||
$request);
|
||||
@@ -651,22 +728,60 @@ class IDF_Views_Issue
|
||||
public function autoCompleteIssueList($request, $match)
|
||||
{
|
||||
$prj = $request->project;
|
||||
$issue_id = !empty($match[2]) ? intval($match[2]) : 0;
|
||||
$query = trim($request->REQUEST['q']);
|
||||
$limit = !empty($request->REQUEST['limit']) ? intval($request->REQUEST['limit']) : 0;
|
||||
$limit = max(10, $limit);
|
||||
|
||||
$issues = array();
|
||||
|
||||
// empty search, return the most recently updated issues
|
||||
if (empty($query)) {
|
||||
$sql = new Pluf_SQL('project=%s', array($prj->id));
|
||||
$tmp = Pluf::factory('IDF_Issue')->getList(array(
|
||||
'filter' => $sql->gen(),
|
||||
'order' => 'modif_dtime DESC'
|
||||
));
|
||||
$issues += $tmp->getArrayCopy();
|
||||
}
|
||||
else {
|
||||
// ID-based search
|
||||
if (is_numeric($query)) {
|
||||
$sql = new Pluf_SQL('project=%s AND id LIKE %s', array($prj->id, $query.'%'));
|
||||
$tmp = Pluf::factory('IDF_Issue')->getList(array(
|
||||
'filter' => $sql->gen(),
|
||||
'order' => 'id ASC'
|
||||
));
|
||||
$issues += $tmp->getArrayCopy();
|
||||
}
|
||||
|
||||
// text-based search
|
||||
$res = new Pluf_Search_ResultSet(
|
||||
IDF_Search::mySearch($query, $prj, 'IDF_Issue')
|
||||
);
|
||||
foreach ($res as $issue)
|
||||
$issues[] = $issue;
|
||||
}
|
||||
|
||||
// Autocomplete from jQuery UI works with JSON, this old one still
|
||||
// expects a parsable string; since we'd need to bump jQuery beyond
|
||||
// 1.2.6 for this to use as well, we're trying to cope with the old format.
|
||||
// see http://www.learningjquery.com/2010/06/autocomplete-migration-guide
|
||||
|
||||
$arr = array(
|
||||
'Fo|o' => 110,
|
||||
'Bar' => 111,
|
||||
'Baz' => 112,
|
||||
);
|
||||
|
||||
$out = '';
|
||||
foreach ($arr as $key => $val)
|
||||
$ids = array();
|
||||
foreach ($issues as $issue)
|
||||
{
|
||||
$out .= str_replace('|', '|', $key).'|'.$val."\n";
|
||||
if ($issue->id == $issue_id)
|
||||
continue;
|
||||
|
||||
if (in_array($issue->id, $ids))
|
||||
continue;
|
||||
|
||||
if (--$limit < 0)
|
||||
break;
|
||||
|
||||
$out .= str_replace('|', '|', $issue->summary) .'|'.$issue->id."\n";
|
||||
$ids[] = $issue->id;
|
||||
}
|
||||
|
||||
return new Pluf_HTTP_Response($out);
|
||||
|
@@ -58,7 +58,7 @@ class IDF_Views_Source
|
||||
$title = sprintf(__('%s Invalid Revision'), (string) $request->project);
|
||||
$scm = IDF_Scm::get($request->project);
|
||||
$branches = $scm->getBranches();
|
||||
|
||||
|
||||
$commit = $match[2];
|
||||
$params = array(
|
||||
'page_title' => $title,
|
||||
@@ -66,7 +66,8 @@ class IDF_Views_Source
|
||||
'commit' => $commit,
|
||||
'branches' => $branches,
|
||||
);
|
||||
return Pluf_Shortcuts_RenderToResponse('idf/source/invalid_revision.html',
|
||||
$scmConf = $request->conf->getVal('scm', 'git');
|
||||
return Pluf_Shortcuts_RenderToResponse('idf/source/'.$scmConf.'/invalid_revision.html',
|
||||
$params, $request);
|
||||
}
|
||||
|
||||
@@ -307,12 +308,7 @@ class IDF_Views_Source
|
||||
$cobject->diff = null;
|
||||
$diff->parse();
|
||||
$scmConf = $request->conf->getVal('scm', 'git');
|
||||
try {
|
||||
$changes = $scm->getChanges($commit);
|
||||
} catch (Exception $e) {
|
||||
// getChanges is not yes supported by this backend.
|
||||
$changes = array();
|
||||
}
|
||||
$changes = $scm->getChanges($commit);
|
||||
$branches = $scm->getBranches();
|
||||
$in_branches = $scm->inBranches($cobject->commit, '');
|
||||
$tags = $scm->getTags();
|
||||
@@ -477,7 +473,7 @@ class IDF_Views_Source
|
||||
}
|
||||
|
||||
// compare two nodes of different types, directories ("tree")
|
||||
// should come before files ("blob")
|
||||
// should come before files ("blob")
|
||||
if ($a->type > $b->type) {
|
||||
return -1;
|
||||
}
|
||||
|
@@ -117,6 +117,11 @@ $ctl[] = array('regex' => '#^/p/([\-\w]+)/issues/$#',
|
||||
'base' => $base,
|
||||
'model' => 'IDF_Views_Issue',
|
||||
'method' => 'index');
|
||||
|
||||
$ctl[] = array('regex' => '#^/p/([\-\w]+)/issues/summary/$#',
|
||||
'base' => $base,
|
||||
'model' => 'IDF_Views_Issue',
|
||||
'method' => 'summary');
|
||||
|
||||
$ctl[] = array('regex' => '#^/p/([\-\w]+)/issues/search/$#',
|
||||
'base' => $base,
|
||||
@@ -173,7 +178,7 @@ $ctl[] = array('regex' => '#^/watchlist/(\w+)$#',
|
||||
'model' => 'IDF_Views_Issue',
|
||||
'method' => 'forgeWatchList');
|
||||
|
||||
$ctl[] = array('regex' => '#^/p/([\-\w]+)/issues/autocomplete/$#',
|
||||
$ctl[] = array('regex' => '#^/p/([\-\w]+)/issues/autocomplete/(\d*)$#',
|
||||
'base' => $base,
|
||||
'model' => 'IDF_Views_Issue',
|
||||
'method' => 'autoCompleteIssueList');
|
||||
@@ -299,11 +304,16 @@ $ctl[] = array('regex' => '#^/p/([\-\w]+)/downloads/(\d+)/$#',
|
||||
'model' => 'IDF_Views_Download',
|
||||
'method' => 'view');
|
||||
|
||||
$ctl[] = array('regex' => '#^/p/([\-\w]+)/downloads/(\d+)/get/$#',
|
||||
$ctl[] = array('regex' => '#^/p/([\-\w]+)/downloads/get/(.+)$#',
|
||||
'base' => $base,
|
||||
'model' => 'IDF_Views_Download',
|
||||
'method' => 'download');
|
||||
|
||||
$ctl[] = array('regex' => '#^/p/([\-\w]+)/downloads/(\d+)/get/$#',
|
||||
'base' => $base,
|
||||
'model' => 'IDF_Views_Download',
|
||||
'method' => 'downloadById');
|
||||
|
||||
$ctl[] = array('regex' => '#^/p/([\-\w]+)/downloads/create/$#',
|
||||
'base' => $base,
|
||||
'model' => 'IDF_Views_Download',
|
||||
|
@@ -130,7 +130,7 @@ msgstr "Entferntes Subversion-Depot"
|
||||
|
||||
#: IDF/Form/Admin/ProjectCreate.php:92 IDF/Form/SourceConf.php:40
|
||||
msgid "Repository username"
|
||||
msgstr "Depot-Nutzername"
|
||||
msgstr "Depot-Benutzername"
|
||||
|
||||
#: IDF/Form/Admin/ProjectCreate.php:99 IDF/Form/SourceConf.php:47
|
||||
msgid "Repository password"
|
||||
@@ -156,11 +156,11 @@ msgstr "Projekt-Eigentümer"
|
||||
#: IDF/Form/Admin/ProjectCreate.php:123 IDF/Form/Admin/ProjectUpdate.php:76
|
||||
#: IDF/Form/MembersConf.php:54 IDF/Form/TabsConf.php:52
|
||||
msgid "Project members"
|
||||
msgstr "Projekt-Mitglieder"
|
||||
msgstr "Projektmitglieder"
|
||||
|
||||
#: IDF/Form/Admin/ProjectCreate.php:136
|
||||
msgid "Project template"
|
||||
msgstr "Projekt-Vorlage"
|
||||
msgstr "Projektvorlage"
|
||||
|
||||
#: IDF/Form/Admin/ProjectCreate.php:138
|
||||
msgid ""
|
||||
@@ -168,7 +168,7 @@ msgid ""
|
||||
"general configuration will be taken from the template project."
|
||||
msgstr ""
|
||||
"Benutze das vorgegebene Projekt, um ein neues zu initialisieren. "
|
||||
"Zugriffsrechte und allgemeine Konfiguration werden von der Projekt-Vorlage "
|
||||
"Zugriffsrechte und allgemeine Konfiguration werden von der Projektvorlage "
|
||||
"übernommen."
|
||||
|
||||
#: IDF/Form/Admin/ProjectCreate.php:185
|
||||
@@ -350,7 +350,7 @@ msgid ""
|
||||
"The password must be hard for other people to guess, but easy for the user "
|
||||
"to remember."
|
||||
msgstr ""
|
||||
"Das Passwort sollte für andere Leute schwer zu erraten, aber für den Nutzer "
|
||||
"Das Passwort sollte für andere Leute schwer zu erraten, aber für den Benutzer "
|
||||
"einfach zu erinnern sein."
|
||||
|
||||
#: IDF/Form/Admin/UserUpdate.php:89
|
||||
@@ -366,7 +366,7 @@ msgstr "Beschreibung"
|
||||
|
||||
#: IDF/Form/Admin/UserUpdate.php:109 IDF/Form/UserAccount.php:110
|
||||
msgid "Twitter username"
|
||||
msgstr "Twitter-Nutzername"
|
||||
msgstr "Twitter-Benutzername"
|
||||
|
||||
#: IDF/Form/Admin/UserUpdate.php:119 IDF/Form/UserAccount.php:120
|
||||
msgid "Public email address"
|
||||
@@ -403,7 +403,7 @@ msgstr "Stab"
|
||||
#: IDF/Form/Admin/UserUpdate.php:164
|
||||
msgid "If you give staff rights to a user, you really need to trust them."
|
||||
msgstr ""
|
||||
"Wenn Du einen Nutzer zum Stab hinzufügst, solltest Du ihm wirklich trauen."
|
||||
"Wenn Du einen Benutzer zum Stab hinzufügst, solltest Du ihm wirklich trauen."
|
||||
|
||||
#: IDF/Form/Admin/UserUpdate.php:172 IDF/Views/Admin.php:213
|
||||
msgid "Active"
|
||||
@@ -414,8 +414,8 @@ msgid ""
|
||||
"If the user is not getting the confirmation email or is abusing the system, "
|
||||
"you can directly enable or disable their account here."
|
||||
msgstr ""
|
||||
"Wenn der Nutzer keine Bestätigungs-E-Mail erhält oder das System "
|
||||
"missbraucht, kannst Du sein Konto hier direkt aktivieren oder deaktivieren."
|
||||
"Wenn der Benutzer keine Bestätigungs-E-Mail erhält oder das System "
|
||||
"missbraucht, kannst Du sein Benutzerkonto hier direkt aktivieren oder deaktivieren."
|
||||
|
||||
#: IDF/Form/Admin/UserUpdate.php:274
|
||||
msgid "--- is not a valid first name."
|
||||
@@ -425,7 +425,7 @@ msgstr "--- ist kein gültiger Vorname"
|
||||
msgid ""
|
||||
"A user with this email already exists, please provide another email address."
|
||||
msgstr ""
|
||||
"Ein Nutzer mit dieser E-Mail-Adresse existiert bereits, bitte gib eine "
|
||||
"Ein Benutzer mit dieser E-Mail-Adresse existiert bereits, bitte gib eine "
|
||||
"andere E-Mail-Adresse an."
|
||||
|
||||
#: IDF/Form/Admin/UserUpdate.php:301 IDF/Form/UserAccount.php:389
|
||||
@@ -678,7 +678,7 @@ msgstr ""
|
||||
|
||||
#: IDF/Form/Register.php:148
|
||||
msgid "Confirm the creation of your account."
|
||||
msgstr "Bestätige die Erstellung deines Accounts."
|
||||
msgstr "Bestätige die Erstellung Deines Benutzerkontos."
|
||||
|
||||
#: IDF/Form/RegisterConfirmation.php:40 IDF/Form/RegisterInputKey.php:36
|
||||
msgid "Your confirmation key"
|
||||
@@ -705,7 +705,7 @@ msgid ""
|
||||
"This account has already been confirmed. Maybe should you try to recover "
|
||||
"your password using the help link."
|
||||
msgstr ""
|
||||
"Dieses Konto wurde bereits bestätigt. Vielleicht möchtest Du versuchen, Dein "
|
||||
"Dieses Benutzerkonto wurde bereits bestätigt. Vielleicht möchtest Du versuchen, Dein "
|
||||
"Passwort über den Hilfe-Link wiederherzustellen?"
|
||||
|
||||
#: IDF/Form/ReviewCreate.php:74
|
||||
@@ -1204,7 +1204,7 @@ msgstr ""
|
||||
"Quellcode.<br />\n"
|
||||
"Wenn Du den Zugriff auf den Quellcode beschränkst, wird kein anonymer "
|
||||
"Zugriff<br />\n"
|
||||
"angeboten und die Nutzer müssen sich mit ihrem Passwort oder "
|
||||
"angeboten und die Benutzer müssen sich mit ihrem Passwort oder "
|
||||
"öffentlichen<br />\n"
|
||||
"Schlüssel authentifizieren."
|
||||
|
||||
@@ -1241,7 +1241,7 @@ msgid ""
|
||||
"\" will default to authorized users only."
|
||||
msgstr ""
|
||||
"Wenn Du ein Projekt als privat markierst, haben nur Projektmitglieder und "
|
||||
"Administratoren zusammen mit den von Dir extra authorisierten Nutzern "
|
||||
"Administratoren zusammen mit den von Dir extra authorisierten Benutzern "
|
||||
"Zugriff darauf. Du kannst weiterhin zusätzliche Zugriffsrechte für bestimmte "
|
||||
"Projektfunktionen vergeben, aber die Einstellungen \"Für alle offen\" und "
|
||||
"\"Angemeldete Benutzer\" werden standardmäßig nur authorisierte Benutzer "
|
||||
@@ -1287,7 +1287,7 @@ msgid ""
|
||||
"<a href=\"%%url%%\">Sign in or create your account</a> to create issues or "
|
||||
"add comments"
|
||||
msgstr ""
|
||||
"<a href=\"%%url%%\">Melde Dich an oder lege ein Konto an</a>, um Tickets "
|
||||
"<a href=\"%%url%%\">Melde Dich an oder lege ein Benutzerkonto an</a>, um Tickets "
|
||||
"oder Kommentare hinzuzufügen"
|
||||
|
||||
#: IDF/gettexttemplates/idf/base-full.html.php:4
|
||||
@@ -1587,7 +1587,7 @@ msgid ""
|
||||
"You need to create an account on <a href=\"http://en.gravatar.com/"
|
||||
"\">Gravatar</a>, this takes about 5 minutes and is free."
|
||||
msgstr ""
|
||||
"Du musst Dir einen Account auf <a href=\"http://de.gravatar.com/\">Gravatar</"
|
||||
"Du musst Dir ein Benutzerkonto auf <a href=\"http://de.gravatar.com/\">Gravatar.com</"
|
||||
"a> erstellen, es dauert nur 5 Minuten und ist kostenfrei."
|
||||
|
||||
#: IDF/gettexttemplates/idf/faq.html.php:10
|
||||
@@ -1632,7 +1632,7 @@ msgstr "<kbd>Umschalt+h</kbd>: Diese Hilfeseite."
|
||||
#: IDF/gettexttemplates/idf/faq.html.php:18
|
||||
msgid "If you are in a project, you have the following shortcuts:"
|
||||
msgstr ""
|
||||
"Befindest Du Dich in einem Projekt, kannst du die folgenden Tastaturkürzel "
|
||||
"Befindest Du Dich in einem Projekt, kannst Du die folgenden Tastaturkürzel "
|
||||
"benutzen:"
|
||||
|
||||
#: IDF/gettexttemplates/idf/faq.html.php:19
|
||||
@@ -1874,28 +1874,28 @@ msgstr "Es wird eine Bestätigung verlangt."
|
||||
#: IDF/gettexttemplates/idf/gadmin/users/base.html.php:3
|
||||
#: IDF/Views/Admin.php:201
|
||||
msgid "User List"
|
||||
msgstr "Nutzerliste"
|
||||
msgstr "Benutzerliste"
|
||||
|
||||
#: IDF/gettexttemplates/idf/gadmin/users/base.html.php:4
|
||||
#: IDF/gettexttemplates/idf/gadmin/users/update.html.php:13
|
||||
msgid "Update User"
|
||||
msgstr "Nutzer aktualisieren"
|
||||
msgstr "Benutzer aktualisieren"
|
||||
|
||||
#: IDF/gettexttemplates/idf/gadmin/users/base.html.php:5
|
||||
#: IDF/gettexttemplates/idf/gadmin/users/create.html.php:4
|
||||
msgid "Create User"
|
||||
msgstr "Nutzer anlegen"
|
||||
msgstr "Benutzer anlegen"
|
||||
|
||||
#: IDF/gettexttemplates/idf/gadmin/users/create.html.php:3
|
||||
msgid "The form contains some errors. Please correct them to create the user."
|
||||
msgstr ""
|
||||
"Die Eingabemaske enthält einige Fehler. Bitte korrigiere diese, um den "
|
||||
"Nutzer zu erstellen."
|
||||
"Benutzer zu erstellen."
|
||||
|
||||
#: IDF/gettexttemplates/idf/gadmin/users/create.html.php:6
|
||||
msgid "The user password will be sent by email to the user."
|
||||
msgstr ""
|
||||
"Das Passwort des Nutzers wird an die E-Mail-Adresse des Nutzers versandt."
|
||||
"Das Passwort des Benutzers wird an die E-Mail-Adresse des Benutzers versandt."
|
||||
|
||||
#: IDF/gettexttemplates/idf/gadmin/users/createuser-email.txt.php:3
|
||||
#, php-format
|
||||
@@ -1916,10 +1916,11 @@ msgid ""
|
||||
msgstr ""
|
||||
"Hallo %%user%%,\n"
|
||||
"\n"
|
||||
"Der Administrator %%admin%% hat ein neues Konto für Dich\n"
|
||||
"auf der Forge angelegt.\n"
|
||||
"Der Administrator %%admin%% hat ein neues Benutzerkonto\n"
|
||||
"für Dich auf der Forge angelegt.\n"
|
||||
"\n"
|
||||
"Hier sind die Zugangsdaten, mit denen Du auf Dein Konto zugreifen kannst:\n"
|
||||
"Hier sind die Zugangsdaten, mit denen Du auf Dein Benutzerkonto\n"
|
||||
"zugreifen kannst:\n"
|
||||
"\n"
|
||||
" Adresse: %%url%%\n"
|
||||
" Anmeldename: %%user.login%%\n"
|
||||
@@ -1931,17 +1932,17 @@ msgstr ""
|
||||
#: IDF/gettexttemplates/idf/gadmin/users/index.html.php:3
|
||||
#, php-format
|
||||
msgid "See <a href=\"%%url%%\">not validated users</a>."
|
||||
msgstr "Zeige <a href=\"%%url%%\">nicht validierte Nutzer</a>."
|
||||
msgstr "Zeige <a href=\"%%url%%\">nicht validierte Benutzer</a>."
|
||||
|
||||
#: IDF/gettexttemplates/idf/gadmin/users/index.html.php:4
|
||||
msgid "<p>You have here an overview of the users registered in the forge.</p>"
|
||||
msgstr ""
|
||||
"<p>Hier siehst Du eine Übersicht der Nutzer, die sich in der Forge "
|
||||
"<p>Hier siehst Du eine Übersicht der Benutzer, die sich in der Forge "
|
||||
"registriert haben."
|
||||
|
||||
#: IDF/gettexttemplates/idf/gadmin/users/index.html.php:5
|
||||
msgid "Number of users:"
|
||||
msgstr "Anzahl der Nutzer:"
|
||||
msgstr "Anzahl der Benutzer:"
|
||||
|
||||
#: IDF/gettexttemplates/idf/gadmin/users/update.html.php:3
|
||||
msgid ""
|
||||
@@ -1949,7 +1950,7 @@ msgid ""
|
||||
"need to ensure that you are providing a valid email\n"
|
||||
"address"
|
||||
msgstr ""
|
||||
"Wenn Du die E-Mail-Adresse eines Nutzers änderst,\n"
|
||||
"Wenn Du die E-Mail-Adresse eines Benutzers änderst,\n"
|
||||
"musst Du sicherstellen, eine gültige, neue E-Mail-Adresse\n"
|
||||
"als Ersatz bereitzustellen."
|
||||
|
||||
@@ -1959,14 +1960,14 @@ msgid ""
|
||||
"able to create new projects and update other non staff users.\n"
|
||||
msgstr ""
|
||||
"Wenn Du dem Benutzer Stab-Rechte erteilst, kann er\n"
|
||||
"neue Projekte anlegen und andere Nutzer, die nicht zum Stab\n"
|
||||
"neue Projekte anlegen und andere Benutzer, die nicht zum Stab\n"
|
||||
"gehören, aktualisieren.\n"
|
||||
|
||||
#: IDF/gettexttemplates/idf/gadmin/users/update.html.php:9
|
||||
msgid "The form contains some errors. Please correct them to update the user."
|
||||
msgstr ""
|
||||
"Die Eingabemaske enthält einige Fehler. Bitte korrigiere diese, um den "
|
||||
"Nutzer zu aktualisieren."
|
||||
"Benutzer zu aktualisieren."
|
||||
|
||||
#: IDF/gettexttemplates/idf/gadmin/users/update.html.php:10
|
||||
#: IDF/gettexttemplates/idf/register/confirmation.html.php:4
|
||||
@@ -2449,7 +2450,7 @@ msgid ""
|
||||
"is still valid and more work is needed to fully fix it."
|
||||
msgstr ""
|
||||
"Dieses Ticket wurde als geschlossen markiert. Füge nur dann einen Kommentar "
|
||||
"hinzu, wenn du denkst, dass das geschilderte Problem noch nicht ganz "
|
||||
"hinzu, wenn Du denkst, dass das geschilderte Problem noch nicht ganz "
|
||||
"beseitigt wurde."
|
||||
|
||||
#: IDF/gettexttemplates/idf/issues/view.html.orig.php:8
|
||||
@@ -2531,7 +2532,7 @@ msgid ""
|
||||
"If you don't have an account yet, you can create one <a href=\"%%url%%"
|
||||
"\">here</a>."
|
||||
msgstr ""
|
||||
"Wenn Du noch kein Konto hast, kannst Du <a href=\"%%url%%\">hier</a> ein "
|
||||
"Wenn Du noch kein Benutzerkonto hast, kannst Du <a href=\"%%url%%\">hier</a> ein "
|
||||
"neues erstellen."
|
||||
|
||||
#: IDF/gettexttemplates/idf/login_form.html.php:4
|
||||
@@ -2560,7 +2561,7 @@ msgstr "Willkommen."
|
||||
|
||||
#: IDF/gettexttemplates/idf/login_form.html.php:10
|
||||
msgid "It takes less than a minute to create your account."
|
||||
msgstr "Es dauert weniger als eine Minute, um Dein Konto zu erstellen."
|
||||
msgstr "Es dauert weniger als eine Minute, um Dein Benutzerkonto zu erstellen."
|
||||
|
||||
#: IDF/gettexttemplates/idf/main-menu.html.php:3
|
||||
#, php-format
|
||||
@@ -2576,7 +2577,7 @@ msgstr "Abmelden"
|
||||
|
||||
#: IDF/gettexttemplates/idf/main-menu.html.php:5
|
||||
msgid "Sign in or create your account"
|
||||
msgstr "Anmelden oder Konto erstellen"
|
||||
msgstr "Anmelden oder Benutzerkonto erstellen"
|
||||
|
||||
#: IDF/gettexttemplates/idf/main-menu.html.php:8 IDF/Views/Admin.php:42
|
||||
msgid "Forge Management"
|
||||
@@ -2671,7 +2672,7 @@ msgid ""
|
||||
msgstr ""
|
||||
"Hallo,\n"
|
||||
"\n"
|
||||
"Du hast die Anlage eines Kontos angeforder, um an dem Leben\n"
|
||||
"Du hast die Anlage eines Benutzerkontos angefordert, um an dem Leben\n"
|
||||
"eines Softwareprojektes teilhaben zu können.\n"
|
||||
"\n"
|
||||
"Um Dein Konto zu bestätigen, folge bitte dem folgenden Link:\n"
|
||||
@@ -2688,7 +2689,7 @@ msgstr ""
|
||||
"\n"
|
||||
"Wenn Du nicht mehr länger an diesem Software-Projekt\n"
|
||||
"interessiert bist oder wenn Du Dich nicht daran erinnern\n"
|
||||
"kannst, dieses Konto erstellen zu wollen, entschuldige\n"
|
||||
"kannst, dieses Benutzerkonto erstellen zu wollen, entschuldige\n"
|
||||
"und ignoriere einfach diese E-Mail.\n"
|
||||
"\n"
|
||||
"Mit freundlichen Grüßen,\n"
|
||||
@@ -2716,7 +2717,7 @@ msgid ""
|
||||
"strong> to log in afterwards."
|
||||
msgstr ""
|
||||
"Dies ist der letzte Schritt, aber bitte <strong>stelle sicher, dass Du "
|
||||
"Cookies aktiviert hast</strong>, um Dich im folgenden anzumelden."
|
||||
"Cookies aktiviert hast</strong>, um Dich im Folgenden anzumelden."
|
||||
|
||||
#: IDF/gettexttemplates/idf/register/index.html.php:3
|
||||
#: IDF/gettexttemplates/idf/register/index.html~.php:3
|
||||
@@ -2736,7 +2737,7 @@ msgid ""
|
||||
"login name and password."
|
||||
msgstr ""
|
||||
"Wenn Du einfach nur Deine Anmeldedaten vergessen hast, gibt es keinen Grund, "
|
||||
"ein neues Konto zu erstellen. Gehe einfach <a href=\"%%url%%\">hier her</a>, "
|
||||
"ein neues Benutzerkonto zu erstellen. Gehe einfach <a href=\"%%url%%\">hier her</a>, "
|
||||
"um Deinen Anmeldenamen und Dein Passwort wiederherzustellen."
|
||||
|
||||
#: IDF/gettexttemplates/idf/register/index.html.php:5
|
||||
@@ -2748,7 +2749,7 @@ msgid ""
|
||||
"you have troubles, you can <a href=\"%%url%%\">let us know about your issues "
|
||||
"at anytime</a>!"
|
||||
msgstr ""
|
||||
"Durch Dein Konto bist Du in der Lage, an dem Leben aller Softwareprojekte, "
|
||||
"Durch Dein Benutzerkonto bist Du in der Lage, an dem Leben aller Softwareprojekte, "
|
||||
"die hierüber verwaltet werden, teilzuhaben. Das Teilnehmen an einem "
|
||||
"Softwareprojekt muss Spass machen, deshalb <a href=\"%%url%%\">lass uns "
|
||||
"jederzeit von Deinen Problemen wissen</a>, solltest Du welche haben."
|
||||
@@ -3209,13 +3210,13 @@ msgstr "Zweige filtern"
|
||||
#: IDF/gettexttemplates/idf/source/mercurial/branch_tag_list.html.php:5
|
||||
#: IDF/gettexttemplates/idf/source/mtn/branch_tag_list.html.php:5
|
||||
msgid "Tags"
|
||||
msgstr "Marken"
|
||||
msgstr "Tags"
|
||||
|
||||
#: IDF/gettexttemplates/idf/source/git/branch_tag_list.html.php:6
|
||||
#: IDF/gettexttemplates/idf/source/mercurial/branch_tag_list.html.php:6
|
||||
#: IDF/gettexttemplates/idf/source/mtn/branch_tag_list.html.php:6
|
||||
msgid "filter tags"
|
||||
msgstr "Marken filtern"
|
||||
msgstr "Tags filtern"
|
||||
|
||||
#: IDF/gettexttemplates/idf/source/git/file.html.php:3
|
||||
#: IDF/gettexttemplates/idf/source/git/tree.html.php:3
|
||||
@@ -3231,7 +3232,7 @@ msgid ""
|
||||
"%%cobject.date%%."
|
||||
msgstr ""
|
||||
"Quellcode bei Revision <a class=\"mono\" href=\"%%url%%\">%%commit%%</a> "
|
||||
"erzeugt am %%cobject.date%%."
|
||||
"erzeugt %%cobject.date%%."
|
||||
|
||||
#: IDF/gettexttemplates/idf/source/git/file.html.php:4
|
||||
#: IDF/gettexttemplates/idf/source/git/tree.html.php:4
|
||||
@@ -3409,8 +3410,8 @@ msgstr "Revision:"
|
||||
#: IDF/gettexttemplates/idf/source/svn/commit.html.php:4
|
||||
#: IDF/gettexttemplates/idf/source/svn/file.html.php:11
|
||||
#: IDF/gettexttemplates/idf/source/svn/tree.html.php:16
|
||||
msgid "Go to revision"
|
||||
msgstr "Zu Revision gehen:"
|
||||
msgid "Switch"
|
||||
msgstr "Wechseln"
|
||||
|
||||
#: IDF/gettexttemplates/idf/source/svn/file.html.php:6
|
||||
#: IDF/gettexttemplates/idf/source/svn/tree.html.php:11
|
||||
@@ -3420,7 +3421,7 @@ msgstr "Eigenschaft"
|
||||
#: IDF/gettexttemplates/idf/source/svn/file.html.php:7
|
||||
#: IDF/gettexttemplates/idf/source/svn/tree.html.php:12
|
||||
msgid "set to:"
|
||||
msgstr "setzen auf:"
|
||||
msgstr "gesetzt auf:"
|
||||
|
||||
#: IDF/gettexttemplates/idf/source/svn/help.html.php:3
|
||||
#, php-format
|
||||
@@ -3442,7 +3443,7 @@ msgstr "Zweige:"
|
||||
|
||||
#: IDF/gettexttemplates/idf/source/svn/tree.html.php:18
|
||||
msgid "Tags:"
|
||||
msgstr "Marken:"
|
||||
msgstr "Tags:"
|
||||
|
||||
#: IDF/gettexttemplates/idf/user/changeemail-email.txt.php:3
|
||||
#, php-format
|
||||
@@ -3491,7 +3492,7 @@ msgstr ""
|
||||
|
||||
#: IDF/gettexttemplates/idf/user/changeemail.html.php:4
|
||||
msgid "Confirm Your New Email Address"
|
||||
msgstr "Bestätige deine neue Email-Adresse"
|
||||
msgstr "Bestätige Deine neue Email-Adresse"
|
||||
|
||||
#: IDF/gettexttemplates/idf/user/changeemail.html.php:7
|
||||
#: IDF/gettexttemplates/idf/user/passrecovery-inputkey.html.php:7
|
||||
@@ -3508,7 +3509,7 @@ msgstr ""
|
||||
#: IDF/gettexttemplates/idf/user/dashboard.html.php:3
|
||||
#, php-format
|
||||
msgid "<a href=\"%%url%%\">Update your account</a>."
|
||||
msgstr "<a href=\"%%url%%\">Aktualisiere Dein Konto</a>."
|
||||
msgstr "<a href=\"%%url%%\">Aktualisiere Dein Benutzerkonto</a>."
|
||||
|
||||
#: IDF/gettexttemplates/idf/user/dashboard.html.php:4
|
||||
#, php-format
|
||||
@@ -3578,7 +3579,7 @@ msgid ""
|
||||
"If possible, use your real name. By using your real name, people will have "
|
||||
"more trust in your comments and remarks."
|
||||
msgstr ""
|
||||
"Wenn möglich, nutze Deinen realen Namen. Dadurch wird deinen Kommentaren und "
|
||||
"Wenn möglich, nutze Deinen realen Namen. Dadurch wird Deinen Kommentaren und "
|
||||
"Bemerkungen mehr Vertrauen geschenkt."
|
||||
|
||||
#: IDF/gettexttemplates/idf/user/myaccount.html.php:19
|
||||
@@ -3646,7 +3647,7 @@ msgstr ""
|
||||
"Hallo %%user%%,\n"
|
||||
"\n"
|
||||
"Du hast Dein Passwort verloren und möchtest es wiederherstellen.\n"
|
||||
"Um ein neues Passwort für Dein Konto anzugeben, musst Du lediglich\n"
|
||||
"Um ein neues Passwort für Dein Benutzerkonto anzugeben, musst Du lediglich\n"
|
||||
"dem folgenden Link folgen. Sie führt zu einer einfachen Eingabemaske,\n"
|
||||
"mit der Du ein neues Passwort setzen kannst.\n"
|
||||
"\n"
|
||||
@@ -3801,7 +3802,7 @@ msgstr ""
|
||||
"a> mit der <a href=\"%%eurl%%\"><em>Extra</em>-Erweiterung</a> verwendet "
|
||||
"werden.</p>\n"
|
||||
"<p>Website-Adresses werden automatisch verlinkt und Du kannst außerdem zu "
|
||||
"anderen Dokumentations-Seiten durch die Benutzung von doppelten, eckige "
|
||||
"anderen Dokumentations-Seiten durch die Benutzung von doppelten, eckigen "
|
||||
"Klammern verlinken, etwa so: [[AndereSeite]].</p>\n"
|
||||
"<p>Um direkt die Inhalte einer Datei aus dem Depot einzubinden, umklammere "
|
||||
"den Pfad zur Datei mit dreifachen, eckigen Klammern: [[[Pfad/zu/Datei.txt]]]."
|
||||
@@ -4388,7 +4389,7 @@ msgstr "Administrator"
|
||||
|
||||
#: IDF/Views/Admin.php:214
|
||||
msgid "Last Login"
|
||||
msgstr "Letzter Login"
|
||||
msgstr "Letztes Login"
|
||||
|
||||
#: IDF/Views/Admin.php:221
|
||||
msgid "No users were found."
|
||||
@@ -4954,7 +4955,7 @@ msgstr ""
|
||||
|
||||
#: IDF/Views.php:284
|
||||
msgid "Here to Help You!"
|
||||
msgstr "Hier, um dir zu helfen!"
|
||||
msgstr "Hier, um Dir zu helfen!"
|
||||
|
||||
#: IDF/Views.php:300
|
||||
msgid "InDefero API (Application Programming Interface)"
|
||||
|
@@ -2,7 +2,7 @@
|
||||
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
|
||||
# This file is distributed under the same license as the PACKAGE package.
|
||||
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
|
||||
#
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Indefero\n"
|
||||
@@ -11,10 +11,10 @@ msgstr ""
|
||||
"PO-Revision-Date: 2011-03-28 14:19+0000\n"
|
||||
"Last-Translator: Mika <mikados.mikados@gmail.com>\n"
|
||||
"Language-Team: Mika <mikados.mikados@gmail.com>\n"
|
||||
"Language: es_ES\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Language: es_ES\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
|
||||
|
||||
#: IDF/Commit.php:55 IDF/Conf.php:54 IDF/Issue.php:52 IDF/Review.php:65
|
||||
@@ -144,8 +144,8 @@ msgid ""
|
||||
"This should be a world-wide unique identifier for your project. A reverse "
|
||||
"DNS notation like \"com.my-domain.my-project\" is a good idea."
|
||||
msgstr ""
|
||||
"Este debe ser un identificador único para su proyecto. Una notación tipo DNS"
|
||||
" inversa como \"com.mi-dominio.mi-proyecto\" es una buena elección."
|
||||
"Este debe ser un identificador único para su proyecto. Una notación tipo DNS "
|
||||
"inversa como \"com.mi-dominio.mi-proyecto\" es una buena elección."
|
||||
|
||||
#: IDF/Form/Admin/ProjectCreate.php:114 IDF/Form/Admin/ProjectUpdate.php:68
|
||||
#: IDF/Form/MembersConf.php:46 IDF/Form/TabsConf.php:53
|
||||
@@ -279,8 +279,8 @@ msgstr "Iniciar sesión"
|
||||
|
||||
#: IDF/Form/Admin/UserCreate.php:60
|
||||
msgid ""
|
||||
"The login must be between 3 and 15 characters long and contains only letters"
|
||||
" and digits."
|
||||
"The login must be between 3 and 15 characters long and contains only letters "
|
||||
"and digits."
|
||||
msgstr ""
|
||||
"El nombre de usuario debe tener entre 3 y 15 caracteres de largo y contener "
|
||||
"solamente letras y dígitos."
|
||||
@@ -421,8 +421,8 @@ msgstr "--- No es un nombre válido."
|
||||
msgid ""
|
||||
"A user with this email already exists, please provide another email address."
|
||||
msgstr ""
|
||||
"Ya existe un usuario con este correo electrónico , por favor, introduce otro"
|
||||
" email."
|
||||
"Ya existe un usuario con este correo electrónico , por favor, introduce otro "
|
||||
"email."
|
||||
|
||||
#: IDF/Form/Admin/UserUpdate.php:301 IDF/Form/UserAccount.php:389
|
||||
msgid "For security reason, you cannot upload a file with this extension."
|
||||
@@ -452,7 +452,8 @@ msgstr "Resumen"
|
||||
#: IDF/Form/IssueCreate.php:72 IDF/Form/IssueUpdate.php:65
|
||||
#: IDF/Form/ReviewCreate.php:83
|
||||
msgid "The \"upload_issue_path\" configuration variable was not set."
|
||||
msgstr "La variable de configuración \"upload_issue_path\" no se ha establecido."
|
||||
msgstr ""
|
||||
"La variable de configuración \"upload_issue_path\" no se ha establecido."
|
||||
|
||||
#: IDF/Form/IssueCreate.php:82 IDF/Form/IssueUpdate.php:75
|
||||
msgid "Attach a file"
|
||||
@@ -478,7 +479,8 @@ msgstr "Etiquetas"
|
||||
|
||||
#: IDF/Form/IssueCreate.php:192
|
||||
msgid "You cannot add a label with the \"Status\" prefix to an issue."
|
||||
msgstr "No se puede agregar una etiqueta con el prefijo \"Status\" a un ticket."
|
||||
msgstr ""
|
||||
"No se puede agregar una etiqueta con el prefijo \"Status\" a un ticket."
|
||||
|
||||
#: IDF/Form/IssueCreate.php:193 IDF/Form/IssueCreate.php:200
|
||||
#: IDF/Form/UpdateUpload.php:110 IDF/Form/Upload.php:120
|
||||
@@ -490,8 +492,7 @@ msgstr "Proporcionaste una etiqueta no válida."
|
||||
#: IDF/Form/Upload.php:119
|
||||
#, php-format
|
||||
msgid "You cannot provide more than label from the %s class to an issue."
|
||||
msgstr ""
|
||||
"No puede proporcionar más de una etiqueta de la clase %s en un ticket."
|
||||
msgstr "No puede proporcionar más de una etiqueta de la clase %s en un ticket."
|
||||
|
||||
#: IDF/Form/IssueCreate.php:210 IDF/Form/IssueUpdate.php:147
|
||||
msgid "You need to provide a description of the issue."
|
||||
@@ -565,8 +566,8 @@ msgid ""
|
||||
"Sorry, we cannot find a user with this email address or login. Feel free to "
|
||||
"try again."
|
||||
msgstr ""
|
||||
"Lo sentimos, no hemos encontrado ningún usuario con esta dirección de correo"
|
||||
" electrónico o nombre de usuario. Vuelva a intentarlo."
|
||||
"Lo sentimos, no hemos encontrado ningún usuario con esta dirección de correo "
|
||||
"electrónico o nombre de usuario. Vuelva a intentarlo."
|
||||
|
||||
#: IDF/Form/Password.php:100
|
||||
msgid "Password Recovery - InDefero"
|
||||
@@ -579,11 +580,11 @@ msgstr "Tu clave de verificación"
|
||||
|
||||
#: IDF/Form/PasswordInputKey.php:50 IDF/Form/PasswordReset.php:89
|
||||
msgid ""
|
||||
"We are sorry but this validation key is not valid. Maybe you should directly"
|
||||
" copy/paste it from your validation email."
|
||||
"We are sorry but this validation key is not valid. Maybe you should directly "
|
||||
"copy/paste it from your validation email."
|
||||
msgstr ""
|
||||
"Lo sentimos, pero esta clave de validación no es válida. Intente "
|
||||
"copiar/pegar desde el email de validación."
|
||||
"Lo sentimos, pero esta clave de validación no es válida. Intente copiar/"
|
||||
"pegar desde el email de validación."
|
||||
|
||||
#: IDF/Form/PasswordInputKey.php:61 IDF/Form/PasswordReset.php:100
|
||||
msgid ""
|
||||
@@ -639,8 +640,8 @@ msgid ""
|
||||
"The login must be between 3 and 15 characters long and contain only letters "
|
||||
"and digits."
|
||||
msgstr ""
|
||||
"El nombre de usuario debe tener entre 3 y 15 caracteres y contener solamente"
|
||||
" letras y dígitos."
|
||||
"El nombre de usuario debe tener entre 3 y 15 caracteres y contener solamente "
|
||||
"letras y dígitos."
|
||||
|
||||
#: IDF/Form/Register.php:53
|
||||
msgid "Your email"
|
||||
@@ -658,8 +659,7 @@ msgstr "Estoy de acuerdo con los términos y condiciones."
|
||||
|
||||
#: IDF/Form/Register.php:88
|
||||
msgid ""
|
||||
"We know, this is boring, but you need to agree with the terms and "
|
||||
"conditions."
|
||||
"We know, this is boring, but you need to agree with the terms and conditions."
|
||||
msgstr ""
|
||||
"Lo sabemos, esto es aburrido, pero es necesario aceptar los términos y "
|
||||
"condiciones."
|
||||
@@ -686,16 +686,16 @@ msgid ""
|
||||
"Your password must be hard for other people to guess, but easy for you to "
|
||||
"remember."
|
||||
msgstr ""
|
||||
"Su contraseña debe ser difícil de averiguar para otras personas, pero que le"
|
||||
" sea fácil de recordar."
|
||||
"Su contraseña debe ser difícil de averiguar para otras personas, pero que le "
|
||||
"sea fácil de recordar."
|
||||
|
||||
#: IDF/Form/RegisterConfirmation.php:99 IDF/Form/RegisterInputKey.php:50
|
||||
msgid ""
|
||||
"We are sorry but this confirmation key is not valid. Maybe you should "
|
||||
"directly copy/paste it from your confirmation email."
|
||||
msgstr ""
|
||||
"Lo sentimos, pero esta clave de confirmación no es válida. Pruebe a copiar y"
|
||||
" pegar directamente desde el email de confirmación."
|
||||
"Lo sentimos, pero esta clave de confirmación no es válida. Pruebe a copiar y "
|
||||
"pegar directamente desde el email de confirmación."
|
||||
|
||||
#: IDF/Form/RegisterConfirmation.php:110
|
||||
msgid ""
|
||||
@@ -886,8 +886,7 @@ msgstr ""
|
||||
|
||||
#: IDF/Form/UserAccount.php:354
|
||||
msgid ""
|
||||
"Please check the key as it does not appear to be a valid monotone public "
|
||||
"key."
|
||||
"Please check the key as it does not appear to be a valid monotone public key."
|
||||
msgstr ""
|
||||
"Por favor, compruebe la clave, ya que parece no ser una clave pública "
|
||||
"monotone válida ."
|
||||
@@ -904,11 +903,11 @@ msgstr "Ya has subido esta clave."
|
||||
|
||||
#: IDF/Form/UserChangeEmail.php:63
|
||||
msgid ""
|
||||
"The validation key is not valid. Please copy/paste it from your confirmation"
|
||||
" email."
|
||||
"The validation key is not valid. Please copy/paste it from your confirmation "
|
||||
"email."
|
||||
msgstr ""
|
||||
"La clave de validación no es válido. Por favor, copia/pega desde su email de"
|
||||
" confirmación."
|
||||
"La clave de validación no es válido. Por favor, copia/pega desde su email de "
|
||||
"confirmación."
|
||||
|
||||
#: IDF/Form/WikiConf.php:49
|
||||
msgid "Predefined documentation page labels"
|
||||
@@ -916,8 +915,7 @@ msgstr "Etiquetas predefinidas para página de documentación"
|
||||
|
||||
#: IDF/Form/WikiConf.php:58
|
||||
msgid ""
|
||||
"Each documentation page may have at most one label with each of these "
|
||||
"classes"
|
||||
"Each documentation page may have at most one label with each of these classes"
|
||||
msgstr ""
|
||||
"Cada página de documentación podrá tener más de una etiqueta para cada una "
|
||||
"de estas clases"
|
||||
@@ -1034,12 +1032,14 @@ msgid ""
|
||||
"\n"
|
||||
"<p><strong>Instructions:</strong></p>\n"
|
||||
"<p>List one status value per line in desired sort-order.</p>\n"
|
||||
"<p>Optionally, use an equals-sign to document the meaning of each status value.</p>\n"
|
||||
"<p>Optionally, use an equals-sign to document the meaning of each status "
|
||||
"value.</p>\n"
|
||||
msgstr ""
|
||||
"\n"
|
||||
"<p><strong>Instrucciones:</strong></p>\n"
|
||||
"<p>Lista un valor por línea en el orden deseado.</p>\n"
|
||||
"<p>Si lo desea, puede utilizar un signo de igual para documentar el valor de cada estado.</p>\n"
|
||||
"<p>Si lo desea, puede utilizar un signo de igual para documentar el valor de "
|
||||
"cada estado.</p>\n"
|
||||
|
||||
#: IDF/gettexttemplates/idf/admin/downloads.html.php:8
|
||||
#: IDF/gettexttemplates/idf/admin/issue-tracking.html.php:8
|
||||
@@ -1056,12 +1056,14 @@ msgstr "Guardar cambios"
|
||||
msgid ""
|
||||
"\n"
|
||||
"<p><strong>Instructions:</strong></p>\n"
|
||||
"<p>Specify each person by its login. Each person must have already registered with the given login.</p>\n"
|
||||
"<p>Specify each person by its login. Each person must have already "
|
||||
"registered with the given login.</p>\n"
|
||||
"<p>Separate the logins with commas and/or new lines.</p>\n"
|
||||
msgstr ""
|
||||
"\n"
|
||||
"<p><strong>Instrucciones:</strong></p>\n"
|
||||
"<p>Especifique cada persona por su nombre de usuaro. Cada persona debe haberse registrado con el nombre de usuario dado.</p>\n"
|
||||
"<p>Especifique cada persona por su nombre de usuaro. Cada persona debe "
|
||||
"haberse registrado con el nombre de usuario dado.</p>\n"
|
||||
"<p>Separe los nombres de usuarios con comas y/o nuevas líneas.</p>\n"
|
||||
|
||||
#: IDF/gettexttemplates/idf/admin/members.html.php:8
|
||||
@@ -1070,17 +1072,22 @@ msgstr ""
|
||||
msgid ""
|
||||
"\n"
|
||||
"<p><strong>Notes:</strong></p>\n"
|
||||
"<p>A project owner may make any change to this project, including removing other project owners. You need to be carefull when you give owner rights.</p>\n"
|
||||
"<p>A project member will not have access to the administration area but will have more options available in the use of the project.</p>\n"
|
||||
"<p>A project owner may make any change to this project, including removing "
|
||||
"other project owners. You need to be carefull when you give owner rights.</"
|
||||
"p>\n"
|
||||
"<p>A project member will not have access to the administration area but will "
|
||||
"have more options available in the use of the project.</p>\n"
|
||||
msgstr ""
|
||||
"\n"
|
||||
"<p><strong>Notas:</strong></p>\n"
|
||||
"<p>El propietario de un proyecto puede hacer cualquier cambio a este proyecto, incluyendo la eliminación de otros propietarios del proyecto. ¡Tienes que tener cuidado cuando das permisos de propietario!.</p>\n"
|
||||
"<p>Un miembro del proyecto no tendrá acceso al área de administración, pero tendrá más opciones disponibles para usar en el proyecto.</p>\n"
|
||||
"<p>El propietario de un proyecto puede hacer cualquier cambio a este "
|
||||
"proyecto, incluyendo la eliminación de otros propietarios del proyecto. "
|
||||
"¡Tienes que tener cuidado cuando das permisos de propietario!.</p>\n"
|
||||
"<p>Un miembro del proyecto no tendrá acceso al área de administración, pero "
|
||||
"tendrá más opciones disponibles para usar en el proyecto.</p>\n"
|
||||
|
||||
#: IDF/gettexttemplates/idf/admin/source.html.php:3
|
||||
msgid ""
|
||||
"You can find here the current repository configuration of your project."
|
||||
msgid "You can find here the current repository configuration of your project."
|
||||
msgstr ""
|
||||
"Puede encontrar aquí la configuración actual del repositorio de su proyecto."
|
||||
|
||||
@@ -1090,7 +1097,8 @@ msgid ""
|
||||
"request is sent after each repository commit. If this field is empty,\n"
|
||||
"notifications are disabled.</p>\n"
|
||||
"\n"
|
||||
"<p>Only properly-escaped <strong>HTTP</strong> URLs are supported, for example:</p>\n"
|
||||
"<p>Only properly-escaped <strong>HTTP</strong> URLs are supported, for "
|
||||
"example:</p>\n"
|
||||
"\n"
|
||||
"<ul>\n"
|
||||
"<li>http://domain.com/commit</li>\n"
|
||||
@@ -1109,8 +1117,10 @@ msgid ""
|
||||
"post-commit URL http://mydomain.com/%p/%r would send a request to\n"
|
||||
"http://mydomain.com/my-project/123.</p>"
|
||||
msgstr ""
|
||||
"<p>La configuración URL WebHook especifica una URL con una solicitud HTTP POST\n"
|
||||
"que se envía después de cada commit del repositorio. Si este campo está vacío,\n"
|
||||
"<p>La configuración URL WebHook especifica una URL con una solicitud HTTP "
|
||||
"POST\n"
|
||||
"que se envía después de cada commit del repositorio. Si este campo está "
|
||||
"vacío,\n"
|
||||
"las notificaciones están desactivadas.</p>\n"
|
||||
"\n"
|
||||
"<p>Únicamente las URLs <strong>HTTP</strong>, \n"
|
||||
@@ -1122,14 +1132,16 @@ msgstr ""
|
||||
"</ul>\n"
|
||||
"\n"
|
||||
"<p>Además, la URL puede contener la siguiente notación: \"%\", que\n"
|
||||
"será reemplazada por los valores específicos del proyecto para cada commit:</p>\n"
|
||||
"será reemplazada por los valores específicos del proyecto para cada commit:</"
|
||||
"p>\n"
|
||||
"\n"
|
||||
"<ul>\n"
|
||||
"<li>%p - nombre del proyecto</li>\n"
|
||||
"<li>%r - número de revisión</li>\n"
|
||||
"</ul>\n"
|
||||
"\n"
|
||||
"<p>Por ejemplo, el commit de la revisión 123 del proyecto 'mi-proyecto' con URL de post-commit http://midominio.com/%p/%r enviaría la solicitud\n"
|
||||
"<p>Por ejemplo, el commit de la revisión 123 del proyecto 'mi-proyecto' con "
|
||||
"URL de post-commit http://midominio.com/%p/%r enviaría la solicitud\n"
|
||||
"http://midominio.com/mi-proyecto/123.</p>"
|
||||
|
||||
#: IDF/gettexttemplates/idf/admin/source.html.php:26
|
||||
@@ -1161,11 +1173,13 @@ msgstr "Clave de autenticación Post-commit:"
|
||||
msgid ""
|
||||
"\n"
|
||||
"<p><strong>Instructions:</strong></p>\n"
|
||||
"<p>The description of the project can be improved using the <a href=\"%%url%%\">Markdown syntax</a>.</p>\n"
|
||||
"<p>The description of the project can be improved using the <a href=\"%%url%%"
|
||||
"\">Markdown syntax</a>.</p>\n"
|
||||
msgstr ""
|
||||
"\n"
|
||||
"<p><strong>Instrucciones:</strong></p>\n"
|
||||
"<p>La descripción del proyecto puede ser mejorada mediante la <a href=\"%%url%%\">Sintaxis de Marcado</a>.</p>\n"
|
||||
"<p>La descripción del proyecto puede ser mejorada mediante la <a href=\"%%url"
|
||||
"%%\">Sintaxis de Marcado</a>.</p>\n"
|
||||
|
||||
#: IDF/gettexttemplates/idf/admin/summary.html.php:7
|
||||
msgid ""
|
||||
@@ -1183,7 +1197,8 @@ msgid ""
|
||||
"password or SSH key."
|
||||
msgstr ""
|
||||
"\n"
|
||||
"Solo los miembros del proyecto y los administradores tienen acceso de escritura sobre las fuentes.<br />\n"
|
||||
"Solo los miembros del proyecto y los administradores tienen acceso de "
|
||||
"escritura sobre las fuentes.<br />\n"
|
||||
"Si restringe el acceso a las fuentes, el acceso anónimo,<br />\n"
|
||||
"no estará habilitado y los usuarios deberán autentificarse con su<br />\n"
|
||||
"contraseña o clave SSH."
|
||||
@@ -1202,12 +1217,12 @@ msgid ""
|
||||
"Notification emails will be sent from the <strong>%%from_email%%</strong> "
|
||||
"address, if you send the email to a mailing list, you may need to register "
|
||||
"this email address. Multiple email addresses must be separated through "
|
||||
"commas (','). If you do not want to send emails for a given type of changes,"
|
||||
" simply leave the corresponding field empty."
|
||||
"commas (','). If you do not want to send emails for a given type of changes, "
|
||||
"simply leave the corresponding field empty."
|
||||
msgstr ""
|
||||
"Las notificaciones de mensajes se enviarán desde la dirección "
|
||||
"<strong>%%from_email%%</strong>, si envía el mensaje a una lista de correo, "
|
||||
"puede que tenga que registrar esta dirección de correo electrónico. Varias "
|
||||
"Las notificaciones de mensajes se enviarán desde la dirección <strong>"
|
||||
"%%from_email%%</strong>, si envía el mensaje a una lista de correo, puede "
|
||||
"que tenga que registrar esta dirección de correo electrónico. Varias "
|
||||
"direcciones de correo electrónico deben separarse por comas (','). Si no "
|
||||
"desea enviar mensajes de correo electrónico para un determinado tipo de "
|
||||
"cambio, simplemente deje el correspondiente campo vacío."
|
||||
@@ -1217,8 +1232,8 @@ msgid ""
|
||||
"If you mark a project as private, only the project members and "
|
||||
"administrators, together with the extra authorized users you provide will "
|
||||
"have access to the project. You will still be able to define further access "
|
||||
"rights for the different tabs but the \"Open to all\" and \"Signed in "
|
||||
"users\" will default to authorized users only."
|
||||
"rights for the different tabs but the \"Open to all\" and \"Signed in users"
|
||||
"\" will default to authorized users only."
|
||||
msgstr ""
|
||||
"Si marca un proyecto como privado, sólo los miembros del proyecto y los "
|
||||
"administradores, junto con los usuarios adicionales autorizados tendrán "
|
||||
@@ -1291,14 +1306,14 @@ msgstr "Nueva descarga"
|
||||
|
||||
#: IDF/gettexttemplates/idf/downloads/delete.html.php:3
|
||||
msgid ""
|
||||
"<strong>Attention!</strong> If you want to delete a specific version of your"
|
||||
" software, maybe, someone is depending on this specific version to run his "
|
||||
"<strong>Attention!</strong> If you want to delete a specific version of your "
|
||||
"software, maybe, someone is depending on this specific version to run his "
|
||||
"systems. Are you sure, you will not affect anybody when removing this file?"
|
||||
msgstr ""
|
||||
"<strong>¡Atención!</strong> Si desea eliminar una versión específica del "
|
||||
"software, tal vez, alguien está utilizando esta versión específica para "
|
||||
"ejecutarlo en su sistema. ¿Estás seguro de que no afectará a nadie cuando se"
|
||||
" elimine este archivo?"
|
||||
"ejecutarlo en su sistema. ¿Estás seguro de que no afectará a nadie cuando se "
|
||||
"elimine este archivo?"
|
||||
|
||||
#: IDF/gettexttemplates/idf/downloads/delete.html.php:4
|
||||
#, php-format
|
||||
@@ -1464,7 +1479,8 @@ msgid ""
|
||||
"name."
|
||||
msgstr ""
|
||||
"Cada archivo debe tener un nombre distinto y el contenido del archivo\n"
|
||||
"no se puede cambiar, así que asegúrese de incluir los números de versión en el nombre de cada\n"
|
||||
"no se puede cambiar, así que asegúrese de incluir los números de versión en "
|
||||
"el nombre de cada\n"
|
||||
"archivo."
|
||||
|
||||
#: IDF/gettexttemplates/idf/downloads/submit.html.php:6
|
||||
@@ -1547,27 +1563,27 @@ msgstr "Proyectos"
|
||||
msgid ""
|
||||
"<p>This is simple:</p>\n"
|
||||
"<ol>\n"
|
||||
"<li>Write in the comments \"This is a duplicate of issue 123\", change 123 with the corresponding issue number.</li>\n"
|
||||
"<li>Write in the comments \"This is a duplicate of issue 123\", change 123 "
|
||||
"with the corresponding issue number.</li>\n"
|
||||
"<li>Change the status of the current issue to <em>Duplicate</em>.</li>\n"
|
||||
"<li>Submit the changes.</li>\n"
|
||||
"</ol>"
|
||||
msgstr ""
|
||||
"<p>Es simple:</p>\n"
|
||||
"<ol>\n"
|
||||
"<li>Escribe en los comentarios \"Esto es una duplicado del ticket 123\", cambia 123 por el número de ticket correspondiente.</li>\n"
|
||||
"<li>Escribe en los comentarios \"Esto es una duplicado del ticket 123\", "
|
||||
"cambia 123 por el número de ticket correspondiente.</li>\n"
|
||||
"<li>Cambia el estado del ticket actual a <em>Duplicado</em>.</li>\n"
|
||||
"<li>Envíe los cambios.</li>\n"
|
||||
"</ol>"
|
||||
|
||||
#: IDF/gettexttemplates/idf/faq.html.php:9
|
||||
msgid ""
|
||||
"You need to create an account on <a "
|
||||
"href=\"http://en.gravatar.com/\">Gravatar</a>, this takes about 5 minutes "
|
||||
"and is free."
|
||||
"You need to create an account on <a href=\"http://en.gravatar.com/"
|
||||
"\">Gravatar</a>, this takes about 5 minutes and is free."
|
||||
msgstr ""
|
||||
"Necesitas crear una cuenta en <a "
|
||||
"href=\"http://en.gravatar.com/\">Gravatar</a> , tardarás 5 minutos y es "
|
||||
"gratuito."
|
||||
"Necesitas crear una cuenta en <a href=\"http://en.gravatar.com/\">Gravatar</"
|
||||
"a> , tardarás 5 minutos y es gratuito."
|
||||
|
||||
#: IDF/gettexttemplates/idf/faq.html.php:10
|
||||
msgid ""
|
||||
@@ -1708,8 +1724,8 @@ msgstr ""
|
||||
|
||||
#: IDF/gettexttemplates/idf/gadmin/projects/create.html.php:4
|
||||
msgid ""
|
||||
"<strong>Once you have defined the repository type, you cannot change "
|
||||
"it</strong>."
|
||||
"<strong>Once you have defined the repository type, you cannot change it</"
|
||||
"strong>."
|
||||
msgstr ""
|
||||
"<strong>Una vez que haya definido el tipo de repositorio, no se puede "
|
||||
"modificar</strong>."
|
||||
@@ -1717,11 +1733,13 @@ msgstr ""
|
||||
#: IDF/gettexttemplates/idf/gadmin/projects/create.html.php:5
|
||||
msgid ""
|
||||
"\n"
|
||||
"<p>Specify each person by its login. Each person must have already registered with the given login.</p>\n"
|
||||
"<p>Specify each person by its login. Each person must have already "
|
||||
"registered with the given login.</p>\n"
|
||||
"<p>Separate the logins with commas and/or new lines.</p>\n"
|
||||
msgstr ""
|
||||
"\n"
|
||||
"<p>Especifique cada persona por su nombre de usuario. Cada persona debe estar registrada con el nombre de usuario proporcionado.</p>\n"
|
||||
"<p>Especifique cada persona por su nombre de usuario. Cada persona debe "
|
||||
"estar registrada con el nombre de usuario proporcionado.</p>\n"
|
||||
"<p>Separe los nombres de usuario con comas y / o saltos de líneas.</p>\n"
|
||||
|
||||
#: IDF/gettexttemplates/idf/gadmin/projects/create.html.php:14
|
||||
@@ -1734,8 +1752,7 @@ msgstr ""
|
||||
#: IDF/gettexttemplates/idf/gadmin/projects/create.html.php:15
|
||||
msgid "Provide at least one owner for the project or use a template."
|
||||
msgstr ""
|
||||
"Proporcione al menos un propietario para el proyecto o utilice una "
|
||||
"plantilla."
|
||||
"Proporcione al menos un propietario para el proyecto o utilice una plantilla."
|
||||
|
||||
#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:3
|
||||
#, php-format
|
||||
@@ -1755,7 +1772,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"\n"
|
||||
"<strong>¡Atención!</strong> Eliminar un proyecto es una operación delicada,\n"
|
||||
"que tiene como resultado <strong>borrar todos los datos</strong> del proyecto.\n"
|
||||
"que tiene como resultado <strong>borrar todos los datos</strong> del "
|
||||
"proyecto.\n"
|
||||
|
||||
#: IDF/gettexttemplates/idf/gadmin/projects/delete.html.php:10
|
||||
msgid ""
|
||||
@@ -1911,8 +1929,8 @@ msgstr "Ver <a href=\"%%url%%\">usuarios sin validar</a>."
|
||||
#: IDF/gettexttemplates/idf/gadmin/users/index.html.php:4
|
||||
msgid "<p>You have here an overview of the users registered in the forge.</p>"
|
||||
msgstr ""
|
||||
"<p>Tiene aquí una visión general de los usuarios registrados en la forja. "
|
||||
"</p>"
|
||||
"<p>Tiene aquí una visión general de los usuarios registrados en la forja. </"
|
||||
"p>"
|
||||
|
||||
#: IDF/gettexttemplates/idf/gadmin/users/index.html.php:5
|
||||
msgid "Number of users:"
|
||||
@@ -1934,7 +1952,8 @@ msgid ""
|
||||
"able to create new projects and update other non staff users.\n"
|
||||
msgstr ""
|
||||
"Si da permisos de acceso tipo Staff, el usuario será capaz \n"
|
||||
"de crear nuevos proyectos y actualizar a otros usuarios que no sean del Staff.\n"
|
||||
"de crear nuevos proyectos y actualizar a otros usuarios que no sean del "
|
||||
"Staff.\n"
|
||||
|
||||
#: IDF/gettexttemplates/idf/gadmin/users/update.html.php:9
|
||||
msgid "The form contains some errors. Please correct them to update the user."
|
||||
@@ -2185,10 +2204,13 @@ msgstr "Volver al ticket"
|
||||
#, php-format
|
||||
msgid ""
|
||||
"<p><strong>Open issues:</strong> <a href=\"%%open_url%%\">%%open%%</a></p>\n"
|
||||
"<p><strong>Closed issues:</strong> <a href=\"%%closed_url%%\">%%closed%%</a></p>\n"
|
||||
"<p><strong>Closed issues:</strong> <a href=\"%%closed_url%%\">%%closed%%</"
|
||||
"a></p>\n"
|
||||
msgstr ""
|
||||
"<p><strong>Tickets abiertos:</strong> <a href=\"%%open_url%%\">%%open%%</a></p>\n"
|
||||
"<p><strong>Tickets cerrados:</strong> <a href=\"%%closed_url%%\">%%closed%%</a></p>\n"
|
||||
"<p><strong>Tickets abiertos:</strong> <a href=\"%%open_url%%\">%%open%%</a></"
|
||||
"p>\n"
|
||||
"<p><strong>Tickets cerrados:</strong> <a href=\"%%closed_url%%\">%%closed%%</"
|
||||
"a></p>\n"
|
||||
|
||||
#: IDF/gettexttemplates/idf/issues/by-label.html.php:7
|
||||
msgid "Label:"
|
||||
@@ -2200,28 +2222,32 @@ msgstr "Finalizados:"
|
||||
|
||||
#: IDF/gettexttemplates/idf/issues/create.html.php:3
|
||||
msgid ""
|
||||
"<p>When you submit the issue do not forget to provide the following information:</p>\n"
|
||||
"<p>When you submit the issue do not forget to provide the following "
|
||||
"information:</p>\n"
|
||||
"<ul>\n"
|
||||
"<li>The steps to reproduce the problem.</li>\n"
|
||||
"<li>The version of the software and your operating system.</li>\n"
|
||||
"<li>Any information that can help the developers to solve the issue.</li>\n"
|
||||
"<li><strong>Do not provide any password or confidential information!</strong></li>\n"
|
||||
"<li><strong>Do not provide any password or confidential information!</"
|
||||
"strong></li>\n"
|
||||
"</ul>"
|
||||
msgstr ""
|
||||
"<p>Cuando envío el ticket, no se olvide proporcionar la siguiente información:</p>\n"
|
||||
"<p>Cuando envío el ticket, no se olvide proporcionar la siguiente "
|
||||
"información:</p>\n"
|
||||
"<ul>\n"
|
||||
"<li>Los pasos para reproducir el problema.</li>\n"
|
||||
"<li>La versión del software y tu sistema operativo.</li>\n"
|
||||
"<li>Cualquier información que pueda ayudar a los desarrolladores para resolver la incidencia.</li>\n"
|
||||
"<li><strong>¡No proporcione ninguna contraseña o información confidencial!</strong></li>\n"
|
||||
"<li>Cualquier información que pueda ayudar a los desarrolladores para "
|
||||
"resolver la incidencia.</li>\n"
|
||||
"<li><strong>¡No proporcione ninguna contraseña o información confidencial!</"
|
||||
"strong></li>\n"
|
||||
"</ul>"
|
||||
|
||||
#: IDF/gettexttemplates/idf/issues/create.html.php:10
|
||||
msgid ""
|
||||
"The form contains some errors. Please correct them to submit the issue."
|
||||
msgid "The form contains some errors. Please correct them to submit the issue."
|
||||
msgstr ""
|
||||
"El formulario contiene algunos errores. Por favor, corríjalos para enviar el"
|
||||
" ticket."
|
||||
"El formulario contiene algunos errores. Por favor, corríjalos para enviar el "
|
||||
"ticket."
|
||||
|
||||
#: IDF/gettexttemplates/idf/issues/create.html.php:11
|
||||
#: IDF/gettexttemplates/idf/issues/create.html.php:13
|
||||
@@ -2297,10 +2323,13 @@ msgstr "Propietario:"
|
||||
#, php-format
|
||||
msgid ""
|
||||
"<p><strong>Open issues:</strong> <a href=\"%%open_url%%\">%%open%%</a></p>\n"
|
||||
"<p><strong>Closed issues:</strong> <a href=\"%%closed_url%%\">%%closed%%</a></p>"
|
||||
"<p><strong>Closed issues:</strong> <a href=\"%%closed_url%%\">%%closed%%</"
|
||||
"a></p>"
|
||||
msgstr ""
|
||||
"<p><strong>Tickets abiertos:</strong> <a href=\"%%open_url%%\">%%open%%</a></p>\n"
|
||||
"<p><strong>Tickets cerrados:</strong> <a href=\"%%closed_url%%\">%%closed%%</a></p>"
|
||||
"<p><strong>Tickets abiertos:</strong> <a href=\"%%open_url%%\">%%open%%</a></"
|
||||
"p>\n"
|
||||
"<p><strong>Tickets cerrados:</strong> <a href=\"%%closed_url%%\">%%closed%%</"
|
||||
"a></p>"
|
||||
|
||||
#: IDF/gettexttemplates/idf/issues/issue-created-email.txt.php:3
|
||||
msgid ""
|
||||
@@ -2344,23 +2373,26 @@ msgstr "Comentarios (más reciente primero):"
|
||||
|
||||
#: IDF/gettexttemplates/idf/issues/my-issues.html.php:3
|
||||
#, php-format
|
||||
msgid "See the <a href=\"%%submit_closed_url%%\">%%nb_submit_closed%% closed</a>."
|
||||
msgid ""
|
||||
"See the <a href=\"%%submit_closed_url%%\">%%nb_submit_closed%% closed</a>."
|
||||
msgid_plural ""
|
||||
"See the <a href=\"%%submit_closed_url%%\">%%nb_submit_closed%% closed</a>."
|
||||
msgstr[0] ""
|
||||
"Ver <a href=\"%%submit_closed_url%%\">%%nb_submit_closed%% tickets "
|
||||
"cerrado</a>."
|
||||
msgstr[1] "Ver <a href=\"%%submit_closed_url%%\">%%nb_submit_closed%% cerrado</a>."
|
||||
"Ver <a href=\"%%submit_closed_url%%\">%%nb_submit_closed%% tickets cerrado</"
|
||||
"a>."
|
||||
msgstr[1] ""
|
||||
"Ver <a href=\"%%submit_closed_url%%\">%%nb_submit_closed%% cerrado</a>."
|
||||
|
||||
#: IDF/gettexttemplates/idf/issues/my-issues.html.php:4
|
||||
#, php-format
|
||||
msgid "See the <a href=\"%%owner_closed_url%%\">%%nb_owner_closed%% closed</a>."
|
||||
msgid ""
|
||||
"See the <a href=\"%%owner_closed_url%%\">%%nb_owner_closed%% closed</a>."
|
||||
msgid_plural ""
|
||||
"See the <a href=\"%%owner_closed_url%%\">%%nb_owner_closed%% closed</a>."
|
||||
msgstr[0] ""
|
||||
"Ver <a href=\"%%owner_closed_url%%\">%%nb_owner_closed%% tickets "
|
||||
"cerrado</a>."
|
||||
msgstr[1] "Ver <a href=\"%%owner_closed_url%%\">%%nb_owner_closed%% cerrado</a>."
|
||||
"Ver <a href=\"%%owner_closed_url%%\">%%nb_owner_closed%% tickets cerrado</a>."
|
||||
msgstr[1] ""
|
||||
"Ver <a href=\"%%owner_closed_url%%\">%%nb_owner_closed%% cerrado</a>."
|
||||
|
||||
#: IDF/gettexttemplates/idf/issues/my-issues.html.php:6
|
||||
#: IDF/gettexttemplates/idf/user/dashboard.html.php:7
|
||||
@@ -2389,8 +2421,8 @@ msgstr "Reportado por %%submitter%%, %%c.creation_dtime%%"
|
||||
msgid ""
|
||||
"Comment <a href=\"%%url%%\">%%i%%</a> by %%submitter%%, %%c.creation_dtime%%"
|
||||
msgstr ""
|
||||
"Comentario <a href=\"%%url%%\">%%i%%</a> por %%submitter%%, "
|
||||
"%%c.creation_dtime%%"
|
||||
"Comentario <a href=\"%%url%%\">%%i%%</a> por %%submitter%%, %%c."
|
||||
"creation_dtime%%"
|
||||
|
||||
#: IDF/gettexttemplates/idf/issues/view.html.orig.php:5
|
||||
#: IDF/gettexttemplates/idf/issues/view.html.php:5
|
||||
@@ -2466,8 +2498,7 @@ msgstr "ver"
|
||||
|
||||
#: IDF/gettexttemplates/idf/issues/view.html.orig.php:21
|
||||
#: IDF/gettexttemplates/idf/issues/view.html.php:21
|
||||
msgid ""
|
||||
"The form contains some errors. Please correct them to change the issue."
|
||||
msgid "The form contains some errors. Please correct them to change the issue."
|
||||
msgstr ""
|
||||
"El formulario contiene algunos errores. Por favor, corríjalos para "
|
||||
"actualizar el ticket."
|
||||
@@ -2485,8 +2516,8 @@ msgstr "Seguido por:"
|
||||
#: IDF/gettexttemplates/idf/login_form.html.php:3
|
||||
#, php-format
|
||||
msgid ""
|
||||
"If you don't have an account yet, you can create one <a "
|
||||
"href=\"%%url%%\">here</a>."
|
||||
"If you don't have an account yet, you can create one <a href=\"%%url%%"
|
||||
"\">here</a>."
|
||||
msgstr ""
|
||||
"Si aún no tienes una cuenta, puedes crear una <a href=\"%%url%%\">aquí</a>."
|
||||
|
||||
@@ -2520,10 +2551,11 @@ msgstr "Se tarda menos de un minuto en crearte una cuenta."
|
||||
|
||||
#: IDF/gettexttemplates/idf/main-menu.html.php:3
|
||||
#, php-format
|
||||
msgid "Welcome, <strong><a class=\"userw\" href=\"%%url%%\">%%user%%</a></strong>."
|
||||
msgid ""
|
||||
"Welcome, <strong><a class=\"userw\" href=\"%%url%%\">%%user%%</a></strong>."
|
||||
msgstr ""
|
||||
"Bienvenido, <strong><a class=\"userw\" "
|
||||
"href=\"%%url%%\">%%user%%</a></strong>."
|
||||
"Bienvenido, <strong><a class=\"userw\" href=\"%%url%%\">%%user%%</a></"
|
||||
"strong>."
|
||||
|
||||
#: IDF/gettexttemplates/idf/main-menu.html.php:4
|
||||
msgid "Sign Out"
|
||||
@@ -2668,8 +2700,8 @@ msgstr "Activar tu cuenta"
|
||||
#: IDF/gettexttemplates/idf/register/confirmation.html.php:8
|
||||
#: IDF/gettexttemplates/idf/user/passrecovery.html.php:8
|
||||
msgid ""
|
||||
"This is the last step, but just <strong>be sure to have the cookies "
|
||||
"enabled</strong> to log in afterwards."
|
||||
"This is the last step, but just <strong>be sure to have the cookies enabled</"
|
||||
"strong> to log in afterwards."
|
||||
msgstr ""
|
||||
"Este es el último paso, pero <strong>asegúrese de tener las cookies "
|
||||
"activadas</strong> para identificarte."
|
||||
@@ -2690,8 +2722,8 @@ msgid ""
|
||||
"create a new account. Just go <a href=\"%%url%%\">here</a> to recover your "
|
||||
"login name and password."
|
||||
msgstr ""
|
||||
"Si ha olvidado los datos de acceso, entonces no tiene porque crear una nueva"
|
||||
" cuenta. Simplemente haga click <a href=\"%%url%%\">aquí</a> para recuperar "
|
||||
"Si ha olvidado los datos de acceso, entonces no tiene porque crear una nueva "
|
||||
"cuenta. Simplemente haga click <a href=\"%%url%%\">aquí</a> para recuperar "
|
||||
"su nombre de usuario y contraseña."
|
||||
|
||||
#: IDF/gettexttemplates/idf/register/index.html.php:5
|
||||
@@ -2699,15 +2731,15 @@ msgstr ""
|
||||
#, php-format
|
||||
msgid ""
|
||||
"With your account, you will able to participate in the life of all the "
|
||||
"projects hosted here. Participating in a software project must be fun, so if"
|
||||
" you have troubles, you can <a href=\"%%url%%\">let us know about your "
|
||||
"issues at anytime</a>!"
|
||||
"projects hosted here. Participating in a software project must be fun, so if "
|
||||
"you have troubles, you can <a href=\"%%url%%\">let us know about your issues "
|
||||
"at anytime</a>!"
|
||||
msgstr ""
|
||||
"Con su cuenta, será capaz de participar en el desarrollo de todos los "
|
||||
"proyectos alojados aquí. Participar en un proyecto software tiene que ser "
|
||||
"algo divertido e interesante, así que si tiene problemas, puede <a "
|
||||
"href=\"%%url%%\">¡hacernos saber cuáles son sus inquietudes en cualquier "
|
||||
"momento</a>!"
|
||||
"algo divertido e interesante, así que si tiene problemas, puede <a href="
|
||||
"\"%%url%%\">¡hacernos saber cuáles son sus inquietudes en cualquier momento</"
|
||||
"a>!"
|
||||
|
||||
#: IDF/gettexttemplates/idf/register/index.html.php:6
|
||||
#: IDF/gettexttemplates/idf/register/index.html~.php:5
|
||||
@@ -2727,8 +2759,8 @@ msgid ""
|
||||
"Be sure to provide a valid email address, as we are sending a validation "
|
||||
"link by email."
|
||||
msgstr ""
|
||||
"Asegúrese de proporcionar una dirección válida de correo electrónico, ya que"
|
||||
" se enviará un enlace de confirmación por correo electrónico."
|
||||
"Asegúrese de proporcionar una dirección válida de correo electrónico, ya que "
|
||||
"se enviará un enlace de confirmación por correo electrónico."
|
||||
|
||||
#: IDF/gettexttemplates/idf/register/index.html.php:10
|
||||
#: IDF/gettexttemplates/idf/register/index.html~.php:9
|
||||
@@ -2778,30 +2810,35 @@ msgstr "Iniciar revisión del Código"
|
||||
msgid ""
|
||||
"<p>To start a code review, you need to provide:</p>\n"
|
||||
"<ul>\n"
|
||||
"<li>A commit or revision of the current code in the repository from which you started your work.</li>\n"
|
||||
"<li>A patch describing your changes with respect to the reference commit.</li>\n"
|
||||
"<li><strong>Check your patch does not provide any password or confidential information!</strong></li>\n"
|
||||
"<li>A commit or revision of the current code in the repository from which "
|
||||
"you started your work.</li>\n"
|
||||
"<li>A patch describing your changes with respect to the reference commit.</"
|
||||
"li>\n"
|
||||
"<li><strong>Check your patch does not provide any password or confidential "
|
||||
"information!</strong></li>\n"
|
||||
"</ul>"
|
||||
msgstr ""
|
||||
"<p>Para iniciar una revisión de código, debe proporcionar:</p>\n"
|
||||
"<ul>\n"
|
||||
"<li>Un commit o revisión del actual código del repositorio, desde el que ha comenzado su trabajo.</li>\n"
|
||||
"<li>Un parche que describa los cambios con respecto al commit referenciado.</li>\n"
|
||||
"<li><strong>¡Asegúrese de que el parche no contiene ninguna contraseña o información confidencial!</strong></li>\n"
|
||||
"<li>Un commit o revisión del actual código del repositorio, desde el que ha "
|
||||
"comenzado su trabajo.</li>\n"
|
||||
"<li>Un parche que describa los cambios con respecto al commit referenciado.</"
|
||||
"li>\n"
|
||||
"<li><strong>¡Asegúrese de que el parche no contiene ninguna contraseña o "
|
||||
"información confidencial!</strong></li>\n"
|
||||
"</ul>"
|
||||
|
||||
#: IDF/gettexttemplates/idf/review/create.html.php:9
|
||||
msgid ""
|
||||
"The form contains some errors. Please correct them to submit the code "
|
||||
"review."
|
||||
"The form contains some errors. Please correct them to submit the code review."
|
||||
msgstr ""
|
||||
"El formulario contiene algunos errores. Por favor, corríjalos para enviar la"
|
||||
" revisión de código."
|
||||
"El formulario contiene algunos errores. Por favor, corríjalos para enviar la "
|
||||
"revisión de código."
|
||||
|
||||
#: IDF/gettexttemplates/idf/review/create.html.php:10
|
||||
msgid ""
|
||||
"Select the commit against which you created your patch to be sure it applies"
|
||||
" correctly."
|
||||
"Select the commit against which you created your patch to be sure it applies "
|
||||
"correctly."
|
||||
msgstr ""
|
||||
"Seleccione el commit contra el que creó el parche para asegurarse de que se "
|
||||
"aplica correctamente."
|
||||
@@ -2864,11 +2901,14 @@ msgid ""
|
||||
msgstr ""
|
||||
"La revisión de código es una proceso en el que\n"
|
||||
"antes o después los cambios son commited en el código del repositorio,\n"
|
||||
"diferentes personas discuten sobre los cambios en el código. El objetivo es \n"
|
||||
"diferentes personas discuten sobre los cambios en el código. El objetivo "
|
||||
"es \n"
|
||||
"<strong>mejorar la calidad del código y las\n"
|
||||
"contribuciones</strong>, por esto, debe ser pragmático cuando escriba \n"
|
||||
"sus comentarios. Menciona correctamente los números de línea (tanto en el antiguo como en el \n"
|
||||
"nuevo código) y trata de mantener un buen equilibrio entre seriedad y diversión\n"
|
||||
"sus comentarios. Menciona correctamente los números de línea (tanto en el "
|
||||
"antiguo como en el \n"
|
||||
"nuevo código) y trata de mantener un buen equilibrio entre seriedad y "
|
||||
"diversión\n"
|
||||
|
||||
#: IDF/gettexttemplates/idf/review/view.html.php:13
|
||||
msgid ""
|
||||
@@ -2880,20 +2920,23 @@ msgid ""
|
||||
"to propose more contributions</strong>.\n"
|
||||
msgstr ""
|
||||
"\n"
|
||||
"<strong>La propuesta para revisar código es intimidante</strong>, debes saber \n"
|
||||
"que recibirás críticas, así que por favor, como revisor, <strong>haz que este \n"
|
||||
"proceso sea divertido</strong>, úsalo para para ayudar al colaborador a aprender tus \n"
|
||||
"<strong>La propuesta para revisar código es intimidante</strong>, debes "
|
||||
"saber \n"
|
||||
"que recibirás críticas, así que por favor, como revisor, <strong>haz que "
|
||||
"este \n"
|
||||
"proceso sea divertido</strong>, úsalo para para ayudar al colaborador a "
|
||||
"aprender tus \n"
|
||||
"normas de codificación y a estructurar el código y <strong>hacer que \n"
|
||||
"quieran proponer más contribuciones</strong>.\n"
|
||||
|
||||
#: IDF/gettexttemplates/idf/review/view.html.php:20
|
||||
#, php-format
|
||||
msgid ""
|
||||
"Comment <a href=\"%%url%%\">%%i%%</a> by <a href=\"%%whourl%%\">%%who%%</a>,"
|
||||
" %%c.creation_dtime%%"
|
||||
"Comment <a href=\"%%url%%\">%%i%%</a> by <a href=\"%%whourl%%\">%%who%%</a>, "
|
||||
"%%c.creation_dtime%%"
|
||||
msgstr ""
|
||||
"Comentario <a href=\"%%url%%\">%%i%%</a> por <a "
|
||||
"href=\"%%whourl%%\">%%who%%</a>, %%c.creation_dtime%%"
|
||||
"Comentario <a href=\"%%url%%\">%%i%%</a> por <a href=\"%%whourl%%\">%%who%%</"
|
||||
"a>, %%c.creation_dtime%%"
|
||||
|
||||
#: IDF/gettexttemplates/idf/review/view.html.php:21
|
||||
#, php-format
|
||||
@@ -2909,8 +2952,8 @@ msgstr "<a href=\"%%url%%\">Accede</a> para participar en la revisión."
|
||||
msgid ""
|
||||
"The form contains some errors. Please correct them to submit your review."
|
||||
msgstr ""
|
||||
"El formulario contiene algunos errores. Por favor, corríjalos para enviar su"
|
||||
" revisión."
|
||||
"El formulario contiene algunos errores. Por favor, corríjalos para enviar su "
|
||||
"revisión."
|
||||
|
||||
#: IDF/gettexttemplates/idf/review/view.html.php:27
|
||||
#: IDF/gettexttemplates/idf/source/commit.html.php:5
|
||||
@@ -3217,15 +3260,13 @@ msgstr ""
|
||||
msgid ""
|
||||
"You may need to <a href=\"%%url%%\">provide your SSH key</a>. The "
|
||||
"synchronization of your SSH key can take a couple of minutes. You can learn "
|
||||
"more about <a "
|
||||
"href=\"http://www.google.com/search?q=public+ssh+key+authentication\">SSH "
|
||||
"key authentication</a>."
|
||||
"more about <a href=\"http://www.google.com/search?q=public+ssh+key"
|
||||
"+authentication\">SSH key authentication</a>."
|
||||
msgstr ""
|
||||
"Puede que tenga que <a href=\"%%url%%\">proporcionar su clave SSH</a>. La "
|
||||
"sincronización de la clave SSH puede tomar un par de minutos. Puede saber "
|
||||
"más acerca de <a "
|
||||
"href=\"http://www.google.com/search?q=public+ssh+key+authentication\">autenticación"
|
||||
" de claves SSH</a>."
|
||||
"más acerca de <a href=\"http://www.google.com/search?q=public+ssh+key"
|
||||
"+authentication\">autenticación de claves SSH</a>."
|
||||
|
||||
#: IDF/gettexttemplates/idf/source/git/help.html.php:7
|
||||
#: IDF/gettexttemplates/idf/source/mtn/help.html.php:6
|
||||
@@ -3305,7 +3346,8 @@ msgid ""
|
||||
msgstr ""
|
||||
"Si se trata de un nuevo repositorio, la razón de este error\n"
|
||||
"podría ser que no ha realizado ningún commit y / o push hasta el momento.\n"
|
||||
"En este caso, por favor eche un vistazo a la <a href=\"%%url%%\">Página de Ayuda</a>\n"
|
||||
"En este caso, por favor eche un vistazo a la <a href=\"%%url%%\">Página de "
|
||||
"Ayuda</a>\n"
|
||||
"sobre cómo tener acceso a su repositorio."
|
||||
|
||||
#: IDF/gettexttemplates/idf/source/mercurial/help.html.php:3
|
||||
@@ -3498,8 +3540,7 @@ msgstr "Clave de API"
|
||||
msgid ""
|
||||
"Your API key will be regenerated automatically if you change your password."
|
||||
msgstr ""
|
||||
"La clave de la API se regenera automáticamente si usted cambia su "
|
||||
"contraseña."
|
||||
"La clave de la API se regenera automáticamente si usted cambia su contraseña."
|
||||
|
||||
#: IDF/gettexttemplates/idf/user/myaccount.html.php:12
|
||||
msgid "Update Your Account"
|
||||
@@ -3535,8 +3576,8 @@ msgid ""
|
||||
"API key is used to interact with this website using a program."
|
||||
msgstr ""
|
||||
"La contraseña adicional se utiliza para acceder a algunos de los sistemas "
|
||||
"externos y la clave de la API se utiliza para interactuar con este sitio web"
|
||||
" utilizando un programa."
|
||||
"externos y la clave de la API se utiliza para interactuar con este sitio web "
|
||||
"utilizando un programa."
|
||||
|
||||
#: IDF/gettexttemplates/idf/user/myaccount.html.php:20
|
||||
msgid "Show API key and extra password"
|
||||
@@ -3556,13 +3597,13 @@ msgstr "Recuperar mi contraseña"
|
||||
|
||||
#: IDF/gettexttemplates/idf/user/passrecovery-ask.html.php:6
|
||||
msgid ""
|
||||
"Provide either your login or email address, if a corresponding user is found"
|
||||
" in the database, we will send you an email with the details on how to reset"
|
||||
" your password."
|
||||
"Provide either your login or email address, if a corresponding user is found "
|
||||
"in the database, we will send you an email with the details on how to reset "
|
||||
"your password."
|
||||
msgstr ""
|
||||
"Proporcione un usuario o dirección de correo electrónico, si el usuario "
|
||||
"correspondiente se encuentra en la base de datos, le enviaremos un email con"
|
||||
" los detalles sobre cómo restablecer su contraseña."
|
||||
"correspondiente se encuentra en la base de datos, le enviaremos un email con "
|
||||
"los detalles sobre cómo restablecer su contraseña."
|
||||
|
||||
#: IDF/gettexttemplates/idf/user/passrecovery-email.txt.php:3
|
||||
#, php-format
|
||||
@@ -3688,12 +3729,15 @@ msgstr "Crear Página"
|
||||
#: IDF/gettexttemplates/idf/wiki/delete.html.php:3
|
||||
#, php-format
|
||||
msgid ""
|
||||
"You are looking at an old revision (<em>%%oldrev.summary%%</em>) of the page \n"
|
||||
"You are looking at an old revision (<em>%%oldrev.summary%%</em>) of the "
|
||||
"page \n"
|
||||
"<a href=\"%%url%%\">%%page.title%%</a>. This revision was created\n"
|
||||
"by %%submitter%%."
|
||||
msgstr ""
|
||||
"Está viendo una revisión antigua (<em>%%oldrev.summary%%</em>) de la página \n"
|
||||
"<a href=\"%%url%%\">%%page.title%%</a>. Esta revisión fue creada por %%submitter%%."
|
||||
"Está viendo una revisión antigua (<em>%%oldrev.summary%%</em>) de la "
|
||||
"página \n"
|
||||
"<a href=\"%%url%%\">%%page.title%%</a>. Esta revisión fue creada por "
|
||||
"%%submitter%%."
|
||||
|
||||
#: IDF/gettexttemplates/idf/wiki/delete.html.php:6
|
||||
msgid ""
|
||||
@@ -3720,8 +3764,8 @@ msgid ""
|
||||
"recover it</strong>."
|
||||
msgstr ""
|
||||
"Si elimina esta página de documentación, será eliminada de la base de datos "
|
||||
"con todas las revisiones relacionadas y <strong>no será capaz de "
|
||||
"recuperarla.</strong>"
|
||||
"con todas las revisiones relacionadas y <strong>no será capaz de recuperarla."
|
||||
"</strong>"
|
||||
|
||||
#: IDF/gettexttemplates/idf/wiki/deletepage.html.php:6
|
||||
msgid "Delete Page"
|
||||
@@ -3732,15 +3776,23 @@ msgstr "Eliminar página"
|
||||
msgid ""
|
||||
"\n"
|
||||
"<p><strong>Instructions:</strong></p>\n"
|
||||
"<p>The content of the page can use the <a href=\"%%burl%%\">Markdown syntax</a> with the <a href=\"%%eurl%%\"><em>Extra</em> extension</a>.</p>\n"
|
||||
"<p>Website addresses are automatically linked and you can link to another page in the documentation using double square brackets like that [[AnotherPage]].</p>\n"
|
||||
"<p>To directly include a file content from the repository, embrace its path with triple square brackets: [[[path/to/file.txt]]].</p>\n"
|
||||
"<p>The content of the page can use the <a href=\"%%burl%%\">Markdown syntax</"
|
||||
"a> with the <a href=\"%%eurl%%\"><em>Extra</em> extension</a>.</p>\n"
|
||||
"<p>Website addresses are automatically linked and you can link to another "
|
||||
"page in the documentation using double square brackets like that "
|
||||
"[[AnotherPage]].</p>\n"
|
||||
"<p>To directly include a file content from the repository, embrace its path "
|
||||
"with triple square brackets: [[[path/to/file.txt]]].</p>\n"
|
||||
msgstr ""
|
||||
"\n"
|
||||
"<p><strong>Instrucciones:</strong></p>\n"
|
||||
"<p>El contenido de la página puede usar <a href=\"%%burl%%\">sintaxis de Marcado</a> con la extensión <a href=\"%%eurl%%\"><em>Extra</em></a>.</p>\n"
|
||||
"<p>Las direcciones Web se enlazan automáticamente y se puede vincular con otras páginas de la documentación usando corchetes dobles como: [[OtraPágina]].</p>\n"
|
||||
"<p>Para incluir directamente el contenido de un fichero del repositorio, rodee la ruta con corchetes triples como: [[[ruta/al/fichero.txt]]].</p>\n"
|
||||
"<p>El contenido de la página puede usar <a href=\"%%burl%%\">sintaxis de "
|
||||
"Marcado</a> con la extensión <a href=\"%%eurl%%\"><em>Extra</em></a>.</p>\n"
|
||||
"<p>Las direcciones Web se enlazan automáticamente y se puede vincular con "
|
||||
"otras páginas de la documentación usando corchetes dobles como: "
|
||||
"[[OtraPágina]].</p>\n"
|
||||
"<p>Para incluir directamente el contenido de un fichero del repositorio, "
|
||||
"rodee la ruta con corchetes triples como: [[[ruta/al/fichero.txt]]].</p>\n"
|
||||
|
||||
#: IDF/gettexttemplates/idf/wiki/index.html.php:3
|
||||
#, php-format
|
||||
@@ -3777,7 +3829,8 @@ msgid ""
|
||||
"use it as reference only if you are sure you need these specific information."
|
||||
msgstr ""
|
||||
"<strong>¡Atención!</strong> Esta página está marcada como obsoleta,\n"
|
||||
"úsala como referencia solamente si está seguro de que usted necesita específicamente esta información ."
|
||||
"úsala como referencia solamente si está seguro de que usted necesita "
|
||||
"específicamente esta información ."
|
||||
|
||||
#: IDF/gettexttemplates/idf/wiki/view.html.php:5
|
||||
#, php-format
|
||||
@@ -3787,7 +3840,8 @@ msgid ""
|
||||
"by %%submitter%%."
|
||||
msgstr ""
|
||||
"Está viendo una revisión antigua de la página \n"
|
||||
"<a href=\"%%url%%\">%%page.title%%</a>. Esta revisión fue creada por %%submitter%%."
|
||||
"<a href=\"%%url%%\">%%page.title%%</a>. Esta revisión fue creada por "
|
||||
"%%submitter%%."
|
||||
|
||||
#: IDF/gettexttemplates/idf/wiki/view.html.php:10
|
||||
msgid "Table of Content"
|
||||
@@ -3845,8 +3899,10 @@ msgstr "fecha de modificación"
|
||||
|
||||
#: IDF/Issue.php:194 IDF/IssueComment.php:143
|
||||
#, php-format
|
||||
msgid "<a href=\"%1$s\" class=\"%2$s\" title=\"View issue\">Issue %3$d</a>, %4$s"
|
||||
msgstr "<a href=\"%1$s\" class=\"%2$s\" title=\"Ver ticket\">Ticket %3$d</a>, %4$s"
|
||||
msgid ""
|
||||
"<a href=\"%1$s\" class=\"%2$s\" title=\"View issue\">Issue %3$d</a>, %4$s"
|
||||
msgstr ""
|
||||
"<a href=\"%1$s\" class=\"%2$s\" title=\"Ver ticket\">Ticket %3$d</a>, %4$s"
|
||||
|
||||
#: IDF/Issue.php:196
|
||||
#, php-format
|
||||
@@ -4001,8 +4057,8 @@ msgstr "No se puede examinar la configuración usher en \"%s\": %s"
|
||||
#, php-format
|
||||
msgid "usher configuration already contains a server entry named \"%s\""
|
||||
msgstr ""
|
||||
"La configuración usher ya contiene una entrada para el servidor llamada "
|
||||
"\"%s\""
|
||||
"La configuración usher ya contiene una entrada para el servidor llamada \"%s"
|
||||
"\""
|
||||
|
||||
#: IDF/Plugin/SyncMonotone.php:320 IDF/Plugin/SyncMonotone.php:510
|
||||
#, php-format
|
||||
@@ -4047,7 +4103,8 @@ msgstr "No se pudo escribir read-permissions para el proyecto \"%s\""
|
||||
#: IDF/Plugin/SyncMonotone.php:617 IDF/Plugin/SyncMonotone.php:717
|
||||
#, php-format
|
||||
msgid "Could not write write-permissions file for project \"%s\""
|
||||
msgstr "No se pudo escribir el fichero write-permissions para el proyecto \"%s\""
|
||||
msgstr ""
|
||||
"No se pudo escribir el fichero write-permissions para el proyecto \"%s\""
|
||||
|
||||
#: IDF/Plugin/SyncMonotone.php:790
|
||||
#, php-format
|
||||
@@ -4106,13 +4163,17 @@ msgstr "voto"
|
||||
|
||||
#: IDF/Review/Comment.php:139 IDF/Review/Patch.php:151
|
||||
#, php-format
|
||||
msgid "<a href=\"%1$s\" class=\"%2$s\" title=\"View review\">Review %3$d</a>, %4$s"
|
||||
msgstr "<a href=\"%1$s\" class=\"%2$s\" title=\"Ver revisión\">Revisión %3$d</a>, %4$s"
|
||||
msgid ""
|
||||
"<a href=\"%1$s\" class=\"%2$s\" title=\"View review\">Review %3$d</a>, %4$s"
|
||||
msgstr ""
|
||||
"<a href=\"%1$s\" class=\"%2$s\" title=\"Ver revisión\">Revisión %3$d</a>, "
|
||||
"%4$s"
|
||||
|
||||
#: IDF/Review/Comment.php:141
|
||||
#, php-format
|
||||
msgid "Update of <a href=\"%s\" class=\"%s\">review %d</a>, by %s"
|
||||
msgstr "Actualización de <a href=\"%s\" class=\"%s\">revisión %d</a>, por %s"
|
||||
msgstr ""
|
||||
"Actualización de <a href=\"%s\" class=\"%s\">revisión %d</a>, por %s"
|
||||
|
||||
#: IDF/Review/Comment.php:151
|
||||
#, php-format
|
||||
@@ -4467,8 +4528,8 @@ msgstr "Lista de mantenimiento: Tickets Cerrados por %s"
|
||||
#, php-format
|
||||
msgid "This table shows the closed issues in your watch list for %s project."
|
||||
msgstr ""
|
||||
"Esta tabla muestra los tickets cerrados en su lista de mantenimiento para el"
|
||||
" proyecto %s."
|
||||
"Esta tabla muestra los tickets cerrados en su lista de mantenimiento para el "
|
||||
"proyecto %s."
|
||||
|
||||
#: IDF/Views/Issue.php:118
|
||||
#, php-format
|
||||
@@ -4479,8 +4540,8 @@ msgstr "Lista mantenimiento: Tickets Abiertos por %s"
|
||||
#, php-format
|
||||
msgid "This table shows the open issues in your watch list for %s project."
|
||||
msgstr ""
|
||||
"Esta tabla muestra los tickets abiertos en su lista de mantenimiento para el"
|
||||
" proyecto %s."
|
||||
"Esta tabla muestra los tickets abiertos en su lista de mantenimiento para el "
|
||||
"proyecto %s."
|
||||
|
||||
#: IDF/Views/Issue.php:195
|
||||
msgid "Watch List: Closed Issues"
|
||||
@@ -4856,8 +4917,7 @@ msgid "Confirm Your Account Creation"
|
||||
msgstr "Confirma la creación de tu cuenta"
|
||||
|
||||
#: IDF/Views.php:172
|
||||
msgid ""
|
||||
"Welcome! You can now participate in the life of your project of choice."
|
||||
msgid "Welcome! You can now participate in the life of your project of choice."
|
||||
msgstr "¡Bienvenido! Ahora puedes participar en el proyecto elegido."
|
||||
|
||||
#: IDF/Views.php:198 IDF/Views.php:222 IDF/Views.php:263
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -45,6 +45,7 @@ $m['IDF_Scm_Cache_Git'] = array('relate_to' => array('IDF_Project'));
|
||||
|
||||
$m['IDF_UserData'] = array('relate_to' => array('Pluf_User'));
|
||||
$m['IDF_EmailAddress'] = array('relate_to' => array('Pluf_User'));
|
||||
$m['IDF_IssueRelation'] = array('relate_to' => array('IDF_Issue', 'Pluf_User'));
|
||||
|
||||
Pluf_Signal::connect('Pluf_Template_Compiler::construct_template_tags_modifiers',
|
||||
array('IDF_Middleware', 'updateTemplateTagsModifiers'));
|
||||
|
@@ -70,7 +70,6 @@
|
||||
<div id="ft">{block foot}{/block}</div>
|
||||
</div>
|
||||
{include 'idf/js-hotkeys.html'}
|
||||
{include 'idf/list-filter.html'}
|
||||
{block javascript}{/block}
|
||||
{if $project}
|
||||
<script type="text/javascript" charset="utf-8">{literal}
|
||||
|
@@ -49,7 +49,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="yui-b context">{block context}{/block}</div>
|
||||
<div class="yui-b context" id="context">{block context}{/block}</div>
|
||||
</div>
|
||||
<div id="ft">{block foot}{/block}</div>
|
||||
</div>
|
||||
|
@@ -66,7 +66,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="yui-b context">{block context}{/block}</div>
|
||||
<div class="yui-b context" id="context">{block context}{/block}</div>
|
||||
</div>
|
||||
<div id="ft">{block foot}{/block}</div>
|
||||
</div>
|
||||
@@ -84,6 +84,21 @@ $(document).ready(function(){
|
||||
else if (frag.length > 3 && frag.substring(0, 3) == '#ic') {
|
||||
$(frag).addClass("issue-comment-focus");
|
||||
}
|
||||
|
||||
var contextTop = $('div#context').position().top;
|
||||
var contextFixEnabled = true;
|
||||
$(window).scroll(function() {
|
||||
if (!contextFixEnabled || $(window).scrollTop() < contextTop)
|
||||
$('div#context').css('position', 'relative');
|
||||
else
|
||||
$('div#context').css('position', 'fixed');
|
||||
});
|
||||
$(window).resize(function() {
|
||||
contextFixEnabled =
|
||||
$('div#context').offset().top + $('div#context').height() <
|
||||
$(window).height();
|
||||
});
|
||||
$(window).resize();
|
||||
});
|
||||
//]]>{/literal}
|
||||
</script>{/if}
|
||||
|
@@ -3,7 +3,7 @@
|
||||
{block body}
|
||||
|
||||
<div class="download-file">
|
||||
<a href="{url 'IDF_Views_Download::download', array($project.shortname, $file.id)}">{$file}</a> - {$file.filesize|size}
|
||||
<a href="{url 'IDF_Views_Download::download', array($project.shortname, $file.file)}">{$file}</a> - {$file.filesize|size}
|
||||
</div>
|
||||
|
||||
<p>{blocktrans}<strong>Attention!</strong> If you want to delete a specific version of your software, maybe, someone is depending on this specific version to run his systems. Are you sure, you will not affect anybody when removing this file?{/blocktrans}</p>
|
||||
@@ -15,7 +15,7 @@
|
||||
<table class="form" summary="">
|
||||
<tr>
|
||||
<td> </td>
|
||||
<td><input type="submit" value="{trans 'Delete File'}" name="submit" /> | <a href="{url 'IDF_Views_Download::index', array($project.shortname)}">{trans 'Cancel'}</a>
|
||||
<td><input type="submit" value="{trans 'Delete File'}" name="submit" /> | <a href="{url 'IDF_Views_Download::index', array($project.shortname)}">{trans 'Cancel'}</a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
@@ -4,7 +4,9 @@
|
||||
|
||||
<div class="download-file">
|
||||
{if $deprecated}<p class="smaller">{blocktrans}<strong>Attention!</strong> This file is marked as deprecated, download it only if you are sure you need this specific version.{/blocktrans}</p>{/if}
|
||||
<a href="{url 'IDF_Views_Download::download', array($project.shortname, $file.id)}">{$file}</a> - {$file.filesize|size}
|
||||
<a href="{url 'IDF_Views_Download::download', array($project.shortname, $file.file)}">{$file}</a> - {$file.filesize|size}
|
||||
<br />
|
||||
<span class="helptext">{trans 'md5:'} {$file.md5}</span>
|
||||
</div>
|
||||
{if $file.changelog}
|
||||
<h2 class="changes">{trans 'Changes'}</h2>
|
||||
|
@@ -8,12 +8,18 @@
|
||||
<th>{trans "address"}</th>
|
||||
<th>{trans "port"}</th>
|
||||
</tr>
|
||||
{if count($connections) == 0}
|
||||
<tr>
|
||||
<td colspan="2" align="center">{trans 'No connections found.'}</td>
|
||||
</tr>
|
||||
{else}
|
||||
{foreach $connections as $connection}
|
||||
<tr>
|
||||
<td>{$connection.address}</td>
|
||||
<td>{$connection.port}</td>
|
||||
</tr>
|
||||
{/foreach}
|
||||
{/if}
|
||||
</table>
|
||||
{/block}
|
||||
|
||||
|
@@ -9,6 +9,11 @@
|
||||
<th>{trans "status"}</th>
|
||||
<th>{trans "action"}</th>
|
||||
</tr>
|
||||
{if count($servers) == 0}
|
||||
<tr>
|
||||
<td colspan="3" align="center">{trans 'No monotone servers configured.'}</td>
|
||||
</tr>
|
||||
{else}
|
||||
{foreach $servers as $server}
|
||||
<tr>
|
||||
<td>{$server.name}</td>
|
||||
@@ -31,6 +36,7 @@
|
||||
{/if}
|
||||
</tr>
|
||||
{/foreach}
|
||||
{/if}
|
||||
</table>
|
||||
{/block}
|
||||
|
||||
|
@@ -2,7 +2,8 @@
|
||||
{block tabissues} class="active"{/block}
|
||||
{block subtabs}
|
||||
<div id="sub-tabs">
|
||||
<a {if $inOpenIssues}class="active" {/if}href="{url 'IDF_Views_Issue::index', array($project.shortname)}">{trans 'Open Issues'}</a>
|
||||
<a {if $inSummaryIssues}class="active" {/if}href="{url 'IDF_Views_Issue::summary', array($project.shortname)}">{trans 'Summary'}</a>
|
||||
| <a {if $inOpenIssues}class="active" {/if}href="{url 'IDF_Views_Issue::index', array($project.shortname)}">{trans 'Open Issues'}</a>
|
||||
{if !$user.isAnonymous()} | <a {if $inCreate}class="active" {/if}href="{url 'IDF_Views_Issue::create', array($project.shortname)}">{trans 'New Issue'}</a> | <a {if $inMyIssues}class="active" {/if}href="{url 'IDF_Views_Issue::myIssues', array($project.shortname, 'submit')}">{trans 'My Issues'}</a>
|
||||
| <a {if $inWatchList}class="active" {/if}href="{url 'IDF_Views_Issue::watchList', array($project.shortname, 'open')}">{trans 'My watch list'}</a>{/if} |
|
||||
<form class="star" action="{url 'IDF_Views_Issue::search', array($project.shortname)}" method="get">
|
||||
|
@@ -63,12 +63,12 @@
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{$form.f.relation_type.labelTag}:</th>
|
||||
<th>{$form.f.relation_type0.labelTag}:</th>
|
||||
<td>
|
||||
{if $form.f.relation_type.errors}{$form.f.relation_type.fieldErrors}{/if}
|
||||
{if $form.f.relation_issue.errors}{$form.f.relation_issue.fieldErrors}{/if}
|
||||
{$form.f.relation_type|unsafe}
|
||||
{$form.f.relation_issue|unsafe}
|
||||
{if $form.f.relation_type0.errors}{$form.f.relation_type0.fieldErrors}{/if}
|
||||
{if $form.f.relation_issue0.errors}{$form.f.relation_issue0.fieldErrors}{/if}
|
||||
{$form.f.relation_type0|unsafe}
|
||||
{$form.f.relation_issue0|unsafe}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
|
@@ -51,33 +51,39 @@
|
||||
return row.to;
|
||||
}
|
||||
});
|
||||
$("#id_relation_type").autocomplete(auto_relation_types, {
|
||||
minChars: 0,
|
||||
width: 310,
|
||||
matchContains: true,
|
||||
max: 50,
|
||||
highlightItem: false,
|
||||
formatItem: function(row, i, max, term) {
|
||||
return row.to.replace(new RegExp("(" + term + ")", "gi"), "<strong>$1</strong>") + " <span style='font-size: 80%;'>" + row.name + "</span>";
|
||||
},
|
||||
formatResult: function(row) {
|
||||
return row.to;
|
||||
}
|
||||
});
|
||||
$("#id_relation_issue").autocomplete("{/literal}{url 'IDF_Views_Issue::autoCompleteIssueList', array($project.shortname)}{literal}", {
|
||||
minChars: 0,
|
||||
width: 310,
|
||||
matchContains: true,
|
||||
max: 10,
|
||||
delay: 500,
|
||||
highlightItem: false,
|
||||
formatItem: function(row, i, max, term) {
|
||||
return row[1].replace(new RegExp("(" + term + ")", "gi"), "<strong>$1</strong>") + " <span style='font-size: 80%;'>" + row[0] + "</span>";
|
||||
},
|
||||
formatResult: function(row) {
|
||||
return row[1];
|
||||
}
|
||||
});
|
||||
for (var idx = 0; ; ++idx) {
|
||||
if ($("#id_relation_type" + idx).length == 0)
|
||||
break;
|
||||
|
||||
$("#id_relation_type" + idx).autocomplete(auto_relation_types, {
|
||||
minChars: 0,
|
||||
width: 310,
|
||||
matchContains: true,
|
||||
max: 50,
|
||||
highlightItem: false,
|
||||
formatItem: function(row, i, max, term) {
|
||||
return row.to.replace(new RegExp("(" + term + ")", "gi"), "<strong>$1</strong>") + " <span style='font-size: 80%;'>" + row.name + "</span>";
|
||||
},
|
||||
formatResult: function(row) {
|
||||
return row.to;
|
||||
}
|
||||
});
|
||||
$("#id_relation_issue" + idx).autocomplete("{/literal}{url 'IDF_Views_Issue::autoCompleteIssueList', array($project.shortname, $issue.id)}{literal}", {
|
||||
minChars: 0,
|
||||
width: 310,
|
||||
matchContains: true,
|
||||
max: 10,
|
||||
multiple: true,
|
||||
delay: 500,
|
||||
highlightItem: false,
|
||||
formatItem: function(row, i, max, term) {
|
||||
return row[1].replace(new RegExp("(" + term + ")", "gi"), "<strong>$1</strong>") + " <span style='font-size: 80%;'>" + row[0] + "</span>";
|
||||
},
|
||||
formatResult: function(row) {
|
||||
return row[1];
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
{/literal} //-->
|
||||
</script>
|
||||
|
95
src/IDF/templates/idf/issues/summary.html
Normal file
95
src/IDF/templates/idf/issues/summary.html
Normal file
@@ -0,0 +1,95 @@
|
||||
{extends "idf/issues/base.html"}
|
||||
|
||||
{block docclass}yui-t2{assign $inSummaryIssues=true}{/block}
|
||||
|
||||
{block body}
|
||||
{if $trackerEmpty}
|
||||
{aurl 'create_url', 'IDF_Views_Issue::create', array($project.shortname)}
|
||||
<p>{blocktrans}The issue tracker is empty.<br />You can create your first issue <a href="{$create_url}">here</a>.{/blocktrans}</p>
|
||||
{else}
|
||||
<div class='issue-summary'>
|
||||
{foreach $tagStatistics as $key => $class}
|
||||
<div>
|
||||
<h2>{blocktrans}Unresolved: By {$key}{/blocktrans}</h2>
|
||||
<table class='issue-summary'>
|
||||
<tbody>
|
||||
{foreach $class as $key => $value}
|
||||
<tr>
|
||||
<td class="name"><a href="{url 'IDF_Views_Issue::listLabel', array($project.shortname, $value[2], 'open')}">{$key}</a></td>
|
||||
<td class="count">{$value[0]}</td>
|
||||
<td class="graph">
|
||||
<table class='graph'>
|
||||
<tbody><tr>
|
||||
<td style="width:{$value[1] * 0.8 + 1}%" class="graph-color" valign="center">
|
||||
<div class="colour-bar"></div>
|
||||
</td>
|
||||
<td class="graph-percent">{$value[1]}%</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
{/foreach}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{/foreach}
|
||||
</div>
|
||||
|
||||
<div class='issue-summary'>
|
||||
{if $status}
|
||||
<div>
|
||||
<h2>{blocktrans}Status Summary{/blocktrans}</h2>
|
||||
<table class='issue-summary'>
|
||||
<tbody>
|
||||
{foreach $status as $key => $value}
|
||||
<tr>
|
||||
<td class="name"><a href="{url 'IDF_Views_Issue::listStatus', array($project.shortname, $key)}">{$key}</a></td>
|
||||
<td class="count">{$value[0]}</td>
|
||||
<td class="graph">
|
||||
<table class='graph'>
|
||||
<tbody><tr>
|
||||
<td style="width:{$value[1] * 0.8 + 1}%" class="graph-color" valign="center">
|
||||
<div class="colour-bar"></div>
|
||||
</td>
|
||||
<td class="graph-percent">{$value[1]}%</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
{/foreach}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{if $ownerStatistics}
|
||||
<div>
|
||||
<h2>{blocktrans}Unresolved: By Assignee{/blocktrans}</h2>
|
||||
<table class='issue-summary'>
|
||||
<tbody>
|
||||
{foreach $ownerStatistics as $key => $value}
|
||||
<tr>
|
||||
<td class="name">{$key}</td>
|
||||
<td class="count">{$value[0]}</td>
|
||||
<td class="graph">
|
||||
<table class='graph'>
|
||||
<tbody><tr>
|
||||
<td style="width:{$value[1] * 0.8 + 1}%" class="graph-color" valign="center">
|
||||
<div class="colour-bar"></div>
|
||||
</td>
|
||||
<td class="graph-percent">{$value[1]}%</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
{/foreach}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
{/block}
|
@@ -40,7 +40,16 @@
|
||||
{if $i> 0 and $c.changedIssue()}
|
||||
<div class="issue-changes">
|
||||
{foreach $c.changes as $w => $v}
|
||||
<strong>{if $w == 'su'}{trans 'Summary:'}{/if}{if $w == 'st'}{trans 'Status:'}{/if}{if $w == 'ow'}{trans 'Owner:'}{/if}{if $w == 'lb'}{trans 'Labels:'}{/if}</strong> {if $w == 'lb'}{assign $l = implode(', ', $v)}{$l}{else}{$v}{/if}<br />
|
||||
<strong>{if $w == 'su'}{trans 'Summary:'}{/if}{if $w == 'st'}{trans 'Status:'}{/if}{if $w == 'ow'}{trans 'Owner:'}{/if}{if $w == 'lb'}{trans 'Labels:'}{/if}{if $w == 'rel'}{trans 'Relations:'}{/if}</strong>
|
||||
{if $w == 'lb' or $w == 'rel'}
|
||||
{foreach $v as $t => $ls}
|
||||
{foreach $ls as $l}
|
||||
{if $t == 'rem'}<s>{/if}{$l}{if $t == 'rem'}</s>{/if}
|
||||
{/foreach}
|
||||
{/foreach}
|
||||
{else}
|
||||
{$v}
|
||||
{/if}<br />
|
||||
{/foreach}
|
||||
</div>
|
||||
{/if}
|
||||
@@ -120,6 +129,23 @@
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{$form.f.relation_type0.labelTag}:</th>
|
||||
<td>
|
||||
{assign $prevField}
|
||||
{foreach $form as $field}
|
||||
{if strpos($field.name, 'relation_type') === 0}
|
||||
{$field|unsafe}
|
||||
{assign $prevField = $field}
|
||||
{/if}
|
||||
{if strpos($field.name, 'relation_issue') === 0}
|
||||
{$field|unsafe}<br />
|
||||
{if $prevField.errors}{$prevField.fieldErrors}{/if}
|
||||
{if $field.errors}{$field.fieldErrors}{/if}
|
||||
{/if}
|
||||
{/foreach}
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{$form.f.label1.labelTag}:</th>
|
||||
<td>
|
||||
{if $form.f.label1.errors}{$form.f.label1.fieldErrors}{/if}{$form.f.label1|unsafe}
|
||||
@@ -161,6 +187,21 @@
|
||||
<span class="label"><a href="{$url}" class="label"><strong>{$tag.class}:</strong>{$tag.name}</a></span><br />
|
||||
{/foreach}
|
||||
</p>{/if}
|
||||
{if count($related_issues) > 0}
|
||||
{foreach $related_issues as $verb => $rel_issues}
|
||||
<p>
|
||||
<strong>{blocktrans}This issue {$verb}{/blocktrans}</strong><br />
|
||||
{foreach $rel_issues as $rel_issue}
|
||||
<span class="label">
|
||||
<a href="{url 'IDF_Views_Issue::view', array($project.shortname, $rel_issue.other_issue)}"
|
||||
class="label" title="{$rel_issue.other_summary}">
|
||||
<strong>{$rel_issue.other_issue}</strong> - {$rel_issue.other_summary|shorten:30}
|
||||
</a>
|
||||
</span><br />
|
||||
{/foreach}
|
||||
</p>
|
||||
{/foreach}
|
||||
{/if}
|
||||
</div>
|
||||
{/block}
|
||||
{block javascript}{if $form}{include 'idf/issues/js-autocomplete.html'}
|
||||
|
@@ -21,7 +21,9 @@
|
||||
{/if}
|
||||
{/foreach}
|
||||
</p>
|
||||
<p><strong>Subscribe to this timeline</strong><br /><img src="{media '/idf/img/rss.png'}" alt="{trans 'RSS'}" /> <a href="{$feedurl}" >Atom feeds</a></p>
|
||||
<p><strong>{trans 'Subscribe to this timeline'}</strong><br />
|
||||
<span class="label"><img src="{media '/idf/img/rss.png'}" alt="{trans 'RSS'}" /> <a href="{$feedurl}">{trans 'Atom feed'}</a></span>
|
||||
</p>
|
||||
{/block}
|
||||
|
||||
|
||||
|
@@ -34,6 +34,9 @@
|
||||
{foreach $changes.renames as $oldname => $newname}
|
||||
<tr><td><span class="scm-action renamed" title="{trans 'renamed'}">R</span></td><td><a href="{url 'IDF_Views_Source::tree', array($project.shortname, $commit, $newname)}">{$oldname} → {$newname}</a></td></tr>
|
||||
{/foreach}
|
||||
{foreach $changes.copies as $srcname => $destname}
|
||||
<tr><td><span class="scm-action copied" title="{trans 'copied'}">C</span></td><td><a href="{url 'IDF_Views_Source::tree', array($project.shortname, $commit, $destname)}">{$srcname} → {$destname}</a></td></tr>
|
||||
{/foreach}
|
||||
{foreach $changes.additions as $filename}
|
||||
<tr><td><span class="scm-action added" title="{trans 'added'}">A</span></td><td><a href="{url 'IDF_Views_Source::tree', array($project.shortname, $commit, $filename)}">{$filename}</a>{if !empty($diff.files[$filename])} (<a href="#diff-{$filename|md5}">{trans 'full'}</a>){/if}</td></tr>
|
||||
{/foreach}
|
||||
|
2
src/IDF/templates/idf/source/git/invalid_revision.html
Normal file
2
src/IDF/templates/idf/source/git/invalid_revision.html
Normal file
@@ -0,0 +1,2 @@
|
||||
{extends "idf/source/invalid_revision.html"}
|
||||
|
@@ -32,13 +32,13 @@
|
||||
<tr>
|
||||
<td class="fileicon"><img src="{media '/idf/img/'~$file.type~'.png'}" alt="{$file.type}" /></td>
|
||||
{if $file.type != 'extern'}
|
||||
<td{if $file.type == 'tree'} colspan="4"{/if}><a href="{$url}">{$file.file}</a></td>{else}<td><a href="#" title="{$file.hash}">{$file.file}</a></td>{/if}
|
||||
<td{if $file.type == 'tree'} colspan="4"{/if}><a href="{$url}"><nobr>{$file.file}</nobr></a></td>{else}<td><a href="#" title="{$file.hash}"><nobr>{$file.file}</nobr></a></td>{/if}
|
||||
{if $file.type == 'blob'}
|
||||
{if isset($file.date) and $file.log != '----'}
|
||||
<td><span class="smaller">{$file.date|dateago:"without"}</span></td>
|
||||
<td><span class="smaller"><nobr>{$file.date|dateago:"without"}</nobr></span></td>
|
||||
<td><span class="smaller">{$file.author|strip_tags|trim}{trans ':'} {issuetext $file.log, $request, true, false}</span></td>
|
||||
{else}<td colspan="2"></td>{/if}
|
||||
<td>{$file.size|size}</td>{/if}
|
||||
<td><nobr>{$file.size|size}</nobr></td>{/if}
|
||||
{if $file.type == 'extern'}
|
||||
<td colspan="3">{$file.extern}</td>
|
||||
{/if}
|
||||
|
@@ -5,6 +5,7 @@
|
||||
<p>{blocktrans}The branch or revision <b>{$commit}</b> is not valid or does not exist
|
||||
in this repository.{/blocktrans}</p>
|
||||
|
||||
{if count($branches) > 0}
|
||||
<p>{blocktrans}The following list shows all available branches:{/blocktrans}</p>
|
||||
<ul>
|
||||
{foreach $branches as $branch => $path}
|
||||
@@ -14,6 +15,7 @@ in this repository.{/blocktrans}</p>
|
||||
</li>
|
||||
{/foreach}
|
||||
</ul>
|
||||
{/if}
|
||||
|
||||
{if $isOwner or $isMember}
|
||||
{aurl 'url', 'IDF_Views_Source::help', array($project.shortname)}
|
||||
|
@@ -0,0 +1,2 @@
|
||||
{extends "idf/source/invalid_revision.html"}
|
||||
|
@@ -5,12 +5,25 @@
|
||||
<h2 class="top"><a href="{url 'IDF_Views_Source::treeBase', array($project.shortname, $commit)}">{trans 'Root'}</a><span class="sep">/</span>{if $breadcrumb}{$breadcrumb|safe}{/if}</h2>
|
||||
|
||||
<table class="code" summary=" ">
|
||||
{if !$tree_in and !$tags_in}
|
||||
{if (!$tree_in and !$tags_in) or $props}
|
||||
{aurl 'url', 'IDF_Views_Source::commit', array($project.shortname, $commit)}
|
||||
<tfoot>
|
||||
<tr><th colspan="2">{blocktrans}Source at commit <a class="mono" href="{$url}">{$commit}</a> created {$cobject.date|dateago}.{/blocktrans}<br/>
|
||||
<span class="smaller">{blocktrans}By {$cobject.author|strip_tags|trim}, {$cobject.title}{/blocktrans}</span>
|
||||
</th></tr>
|
||||
{if $props}
|
||||
<tr><th colspan="2">
|
||||
<ul>
|
||||
{foreach $props as $prop => $val}
|
||||
<li>{blocktrans}Property <strong>{$prop}</strong> set to <em>{$val}</em>{/blocktrans}</li>
|
||||
{/foreach}
|
||||
</ul>
|
||||
</th></tr>
|
||||
{/if}
|
||||
{if !$tree_in and !$tags_in}
|
||||
<tr>
|
||||
<th colspan="2">{blocktrans}Source at commit <a class="mono" href="{$url}">{$commit}</a> created {$cobject.date|dateago}.{/blocktrans}<br/>
|
||||
<span class="smaller">{blocktrans}By {$cobject.author|strip_tags|trim}, {$cobject.title}{/blocktrans}</span>
|
||||
</th>
|
||||
</tr>
|
||||
{/if}
|
||||
</tfoot>
|
||||
{/if}
|
||||
<tbody>
|
||||
|
2
src/IDF/templates/idf/source/mtn/invalid_revision.html
Normal file
2
src/IDF/templates/idf/source/mtn/invalid_revision.html
Normal file
@@ -0,0 +1,2 @@
|
||||
{extends "idf/source/invalid_revision.html"}
|
||||
|
@@ -11,14 +11,27 @@
|
||||
<th>{trans 'Message'}</th>
|
||||
<th>{trans 'Size'}</th>
|
||||
</tr>
|
||||
</thead>{if !$tree_in and !$tags_in}
|
||||
</thead>
|
||||
{if (!$tree_in and !$tags_in) or $props}
|
||||
{aurl 'url', 'IDF_Views_Source::commit', array($project.shortname, $commit)}
|
||||
<tfoot>
|
||||
<tr><th colspan="5">{blocktrans}Source at commit <a class="mono" href="{$url}">{$commit}</a> created {$cobject.date|dateago}.{/blocktrans}<br/>
|
||||
<span class="smaller">{blocktrans}By {$cobject.author|strip_tags|trim}, {$cobject.title}{/blocktrans}</span>
|
||||
</th></tr>
|
||||
{if $props}
|
||||
<tr><th colspan="5">
|
||||
<ul>
|
||||
{foreach $props as $prop => $val}
|
||||
<li>{blocktrans}Property <strong>{$prop}</strong> set to <em>{$val}</em>{/blocktrans}</li>
|
||||
{/foreach}
|
||||
</ul>
|
||||
</th></tr>
|
||||
{/if}
|
||||
{if !$tree_in and !$tags_in}
|
||||
<tr><th colspan="5">{blocktrans}Source at commit <a class="mono" href="{$url}">{$commit}</a> created {$cobject.date|dateago}.{/blocktrans}<br/>
|
||||
<span class="smaller">{blocktrans}By {$cobject.author|strip_tags|trim}, {$cobject.title}{/blocktrans}</span>
|
||||
</th></tr>
|
||||
{/if}
|
||||
{/if}
|
||||
</tfoot>
|
||||
{/if}<tbody>
|
||||
<tbody>
|
||||
{if $base}
|
||||
<tr>
|
||||
<td> </td>
|
||||
|
@@ -4,7 +4,7 @@
|
||||
<p><strong>{trans 'Revision:'}</strong> {$commit}</p>
|
||||
<p>
|
||||
<input accesskey="4" type="text" value="{$commit}" name="rev" size="5" />
|
||||
<input type="submit" name="s" value="{trans 'Go to revision'}" />
|
||||
<input type="submit" name="s" value="{trans 'Switch'}" />
|
||||
</p>
|
||||
</form>
|
||||
{/block}
|
||||
|
@@ -4,7 +4,7 @@
|
||||
<p><strong>{trans 'Revision:'}</strong> {$commit}</p>
|
||||
<p>
|
||||
<input accesskey="4" type="text" value="{$commit}" name="rev" size="5"/>
|
||||
<input type="submit" name="s" value="{trans 'Go to revision'}"/>
|
||||
<input type="submit" name="s" value="{trans 'Switch'}"/>
|
||||
</p>
|
||||
</form>
|
||||
{/block}
|
||||
|
@@ -6,13 +6,13 @@
|
||||
|
||||
<table class="code" summary=" ">
|
||||
{if !$tree_in || $props}
|
||||
{aurl 'url', 'IDF_Views_Source::commit', array($project.shortname, $commit)}
|
||||
{aurl 'url', 'IDF_Views_Source::commit', array($project.shortname, $commit)}
|
||||
<tfoot>
|
||||
{if $props}
|
||||
<tr><th colspan="2">
|
||||
<ul>
|
||||
{foreach $props as $prop => $val}
|
||||
<li>{trans 'Property'} <strong>{$prop}</strong> {trans 'set to:'} <em>{$val}</em></li>
|
||||
<li>{blocktrans}Property <strong>{$prop}</strong> set to <em>{$val}</em>{/blocktrans}</li>
|
||||
{/foreach}
|
||||
</ul>
|
||||
</th></tr>
|
||||
@@ -38,7 +38,7 @@
|
||||
<p>
|
||||
<input accesskey="4" type="text" value="{$commit}" name="rev" size="5" />
|
||||
<input type="hidden" name="sourcefile" value="{$base}"/>
|
||||
<input type="submit" name="s" value="{trans 'Go to revision'}" /></p>
|
||||
<input type="submit" name="s" value="{trans 'Switch'}" /></p>
|
||||
</form>
|
||||
{/block}
|
||||
|
||||
|
30
src/IDF/templates/idf/source/svn/invalid_revision.html
Normal file
30
src/IDF/templates/idf/source/svn/invalid_revision.html
Normal file
@@ -0,0 +1,30 @@
|
||||
{extends "idf/source/base.html"}
|
||||
{block docclass}yui-t2{assign $inError=true}{/block}
|
||||
{block body}
|
||||
|
||||
<p>{blocktrans}The revision <b>{$commit}</b> is not valid or does not exist
|
||||
in this repository.{/blocktrans}</p>
|
||||
|
||||
{if count($branches) > 0}
|
||||
<p>{blocktrans}The following list shows all available branches:{/blocktrans}</p>
|
||||
<ul>
|
||||
{foreach $branches as $branch => $path}
|
||||
{if $path}{aurl 'url', 'IDF_Views_Source::tree', array($project.shortname, 'HEAD', $path)}
|
||||
{else}{aurl 'url', 'IDF_Views_Source::treeBase', array($project.shortname, 'HEAD')}{/if}
|
||||
<li class="label">
|
||||
<a href="{$url}" class="label">{$branch}</a>
|
||||
</li>
|
||||
{/foreach}
|
||||
</ul>
|
||||
{/if}
|
||||
|
||||
{if $isOwner or $isMember}
|
||||
{aurl 'url', 'IDF_Views_Source::help', array($project.shortname)}
|
||||
<p>{blocktrans}If this is a new repository, the reason for this error
|
||||
could be that you have not committed and / or pushed any change so far.
|
||||
In this case please take a look at the <a href="{$url}">Help</a> page
|
||||
how to access your repository.{/blocktrans}</p>
|
||||
{/if}
|
||||
|
||||
{/block}
|
||||
|
@@ -13,13 +13,13 @@
|
||||
<th>{trans 'Size'}</th>
|
||||
</tr>
|
||||
</thead>{if (!$tree_in and !$tags_in and $commit != 'HEAD') || $props}
|
||||
{aurl 'url', 'IDF_Views_Source::commit', array($project.shortname, $commit)}
|
||||
{aurl 'url', 'IDF_Views_Source::commit', array($project.shortname, $commit)}
|
||||
<tfoot>
|
||||
{if $props}
|
||||
<tr><th colspan="6">
|
||||
<ul>
|
||||
{foreach $props as $prop => $val}
|
||||
<li>{trans 'Property'} <strong>{$prop}</strong> {trans 'set to:'} <em>{$val}</em></li>
|
||||
<li>{blocktrans}Property <strong>{$prop}</strong> set to <em>{$val}</em>{/blocktrans}</li>
|
||||
{/foreach}
|
||||
</ul>
|
||||
</th></tr>
|
||||
@@ -45,7 +45,7 @@
|
||||
<td class="fileicon"><img src="{media '/idf/img/'~$file.type~'.png'}" alt="{$file.type}" /></td>
|
||||
|
||||
<td><a href="{$url}">{$file.file}</a></td>
|
||||
<td><span class="smaller">{$file.date|dateago:"without"}</span></td>
|
||||
<td><span class="smaller">{$file.date|dateago:"without"}</span></td>
|
||||
<td>{$file.rev}</td>
|
||||
<td{if $file.type != 'blob'} colspan="2"{/if}><span class="smaller">{$file.author|strip_tags|trim}{trans ':'} {issuetext $file.log, $request, true, false}</span></td>
|
||||
{if $file.type == 'blob'}
|
||||
@@ -66,7 +66,7 @@
|
||||
<p>
|
||||
<input accesskey="4" type="text" value="{$commit}" name="rev" size="5" />
|
||||
<input type="hidden" name="sourcefile" value="{$base}"/>
|
||||
<input type="submit" name="s" value="{trans 'Go to revision'}" /></p>
|
||||
<input type="submit" name="s" value="{trans 'Switch'}" /></p>
|
||||
</form>
|
||||
<p><strong>{trans 'Branches:'}</strong><br />
|
||||
{foreach $branches as $branch => $path}
|
||||
|
90
test/IDF/ProjectTest.php
Normal file
90
test/IDF/ProjectTest.php
Normal file
@@ -0,0 +1,90 @@
|
||||
<?php
|
||||
/* -*- tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# This file is part of InDefero, an open source project management application.
|
||||
# Copyright (C) 2008-2011 Céondo Ltd and contributors.
|
||||
#
|
||||
# InDefero 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.
|
||||
#
|
||||
# InDefero 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 St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
#
|
||||
# ***** END LICENSE BLOCK ***** */
|
||||
|
||||
class IDF_ProjectTest extends PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function testGetIssueCountByOwner()
|
||||
{
|
||||
// Add users
|
||||
$user1 = new Pluf_User();
|
||||
$user1->login = 'user1';
|
||||
$user1->create();
|
||||
$user2 = new Pluf_User();
|
||||
$user2->login = 'user2';
|
||||
$user2->create();
|
||||
|
||||
// Add a project
|
||||
$prj = new IDF_Project();
|
||||
$prj->create();
|
||||
$tag = $prj->getTagIdsByStatus('open');
|
||||
|
||||
// First test with no issue
|
||||
$stats = $prj->getIssueCountByOwner();
|
||||
$this->assertEquals($stats, array());
|
||||
|
||||
// Add some issues
|
||||
$issue1 = new IDF_Issue();
|
||||
$issue1->project = $prj;
|
||||
$issue1->submitter = $user1;
|
||||
$issue1->owner = $user1;
|
||||
$issue1->status = new IDF_Tag($tag[0]);
|
||||
$issue1->create();
|
||||
|
||||
$issue2 = new IDF_Issue();
|
||||
$issue2->project = $prj;
|
||||
$issue2->submitter = $user2;
|
||||
$issue2->owner = $user1;
|
||||
$issue2->status = new IDF_Tag($tag[0]);
|
||||
$issue2->create();
|
||||
|
||||
$issue3 = new IDF_Issue();
|
||||
$issue3->project = $prj;
|
||||
$issue3->submitter = $user2;
|
||||
$issue3->status = new IDF_Tag($tag[0]);
|
||||
$issue3->create();
|
||||
|
||||
$issue4 = new IDF_Issue();
|
||||
$issue4->project = $prj;
|
||||
$issue4->submitter = $user2;
|
||||
$issue4->owner = $user2;
|
||||
$issue4->status = new IDF_Tag($tag[0]);
|
||||
$issue4->create();
|
||||
|
||||
// 2nd test
|
||||
$stats = $prj->getIssueCountByOwner();
|
||||
$expected = array(0 => 1,
|
||||
$user2->id => 1,
|
||||
$user1->id => 2);
|
||||
$this->assertEquals($stats, $expected);
|
||||
|
||||
// Clean DB
|
||||
$issue4->delete();
|
||||
$issue3->delete();
|
||||
$issue2->delete();
|
||||
$issue1->delete();
|
||||
$prj->delete();
|
||||
$user2->delete();
|
||||
$user1->delete();
|
||||
}
|
||||
}
|
||||
|
@@ -714,6 +714,31 @@ END;
|
||||
$this->assertEquals('', $commit->diff);
|
||||
}
|
||||
|
||||
public function testGetProperties()
|
||||
{
|
||||
$rev = "2345678901234567890123456789012345678901";
|
||||
|
||||
$instance = $this->createMock();
|
||||
$instance->getStdio()->setExpectedOutput(array('interface_version'), array(), '13.1');
|
||||
|
||||
$stdio =<<<END
|
||||
attr "foo" "bar"
|
||||
state "unchanged"
|
||||
|
||||
attr "some new
|
||||
line" "and more <weird>-
|
||||
nesses"
|
||||
END;
|
||||
$instance->getStdio()->setExpectedOutput(array('get_attributes', 'foo'), array('r' => $rev), $stdio);
|
||||
$res = $instance->getProperties($rev, 'foo');
|
||||
|
||||
$this->assertEquals(2, count($res));
|
||||
$this->assertEquals(array(
|
||||
'foo' => 'bar',
|
||||
"some new\nline" => "and more <weird>-\nnesses"
|
||||
), $res);
|
||||
}
|
||||
|
||||
public function testGetExtraProperties()
|
||||
{
|
||||
$instance = $this->createMock();
|
||||
|
@@ -86,6 +86,14 @@ a.soft:visited {
|
||||
|
||||
div.context {
|
||||
padding-left: 1em;
|
||||
position: relative;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
div.context h3 {
|
||||
font-size: 13px;
|
||||
font-weight: bold;
|
||||
margin: 10px 0 5px;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -127,9 +135,9 @@ ul.errorlist {
|
||||
div.user-messages {
|
||||
border: 1px solid rgb(229, 225, 169);
|
||||
background-color: #fffde3;
|
||||
margin-bottom: 1em;
|
||||
margin-bottom: 2em;
|
||||
margin-left: -1px;
|
||||
width: 90%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
div.theterms {
|
||||
@@ -275,7 +283,7 @@ div.issue-changes-timeline {
|
||||
|
||||
div.issue-prev-next {
|
||||
float: right;
|
||||
margin-top: -25px;
|
||||
margin-top: -1.5em;
|
||||
}
|
||||
|
||||
div.issue-submit-info {
|
||||
@@ -295,6 +303,11 @@ span.label {
|
||||
padding-left: 0.5em;
|
||||
}
|
||||
|
||||
span.label img {
|
||||
max-height: 13px;
|
||||
vertical-align: -10%;
|
||||
}
|
||||
|
||||
a.label {
|
||||
color: #204a87;
|
||||
text-decoration: none;
|
||||
@@ -923,14 +936,6 @@ ol > li {
|
||||
/**
|
||||
* List expander for tag and branch view
|
||||
*/
|
||||
.context {}
|
||||
|
||||
.context h3 {
|
||||
font-size: 13px;
|
||||
font-weight: bold;
|
||||
margin: 10px 0 5px;
|
||||
}
|
||||
|
||||
.context > .expander {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
@@ -1053,6 +1058,10 @@ span.scm-action.renamed {
|
||||
background-color: purple;
|
||||
}
|
||||
|
||||
span.scm-action.copied {
|
||||
background-color: orchid;
|
||||
}
|
||||
|
||||
span.scm-action.property-changed {
|
||||
background-color: blue;
|
||||
}
|
||||
@@ -1095,3 +1104,53 @@ div.p-list-private {
|
||||
right: -3px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
/*
|
||||
* Issue summary
|
||||
*/
|
||||
div.issue-summary {
|
||||
float: left;
|
||||
width: 50%;
|
||||
}
|
||||
|
||||
div.issue-summary > div {
|
||||
margin-right: 3em;
|
||||
padding-top: 1em;
|
||||
}
|
||||
|
||||
div.issue-summary h2 {
|
||||
border-bottom: 1px solid #A5E26A;
|
||||
}
|
||||
|
||||
table.issue-summary {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
table.issue-summary tr td {
|
||||
border: 0;
|
||||
padding: .1em .005em;
|
||||
}
|
||||
|
||||
table.issue-summary td.graph {
|
||||
width: 60%;
|
||||
}
|
||||
|
||||
table.issue-summary td.count {
|
||||
text-align: right;
|
||||
padding-right: .5em;
|
||||
}
|
||||
|
||||
table.graph {
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
table.issue-summary td.graph-color {
|
||||
background: #3C78B5;
|
||||
}
|
||||
|
||||
table.issue-summary td.graph-percent {
|
||||
padding-left: 1em;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user