bug 589313, remove obsolete l10n tests, those are hosted elsewhere, details in the bug. r/a=sayrer, NPOTB

This commit is contained in:
Axel Hecht 2010-08-23 10:08:50 +02:00
Родитель 8896fadf25
Коммит cff57d723a
36 изменённых файлов: 0 добавлений и 4395 удалений

Просмотреть файл

@ -1,57 +0,0 @@
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
# The contents of this file are subject to the Mozilla Public License Version
# 1.1 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
# http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is mozilla.org l10n testing.
#
# The Initial Developer of the Original Code is
# Mozilla Foundation.
# Portions created by the Initial Developer are Copyright (C) 2006
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# Axel Hecht <l10n@mozilla.com>
#
# Alternatively, the contents of this file may be used under the terms of
# either the GNU General Public License Version 2 or later (the "GPL"), or
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
# in which case the provisions of the GPL or the LGPL are applicable instead
# of those above. If you wish to allow use of your version of this file only
# under the terms of either the GPL or the LGPL, and not to allow others to
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK *****
DEPTH = ../../../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = coverage
XPI_NAME = coverage
#INSTALL_EXTENSION_ID = coverage@l10n.mozilla.com
XPI_PKGNAME = coverage-$(EXTENSION_VERSION)
EXTENSION_VERSION = 0.5
USE_EXTENSION_MANIFEST = 1
DIST_FILES = install.rdf
PREF_JS_EXPORTS = $(srcdir)/coverage-extension-prefs.js
DEFINES += -DEXTENSION_VERSION=$(EXTENSION_VERSION)
include $(topsrcdir)/config/rules.mk

Просмотреть файл

@ -1,104 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org l10n testing.
*
* The Initial Developer of the Original Code is
* Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2066
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Axel Hecht <l10n@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/**
* Item to close a menu popup
*
* Used by OpenMenuObj.
*/
function CloseMenuObj(aPopup) {
this.args = [aPopup];
}
CloseMenuObj.prototype = {
args: null,
method: function _openMenu(aPopup) {
aPopup.hidePopup();
}
};
/**
* Item to open a menu popup
*
* Adds a CloseMenuObj item as well as potentially child popups to
* Stack
*/
function OpenMenuObj(aPopup) {
this.args = [aPopup];
}
OpenMenuObj.prototype = {
args: null,
method: function _openMenu(aPopup) {
aPopup.showPopup();
Stack.push(new CloseMenuObj(aPopup));
for (var i = aPopup.childNodes.length - 1; i>=0; --i) {
var c = aPopup.childNodes[i];
if (c.nodeName != 'menu' || c.childNodes.length == 0) {
continue;
}
for each (var childpop in c.childNodes) {
if (childpop.localName == "menupopup") {
Stack.push(new OpenMenuObj(childpop));
}
}
}
}
};
/**
* Item to kick off menu coverage testing
*
* Pretty similar to OpenMenuObj, just that it works on the main-menubar
* instead of a given popup.
*/
function RootMenu(aWindow) {
this._w = aWindow;
};
RootMenu.prototype = {
args: [],
method: function() {
var mb = this._w.document.getElementById('main-menubar');
for (var i = mb.childNodes.length - 1; i>=0; --i) {
var m = mb.childNodes[i];
Stack.push(new OpenMenuObj(m.firstChild));
}
},
_w: null
};
toRun.push(new TestDone('MENUS'));
toRun.push(new RootMenu(wins[0]));
toRun.push(new TestStart('MENUS'));

Просмотреть файл

@ -1,113 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org l10n testing.
*
* The Initial Developer of the Original Code is
* Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2066
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Axel Hecht <l10n@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
var SBS = Cc["@mozilla.org/intl/stringbundle;1"].getService(Ci.nsIStringBundleService);
var bundle = SBS.createBundle("chrome://global/locale/appstrings.properties");
/**
* Item to wait on asynchronous loads
*/
var loadAction = {
isLoaded: false,
args: [],
method: function() {
if (!this.isLoaded) {
Stack.push(this);
}
}
};
// onLoad handler for the iframe, sibling of loadAction
function onFrameLoad(aEvent) {
aEvent.stopPropagation();
loadAction.isLoaded = true;
return false;
};
/**
* Item to load the next error page
*
* Uses the loadAction object to wait for asynchronous loading.
*/
function ErrPageLoad(aFrame, aProperty) {
this.args = [aFrame, aProperty.key, aProperty.value];
};
ErrPageLoad.prototype = {
args: null,
method: function(aFrame, aErr, aDesc) {
loadAction.isLoaded = false;
var q = 'e=' + encodeURIComponent(aErr);
q += '&u=' + encodeURIComponent('http://foo.bar');
// Simple replacement, replace anything that's %s with aURL,
// see http://lxr.mozilla.org/mozilla1.8/source/docshell/base/nsDocShell.cpp#2907
// on how to do this right. But that requires knowledge on each and
// every error, too much work for now.
aDesc = aDesc.replace('%S', 'http://foo.bar');
q += '&d=' + encodeURIComponent(aDesc);
Stack.push(loadAction);
aFrame.setAttribute('src', 'about:neterror?' + q);
}
};
/**
* Item to start the neterror tests
*
* This item collects all the neterror pages we intend to test
* and adds them to the Stack.
*/
function RootNeterror() {
this.args = [];
};
RootNeterror.prototype = {
args: null,
method: function(aIFrame) {
var frame = document.getElementById('neterror-pane');
var nErrors =
[err for (err in SimpleGenerator(bundle.getSimpleEnumeration(),
Ci.nsIPropertyElement))];
nErrors.sort(function(aPl, aPr) {
return aPl.key > aPr.key ? 1 :
aPl.key < aPr.key ? -1 : 0;
});
for each (err in nErrors) {
Stack.push(new ErrPageLoad(frame, err));
}
}
};
toRun.push(new TestDone('NETERROR'));
toRun.push(new RootNeterror());
toRun.push(new TestStart('NETERROR'));

Просмотреть файл

@ -1,138 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org l10n testing.
*
* The Initial Developer of the Original Code is
* Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2066
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Axel Hecht <l10n@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/**
* Item to show the next pane in a prefs window
*/
function ShowPaneObj(aPane, aLoader) {
this.args = [aPane, aLoader];
}
ShowPaneObj.prototype = {
args: null,
method: function _openMenu(aPane, aLoader) {
Stack.push(aLoader);
aPane.parentNode.showPane(aPane);
}
};
/**
* Item to close the preferences window once the tests are done
*/
function ClosePreferences() {
this.args = [];
};
ClosePreferences.prototype = {
args: [],
method: function() {
var pWin = WM.getMostRecentWindow("Browser:Preferences");
if (pWin) {
pWin.close();
}
else {
Components.utils.reportError("prefwindow not found, trying again");
}
}
};
/**
* Item to wait for a preference pane to load
*/
function PrefPaneLoader() {
};
PrefPaneLoader.prototype = {
_currentPane: null,
args: [],
method: function() {
if (!this._currentPane) {
// The pane we're waiting for hasn't been loaded yet, do me again
Stack.push(this);
return;
}
// the pane is loaded, kick off the load of the next one, if available
pane = this._currentPane.nextSibling;
this._currentPane = null;
while (pane) {
if (pane.nodeName == 'prefpane') {
Stack.push(new ShowPaneObj(pane, this));
return;
}
pane = pane.nextSibling;
}
},
// nsIDOMEventListener
handleEvent: function _hv(aEvent) {
this._currentPane = aEvent.target;
}
};
/**
* Item to start the preference dialog tests
*
* This item expects to have 'paneMain' as the ID of the first pane.
* That may be an over-simplification, but it guarantees to load
* the panes from left to right, and that all are not loaded yet.
* WFM.
*/
function RootPreference(aWindow) {
this.args = [aWindow];
};
RootPreference.prototype = {
args: [],
method: function(aWindow) {
WM.addListener(this);
aWindow.openPreferences('paneMain');
},
// nsIWindowMediatorListener
onWindowTitleChange: function(aWindow, newTitle){},
onOpenWindow: function(aWindow) {
WM.removeListener(this);
// ensure the timer runs in the modal window, too
Stack._timer.initWithCallback({notify:function (aTimer) {Stack.pop();}},
Stack._time, 1);
Stack.push(new ClosePreferences());
var ppl = new PrefPaneLoader();
aWindow.docShell.QueryInterface(Ci.nsIInterfaceRequestor);
var DOMwin = aWindow.docShell.getInterface(Ci.nsIDOMWindow);
DOMwin.addEventListener('paneload', ppl, false);
Stack.push(ppl);
},
onCloseWindow: function(aWindow){}
};
toRun.push(new TestDone('PREFERENCES'));
toRun.push(new RootPreference(wins[0]));
toRun.push(new TestStart('PREFERENCES'));

Просмотреть файл

@ -1,130 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org l10n testing.
*
* The Initial Developer of the Original Code is
* Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2066
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Axel Hecht <l10n@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
/**
* Basic architecture for UI exposure tests
*
* Details on http://wiki.mozilla.org/SoftwareTesting:Tools:L10n:Coverage
*/
var Ci = Components.interfaces;
var Cc = Components.classes;
var Cr = Components.results;
var ios = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService);
var ds = Cc[NS_DIRECTORY_SERVICE_CONTRACTID].getService(Ci.nsIProperties);
const WM = Cc["@mozilla.org/appshell/window-mediator;1"].getService(Ci.nsIWindowMediator);
/**
* Global Stack object
*
* This object keeps the tests running with some time for visual inspection.
*/
var Stack = {
_stack: [],
_time: 250,
_timer: Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer),
notify: function _notify(aTimer) {
this.pop();
},
push: function _push(aItem) {
this._stack.push(aItem);
if (this._stack.length == 1) {
this._timer.initWithCallback({notify:function (aTimer) {Stack.pop();}},
this._time, 1);
}
},
pop: function _pop() {
var obj = this._stack.pop();
try {
obj.method.apply(obj, obj.args);
} catch (e) {
Components.utils.reportError(e);
}
if (!this._stack.length) {
this._timer.cancel();
}
}
};
/**
* Add your test set to toRun.
* The onload handler will add them to the Stack and kick off the
* testing.
*/
var toRun = [];
/**
* Utility to get array of xpcom objects from a nsISimpleEnumerator
* Requires JS1.7
*/
function SimpleGenerator(enumr, interface) {
while (enumr.hasMoreElements()) {
yield enumr.getNext().QueryInterface(interface);
}
}
var wins = [w for (w in SimpleGenerator(WM.getEnumerator(null), Ci.nsIDOMWindow))];
/**
* Helper items to log start and end of testing to the Error Console
*/
function MsgBase() {
}
MsgBase.prototype = {
args: [],
method: function() {
Components.utils.reportError(this._msg);
}
};
function TestStart(aCat) {
this._msg = 'TESTING:START:COVERAGE:' + aCat;
}
TestStart.prototype = new MsgBase;
function TestDone(aCat) {
this._msg = 'TESTING:DONE:COVERAGE:' + aCat;
}
TestDone.prototype = new MsgBase;
/**
* onload handler for the entry page.
* Copy the toRun items over to the stack and kick things off.
*/
function onLoad() {
for each (var obj in toRun) {
Stack.push(obj);
}
}

Просмотреть файл

@ -1,48 +0,0 @@
<?xml version="1.0"?>
<!-- ***** BEGIN LICENSE BLOCK *****
- Version: MPL 1.1/GPL 2.0/LGPL 2.1
-
- The contents of this file are subject to the Mozilla Public License Version
- 1.1 (the "License"); you may not use this file except in compliance with
- the License. You may obtain a copy of the License at
- http://www.mozilla.org/MPL/
-
- Software distributed under the License is distributed on an "AS IS" basis,
- WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- for the specific language governing rights and limitations under the
- License.
-
- The Original Code is mozilla.org l10n testing.
-
- The Initial Developer of the Original Code is
- Mozilla Foundation.
- Portions created by the Initial Developer are Copyright (C) 2006
- the Initial Developer. All Rights Reserved.
-
- Contributor(s):
- Axel Hecht <l10n@mozilla.com>
-
- Alternatively, the contents of this file may be used under the terms of
- either the GNU General Public License Version 2 or later (the "GPL"), or
- the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- in which case the provisions of the GPL or the LGPL are applicable instead
- of those above. If you wish to allow use of your version of this file only
- under the terms of either the GPL or the LGPL, and not to allow others to
- use your version of this file under the terms of the MPL, indicate your
- decision by deleting the provisions above and replace them with the notice
- and other provisions required by the LGPL or the GPL. If you do not delete
- the provisions above, a recipient may use your version of this file under
- the terms of any one of the MPL, the GPL or the LGPL.
-
- ***** END LICENSE BLOCK ***** -->
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<window id="coverage"
title="Coverage Tool"
onload="return onLoad(event)"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<script type="application/javascript;version=1.7" src="coverage.js"/>
<script type="application/javascript;version=1.7" src="coverage-prefs.js"/>
<script type="application/javascript;version=1.7" src="coverage-menu.js"/>
<label value="test"/>
</window>

Просмотреть файл

@ -1,48 +0,0 @@
<?xml version="1.0"?>
<!-- ***** BEGIN LICENSE BLOCK *****
- Version: MPL 1.1/GPL 2.0/LGPL 2.1
-
- The contents of this file are subject to the Mozilla Public License Version
- 1.1 (the "License"); you may not use this file except in compliance with
- the License. You may obtain a copy of the License at
- http://www.mozilla.org/MPL/
-
- Software distributed under the License is distributed on an "AS IS" basis,
- WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- for the specific language governing rights and limitations under the
- License.
-
- The Original Code is mozilla.org l10n testing.
-
- The Initial Developer of the Original Code is
- Mozilla Foundation.
- Portions created by the Initial Developer are Copyright (C) 2006
- the Initial Developer. All Rights Reserved.
-
- Contributor(s):
- Axel Hecht <l10n@mozilla.com>
-
- Alternatively, the contents of this file may be used under the terms of
- either the GNU General Public License Version 2 or later (the "GPL"), or
- the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- in which case the provisions of the GPL or the LGPL are applicable instead
- of those above. If you wish to allow use of your version of this file only
- under the terms of either the GPL or the LGPL, and not to allow others to
- use your version of this file under the terms of the MPL, indicate your
- decision by deleting the provisions above and replace them with the notice
- and other provisions required by the LGPL or the GPL. If you do not delete
- the provisions above, a recipient may use your version of this file under
- the terms of any one of the MPL, the GPL or the LGPL.
-
- ***** END LICENSE BLOCK ***** -->
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<window id="neterror-coverage"
title="NetError Coverage Tool"
onload="return onLoad(event)"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<script type="application/javascript;version=1.7" src="coverage.js"/>
<script type="application/javascript;version=1.7" src="coverage-neterror.js"/>
<label value="Neterror page tests"/>
<iframe flex="1" onload="return onFrameLoad(event);" id="neterror-pane"/>
</window>

Просмотреть файл

@ -1,3 +0,0 @@
pref('javascript.options.showInConsole', true);
pref('testing.extensions.l10n.coverage', 'chrome://coverage/content/');
pref('testing.extensions.l10n.neterror-coverage', 'chrome://coverage/content/neterror-coverage.xul');

Просмотреть файл

@ -1,27 +0,0 @@
<?xml version="1.0"?>
<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:em="http://www.mozilla.org/2004/em-rdf#">
<Description about="urn:mozilla:install-manifest">
<em:id>coverage@l10n.mozilla.com</em:id>
#expand <em:version>__EXTENSION_VERSION__</em:version>
<em:type>2</em:type>
<!-- Target Application this extension can install into,
with minimum and maximum supported versions. -->
<em:targetApplication>
<Description>
<em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
<em:minVersion>2.0</em:minVersion>
<em:maxVersion>2.0.*</em:maxVersion>
</Description>
</em:targetApplication>
<!-- Front End MetaData -->
<em:name>Coverage tester</em:name>
<em:description>Triggers lots of UI to see if errors pop up.</em:description>
<em:creator>Axel Hecht &lt;l10n@mozilla.com&gt;</em:creator>
<em:homepageURL>http://wiki.mozilla.org/SoftwareTesting:Tools:L10n:Coverage</em:homepageURL>
</Description>
</RDF>

Просмотреть файл

@ -1,8 +0,0 @@
coverage.jar:
% content coverage %content/
content/coverage.xul (chrome/content/coverage.xul)
content/coverage.js (chrome/content/coverage.js)
content/coverage-menu.js (chrome/content/coverage-menu.js)
content/coverage-prefs.js (chrome/content/coverage-prefs.js)
content/neterror-coverage.xul (chrome/content/neterror-coverage.xul)
content/coverage-neterror.js (chrome/content/coverage-neterror.js)

Просмотреть файл

@ -1,57 +0,0 @@
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
# The contents of this file are subject to the Mozilla Public License Version
# 1.1 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
# http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is mozilla.org l10n testing.
#
# The Initial Developer of the Original Code is
# Mozilla Foundation.
# Portions created by the Initial Developer are Copyright (C) 2006
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# Axel Hecht <l10n@mozilla.com>
#
# Alternatively, the contents of this file may be used under the terms of
# either the GNU General Public License Version 2 or later (the "GPL"), or
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
# in which case the provisions of the GPL or the LGPL are applicable instead
# of those above. If you wish to allow use of your version of this file only
# under the terms of either the GPL or the LGPL, and not to allow others to
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK *****
DEPTH = ../../../../..
topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
MODULE = help-helper
XPI_NAME = help-helper
#INSTALL_EXTENSION_ID = helper@l10n.mozilla.com
XPI_PKGNAME = help-helper-$(EXTENSION_VERSION)
EXTENSION_VERSION = 0.7
USE_EXTENSION_MANIFEST = 1
DIST_FILES = install.rdf
PREF_JS_EXPORTS = $(srcdir)/help-helper-prefs.js
DEFINES += -DEXTENSION_VERSION=$(EXTENSION_VERSION)
include $(topsrcdir)/config/rules.mk

Просмотреть файл

@ -1,193 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is mozilla.org l10n testing.
*
* The Initial Developer of the Original Code is
* Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2066
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Axel Hecht <l10n@mozilla.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
// Controller section
var Ci = Components.interfaces;
var Cc = Components.classes;
var Cr = Components.results;
var RDF = Cc['@mozilla.org/rdf/rdf-service;1'].getService(Ci.nsIRDFService);
var ios = Cc["@mozilla.org/network/io-service;1"].getService(Ci.nsIIOService);
var AI = Cc['@mozilla.org/xre/app-info;1'].getService(Ci.nsIXULAppInfo);
var prefs = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefService);
prefs = prefs.getBranch("l10n.tests.help.");
var prefName = AI.name + '.' + AI.version.substr(0,3); // only take the major version
var gData = eval('(' + prefs.getCharPref(prefName) + ')');
// Table of Contents is the first datasource
var toc = ios.newURI(gData.datasources[0].url, null, null);
function getDS(data) {
try {
var ds = RDF.GetDataSourceBlocking(data.url);
} catch (e) {
Components.utils.reportError('failed to load RDF for ' + data.url);
}
ds.QueryInterface(Ci.rdfIDataSource);
return ds;
}
gData.rdfds = gData.datasources.map(getDS);
var nc = "http://home.netscape.com/NC-rdf#";
var lnk = RDF.GetResource(nc + 'link');
var toCheck = {};
var checkList = [];
var isGood;
var current = null;
var frm, gb = document.documentElement;
function triplehandler(aBaseURI) {
return function(aSubj, aPred, aObj, aTruth) {
if (aPred.EqualsNode(lnk)) {
aObj.QueryInterface(Ci.nsIRDFLiteral);
var target = ios.newURI(aObj.Value, null, aBaseURI);
target.QueryInterface(Ci.nsIURL);
var ref = target.ref;
var base = target.prePath + target.filePath;
if (! (base in toCheck)) {
toCheck[base] = {};
}
toCheck[base][ref] = [aSubj, target];
}
}
}
function onLoad(event) {
//Components.utils.reportError(event.target + ' loaded');
if (event.target != document) {
return;
}
document.documentElement.removeAttribute('onload');
frm = document.getElementById('frm');
frm.addEventListener('load', frmLoad, true);
gData.current = -1;
runDS();
}
function runDS() {
gData.current++;
if (gData.datasources.length == gData.current) {
postChecks();
return;
}
toCheck = {};
checkList = [];
isGood = true;
var data = gData.datasources[gData.current];
Components.utils.reportError('testing ' + data.title);
createBox(data.title);
var uri = ios.newURI(data.url, null, null);
gData.rdfds[gData.current].visitAllTriples(triplehandler(uri));
for (key in toCheck) {
checkList.push([key, toCheck[key]]);
}
current = checkList.pop();
frm.setAttribute('src', current[0]);
}
function frmLoad(event) {
event.stopPropagation();
event.preventDefault();
//Components.utils.reportError('loaded ' + current[0]);
checkIDs(current[1], current[0]);
if (checkList.length == 0) {
if (isGood) {
logMessage('PASS');
}
runDS();
return;
}
current = checkList.pop();
frm.setAttribute('src', current[0]);
}
function checkIDs(refs, url) {
if (!frm.contentDocument) {
Components.utils.reportError(url + ' not found\n')
return;
}
for (var ref in refs) {
if (ref && !frm.contentDocument.getElementById(ref)) {
isGood = false;
var msg = 'ID "' + ref + '" in ' + url + ' not found';
Components.utils.reportError(msg);
var d = document.createElement('description');
d.setAttribute('value', msg);
gb.appendChild(d);
}
}
}
function postChecks() {
if (gData.entrypoints) {
createBox('Entry points');
Components.utils.reportError('testing entry points');
var good = 0; bad = 0;
for each (idref in gData.entrypoints) {
var r=RDF.GetResource(toc.spec + '#' + idref);
if (gData.rdfds[0].GetTarget(r,lnk,true)) {
good++;
}
else {
bad++;
logMessage('Entrypoint "' + idref + '" not resolved.');
}
}
if (bad == 0) {
logMessage('PASS');
}
}
Components.utils.reportError('TESTING:DONE');
}
// View section
function createBox(aTitle) {
gb = document.createElement('groupbox');
gb.appendChild(document.createElement('caption'));
gb.firstChild.setAttribute('label', aTitle);
document.documentElement.appendChild(gb);
}
function logMessage(aMsg) {
Components.utils.reportError(aMsg);
var d = document.createElement('description');
d.setAttribute('value', aMsg);
gb.appendChild(d);
}

Просмотреть файл

@ -1,46 +0,0 @@
<?xml version="1.0"?>
<!-- ***** BEGIN LICENSE BLOCK *****
- Version: MPL 1.1/GPL 2.0/LGPL 2.1
-
- The contents of this file are subject to the Mozilla Public License Version
- 1.1 (the "License"); you may not use this file except in compliance with
- the License. You may obtain a copy of the License at
- http://www.mozilla.org/MPL/
-
- Software distributed under the License is distributed on an "AS IS" basis,
- WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- for the specific language governing rights and limitations under the
- License.
-
- The Original Code is mozilla.org l10n testing.
-
- The Initial Developer of the Original Code is
- Mozilla Foundation.
- Portions created by the Initial Developer are Copyright (C) 2006
- the Initial Developer. All Rights Reserved.
-
- Contributor(s):
- Axel Hecht <l10n@mozilla.com>
-
- Alternatively, the contents of this file may be used under the terms of
- either the GNU General Public License Version 2 or later (the "GPL"), or
- the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- in which case the provisions of the GPL or the LGPL are applicable instead
- of those above. If you wish to allow use of your version of this file only
- under the terms of either the GPL or the LGPL, and not to allow others to
- use your version of this file under the terms of the MPL, indicate your
- decision by deleting the provisions above and replace them with the notice
- and other provisions required by the LGPL or the GPL. If you do not delete
- the provisions above, a recipient may use your version of this file under
- the terms of any one of the MPL, the GPL or the LGPL.
-
- ***** END LICENSE BLOCK ***** -->
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<window id="help-helper"
title="Help Link Checker"
onload="return onLoad(event)"
xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<script type="application/javascript" src="help-helper.js"/>
<iframe id="frm" style="height:0px;"/>
</window>

Просмотреть файл

@ -1 +0,0 @@
pref("l10n.tests.help.Firefox.2.0", '{entrypoints:["firefox-help", "ieusers", "prefs-advanced-encryption", "prefs-advanced-general", "prefs-advanced-javascript", "prefs-advanced-network", "prefs-advanced-update", "prefs-clear-private-data", "prefs-connection-settings", "prefs-content", "prefs-feeds", "prefs-file-types", "prefs-fonts-and-colors", "prefs-languages", "prefs-main", "prefs-privacy", "prefs-security", "prefs-tabs"], datasources:[{url:"chrome://browser/locale/help/firebird-toc.rdf", title:"Table Of Contents"}, {url:"chrome://browser/locale/help/search-db.rdf", title:"Search"}]}');

Просмотреть файл

@ -1,27 +0,0 @@
<?xml version="1.0"?>
<RDF xmlns="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:em="http://www.mozilla.org/2004/em-rdf#">
<Description about="urn:mozilla:install-manifest">
<em:id>helper@l10n.mozilla.com</em:id>
#expand <em:version>__EXTENSION_VERSION__</em:version>
<em:type>2</em:type>
<!-- Target Application this extension can install into,
with minimum and maximum supported versions. -->
<em:targetApplication>
<Description>
<em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
<em:minVersion>2.0b2</em:minVersion>
<em:maxVersion>2.0.*</em:maxVersion>
</Description>
</em:targetApplication>
<!-- Front End MetaData -->
<em:name>Help Helper</em:name>
<em:description>Finds all links in the help TOC and tries to resolve them.</em:description>
<em:creator>Axel Hecht &lt;l10n@mozilla.com&gt;</em:creator>
<em:homepageURL>http://people.mozilla.com/~axel/l10n/</em:homepageURL>
</Description>
</RDF>

Просмотреть файл

@ -1,4 +0,0 @@
help-helper.jar:
% content help-helper %content
content/help-helper.xul (chrome/content/help-helper.xul)
content/help-helper.js (chrome/content/help-helper.js)

Просмотреть файл

@ -1,235 +0,0 @@
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
# The contents of this file are subject to the Mozilla Public License Version
# 1.1 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
# http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is l10n test automation.
#
# The Initial Developer of the Original Code is
# Mozilla Foundation
# Portions created by the Initial Developer are Copyright (C) 2006
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# Axel Hecht <l10n@mozilla.com>
#
# Alternatively, the contents of this file may be used under the terms of
# either the GNU General Public License Version 2 or later (the "GPL"), or
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
# in which case the provisions of the GPL or the LGPL are applicable instead
# of those above. If you wish to allow use of your version of this file only
# under the terms of either the GPL or the LGPL, and not to allow others to
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK *****
'Mozilla l10n compare locales tool'
import os
import os.path
import re
import logging
import Parser
import Paths
class FileCollector:
def __init__(self):
pass
def getFiles(self, mod, locale):
fls = {}
for leaf, path in self.iterateFiles(mod,locale):
fls[leaf] = path
return fls
def iterateFiles(self, mod, locale):
base = Paths.get_base_path(mod, locale)
cutoff = len(base) + 1
for dirpath, dirnames, filenames in os.walk(base):
try:
# ignore CVS dirs
dirnames.remove('CVS')
except ValueError:
pass
dirnames.sort()
filenames.sort()
for f in filenames:
leaf = dirpath + '/' + f
yield (leaf[cutoff:], leaf)
def collectFiles(aComparer, apps = None, locales = None):
'''
returns new files, files to compare, files to remove
apps or locales need to be given, apps is a list, locales is a
hash mapping applications to languages.
If apps is given, it will look up all-locales for all apps for the
languages to test.
'toolkit' is added to the list of modules, too.
'''
if not apps and not locales:
raise RuntimeError, "collectFiles needs either apps or locales"
if apps and locales:
raise RuntimeError, "You don't want to give both apps or locales"
if locales:
apps = locales.keys()
# add toolkit, with all of the languages of all apps
all = set()
for locs in locales.values():
all.update(locs)
locales['toolkit'] = list(all)
else:
locales = Paths.allLocales(apps)
modules = Paths.Modules(apps)
en = FileCollector()
l10n = FileCollector()
# load filter functions for each app
fltrs = []
for app in apps:
filterpath = 'mozilla/%s/locales/filter.py' % app
if not os.path.exists(filterpath):
continue
l = {}
execfile(filterpath, {}, l)
if 'test' not in l or not callable(l['test']):
logging.debug('%s does not define function "test"' % filterpath)
continue
fltrs.append(l['test'])
# define fltr function to be used, calling into the app specific ones
# if one of our apps wants us to know about a triple, make it so
def fltr(mod, lpath, entity = None):
for f in fltrs:
keep = True
try:
keep = f(mod, lpath, entity)
except Exception, e:
logging.error(str(e))
if not keep:
return False
return True
for cat in modules.keys():
logging.debug(" testing " + cat+ " on " + str(modules))
aComparer.notifyLocales(cat, locales[cat])
for mod in modules[cat]:
en_fls = en.getFiles(mod, 'en-US')
for loc in locales[cat]:
fls = dict(en_fls) # create copy for modification
for l_fl, l_path in l10n.iterateFiles(mod, loc):
if fls.has_key(l_fl):
# file in both en-US and locale, compare
aComparer.compareFile(mod, loc, l_fl)
del fls[l_fl]
else:
if fltr(mod, l_fl):
# file in locale, but not in en-US, remove
aComparer.removeFile(mod, loc, l_fl)
else:
logging.debug(" ignoring %s from %s in %s" %
(l_fl, loc, mod))
# all locale files dealt with, remaining fls need to be added?
for lf in fls.keys():
if fltr(mod, lf):
aComparer.addFile(mod,loc,lf)
else:
logging.debug(" ignoring %s from %s in %s" %
(lf, loc, mod))
return fltr
class CompareCollector:
'collects files to be compared, added, removed'
def __init__(self):
self.cl = {}
self.files = {}
self.modules = {}
def notifyLocales(self, aModule, aLocaleList):
for loc in aLocaleList:
if self.modules.has_key(loc):
self.modules[loc].append(aModule)
else:
self.modules[loc] = [aModule]
def addFile(self, aModule, aLocale, aLeaf):
logging.debug(" add %s for %s in %s" % (aLeaf, aLocale, aModule))
if not self.files.has_key(aLocale):
self.files[aLocale] = {'missingFiles': [(aModule, aLeaf)],
'obsoleteFiles': []}
else:
self.files[aLocale]['missingFiles'].append((aModule, aLeaf))
pass
def compareFile(self, aModule, aLocale, aLeaf):
if not self.cl.has_key((aModule, aLeaf)):
self.cl[(aModule, aLeaf)] = [aLocale]
else:
self.cl[(aModule, aLeaf)].append(aLocale)
pass
def removeFile(self, aModule, aLocale, aLeaf):
logging.debug(" remove %s from %s in %s" % (aLeaf, aLocale, aModule))
if not self.files.has_key(aLocale):
self.files[aLocale] = {'obsoleteFiles': [(aModule, aLeaf)],
'missingFiles':[]}
else:
self.files[aLocale]['obsoleteFiles'].append((aModule, aLeaf))
pass
def compare(apps=None, testLocales=None):
result = {}
c = CompareCollector()
fltr = collectFiles(c, apps=apps, locales=testLocales)
key = re.compile('[kK]ey')
for fl, locales in c.cl.iteritems():
(mod,path) = fl
try:
parser = Parser.getParser(path)
except UserWarning:
logging.warning(" Can't compare " + path + " in " + mod)
continue
parser.read(Paths.get_path(mod, 'en-US', path))
enMap = parser.mapping()
for loc in locales:
if not result.has_key(loc):
result[loc] = {'missing':[],'obsolete':[],
'changed':0,'unchanged':0,'keys':0}
enTmp = dict(enMap)
parser.read(Paths.get_path(mod, loc, path))
for k,v in parser:
if not fltr(mod, path, k):
if enTmp.has_key(k):
del enTmp[k]
continue
if not enTmp.has_key(k):
result[loc]['obsolete'].append((mod,path,k))
continue
enVal = enTmp[k]
del enTmp[k]
if key.search(k):
result[loc]['keys'] += 1
else:
if enVal == v:
result[loc]['unchanged'] +=1
logging.info('%s in %s unchanged' %
(k, Paths.get_path(mod, loc, path)))
else:
result[loc]['changed'] +=1
result[loc]['missing'].extend(filter(lambda t: fltr(*t),
[(mod,path,k) for k in enTmp.keys()]))
for loc,dics in c.files.iteritems():
if not result.has_key(loc):
result[loc] = dics
else:
for key, list in dics.iteritems():
result[loc][key] = list
for loc, mods in c.modules.iteritems():
result[loc]['tested'] = mods
return result

Просмотреть файл

@ -1,201 +0,0 @@
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
# The contents of this file are subject to the Mozilla Public License Version
# 1.1 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
# http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is l10n test automation.
#
# The Initial Developer of the Original Code is
# Mozilla Foundation
# Portions created by the Initial Developer are Copyright (C) 2006
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# Axel Hecht <l10n@mozilla.com>
#
# Alternatively, the contents of this file may be used under the terms of
# either the GNU General Public License Version 2 or later (the "GPL"), or
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
# in which case the provisions of the GPL or the LGPL are applicable instead
# of those above. If you wish to allow use of your version of this file only
# under the terms of either the GPL or the LGPL, and not to allow others to
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK *****
import re
import codecs
import logging
__constructors = []
class Parser:
def __init__(self):
if not hasattr(self, 'encoding'):
self.encoding = 'utf-8';
pass
def read(self, file):
f = codecs.open(file, 'r', self.encoding)
try:
self.contents = f.read()
except UnicodeDecodeError, e:
logging.getLogger('locales').error("Can't read file: " + file + '; ' + str(e))
self.contents = u''
f.close()
def parse(self, contents):
(self.contents, length) = codecs.getdecoder(self.encoding)(contents)
def mapping(self):
m = {}
for p in self:
m[p[0]] = p[1]
return m
def compareEntries(self, en, l10n):
return None
def postProcessValue(self, val):
return val
def __iter__(self):
self.offset = 0
return self
def next(self):
cm = self.comment.search(self.contents, self.offset)
m = self.key.search(self.contents, self.offset)
if not m:
raise StopIteration
# eagerly strip comments
if cm and cm.start() < m.start():
self.offset = cm.end()
return self.next()
self.offset = m.end()
return (m.group(1), self.postProcessValue(m.group(2)))
def getParser(path):
for item in __constructors:
if re.search(item[0], path):
return item[1]
raise UserWarning, "Cannot find Parser"
class DTDParser(Parser):
def __init__(self):
# http://www.w3.org/TR/2006/REC-xml11-20060816/#NT-NameStartChar
#":" | [A-Z] | "_" | [a-z] |
# [#xC0-#xD6] | [#xD8-#xF6] | [#xF8-#x2FF] | [#x370-#x37D] | [#x37F-#x1FFF]
# | [#x200C-#x200D] | [#x2070-#x218F] | [#x2C00-#x2FEF] |
# [#x3001-#xD7FF] | [#xF900-#xFDCF] | [#xFDF0-#xFFFD] |
# [#x10000-#xEFFFF]
NameStartChar = u':A-Z_a-z\xC0-\xD6\xD8-\xF6\xF8-\u02FF' + \
u'\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF'+\
u'\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD'
# + \U00010000-\U000EFFFF seems to be unsupported in python
# NameChar ::= NameStartChar | "-" | "." | [0-9] | #xB7 |
# [#x0300-#x036F] | [#x203F-#x2040]
NameChar = NameStartChar + ur'\-\.0-9' + u'\xB7\u0300-\u036F\u203F-\u2040'
Name = '[' + NameStartChar + '][' + NameChar + ']*'
self.key = re.compile('<!ENTITY\s+(' + Name + ')\s+(\"(?:[^\"]*\")|(?:\'[^\']*)\')\s*>', re.S)
self.comment = re.compile('<!--.*?-->', re.S)
Parser.__init__(self)
class PropertiesParser(Parser):
def __init__(self):
self.key = re.compile('^\s*([^#!\s\r\n][^=:\r\n]*?)\s*[:=][ \t]*(.*?)[ \t]*$',re.M)
self.comment = re.compile('^\s*[#!].*$',re.M)
self._post = re.compile('\\\\u([0-9a-fA-F]{4})')
Parser.__init__(self)
_arg_re = re.compile('%(?:(?P<cn>[0-9]+)\$)?(?P<width>[0-9]+)?(?:.(?P<pres>[0-9]+))?(?P<size>[hL]|(?:ll?))?(?P<type>[dciouxXefgpCSsn])')
def postProcessValue(self, val):
m = self._post.search(val)
if not m:
return val
while m:
uChar = unichr(int(m.group(1), 16))
val = val.replace(m.group(), uChar)
m = self._post.search(val)
return val
class DefinesParser(Parser):
def __init__(self):
self.key = re.compile('^#define\s+(\w+)\s*(.*?)\s*$',re.M)
self.comment = re.compile('^#[^d][^e][^f][^i][^n][^e][^\s].*$',re.M)
Parser.__init__(self)
class BookmarksParser(Parser):
def __init__(self):
Parser.__init__(self)
def __iter__(self):
def getProps(f, base):
r = []
if f.has_key(u'__title__'):
r.append((base+'.title', f[u'__title__']))
if f.has_key(u'__desc__'):
r.append((base+'.desc',f[u'__desc__']))
for i in range(len(f[u'children'])):
c = f[u'children'][i]
if c.has_key(u'children'):
r += getProps(c, base + '.' + str(i))
else:
for k,v in c.iteritems():
if k == u'HREF':
r.append(('%s.%i.href'%(base, i), v))
if k == u'FEEDURL':
r.append(('%s.%i.feedurl'%(base, i), v))
elif k == u'__title__':
r.append(('%s.%i.title'%(base, i), v))
elif k == u'ICON':
r.append(('%s.%i.icon'%(base, i), v))
return r
return getProps(self.getDetails(), 'bookmarks').__iter__()
def next(self):
raise NotImplementedError
def getDetails(self):
def parse_link(f, line):
link = {}
for m in re.finditer('(?P<key>[A-Z]+)="(?P<val>[^"]+)', line):
link[m.group('key').upper()] = m.group('val')
m = re.search('"[ ]*>([^<]+)</A>', line, re.I)
link[u'__title__'] = m.group(1)
f[u'children'].append(link)
stack = []
f = {u'children': []}
nextTitle = None
nextDesc = None
for ln in self.contents.splitlines():
if ln.find('<DL') >= 0:
stack.append(f)
chld = {u'children':[], u'__title__': nextTitle, u'__desc__': nextDesc}
nextTitle = None
nextDesc = None
f[u'children'].append(chld)
f = chld
elif re.search('<H[13]',ln):
if nextTitle:
pass
nextTitle = re.search('>([^<]+)</H', ln, re.I).group(1)
elif ln.find('<DD>') >= 0:
if nextDesc:
pass
nextDesc = re.search('DD>([^<]+)', ln).group(1)
elif ln.find('<DT><A') >= 0:
parse_link(f, ln)
elif ln.find('</DL>') >= 0:
f = stack.pop()
elif ln.find('<TITLE') >= 0:
f[u'__title__'] = re.search('>([^<]+)</TITLE', ln).group(1)
return f
__constructors = [('\\.dtd', DTDParser()),
('\\.properties', PropertiesParser()),
('\\.inc', DefinesParser()),
('bookmarks\\.html', BookmarksParser())]

Просмотреть файл

@ -1,102 +0,0 @@
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
# The contents of this file are subject to the Mozilla Public License Version
# 1.1 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
# http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is l10n test automation.
#
# The Initial Developer of the Original Code is
# Mozilla Foundation
# Portions created by the Initial Developer are Copyright (C) 2006
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# Axel Hecht <l10n@mozilla.com>
#
# Alternatively, the contents of this file may be used under the terms of
# either the GNU General Public License Version 2 or later (the "GPL"), or
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
# in which case the provisions of the GPL or the LGPL are applicable instead
# of those above. If you wish to allow use of your version of this file only
# under the terms of either the GPL or the LGPL, and not to allow others to
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK *****
import os.path
from subprocess import *
class Modules(dict):
'''
Subclass of dict to hold information on which directories belong to a
particular app.
It expects to have mozilla/client.mk right there from the working dir,
and asks that for the LOCALES_foo variables.
This only works for toolkit applications, as it's assuming that the
apps include toolkit.
'''
def __init__(self, apps):
super(dict, self).__init__()
lapps = apps[:]
lapps.insert(0, 'toolkit')
of = os.popen('make -f mozilla/client.mk ' + \
' '.join(['echo-variable-LOCALES_' + app for app in lapps]))
for val in of.readlines():
self[lapps.pop(0)] = val.strip().split()
for k,v in self.iteritems():
if k == 'toolkit':
continue
self[k] = [d for d in v if d not in self['toolkit']]
class Components(dict):
'''
Subclass of dict to map module dirs to applications. This reverses the
mapping you'd get from a Modules class, and it in fact uses one to do
its job.
'''
def __init__(self, apps):
modules = Modules(apps)
for mod, lst in modules.iteritems():
for c in lst:
self[c] = mod
def allLocales(apps):
'''
Get a locales hash for the given list of applications, mapping
applications to the list of languages given by all-locales.
Adds a module 'toolkit' holding all languages for all applications, too.
'''
locales = {}
all = set()
for app in apps:
path = 'mozilla/%s/locales/all-locales' % app
locales[app] = [l.strip() for l in open(path)]
all.update(locales[app])
locales['toolkit'] = list(all)
return locales
def get_base_path(mod, loc):
'statics for path patterns and conversion'
__l10n = 'l10n/%(loc)s/%(mod)s'
__en_US = 'mozilla/%(mod)s/locales/en-US'
if loc == 'en-US':
return __en_US % {'mod': mod}
return __l10n % {'mod': mod, 'loc': loc}
def get_path(mod, loc, leaf):
return get_base_path(mod, loc) + '/' + leaf

Просмотреть файл

@ -1,425 +0,0 @@
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
# The contents of this file are subject to the Mozilla Public License Version
# 1.1 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
# http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is l10n test automation.
#
# The Initial Developer of the Original Code is
# Mozilla Foundation
# Portions created by the Initial Developer are Copyright (C) 2006
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# Axel Hecht <l10n@mozilla.com>
#
# Alternatively, the contents of this file may be used under the terms of
# either the GNU General Public License Version 2 or later (the "GPL"), or
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
# in which case the provisions of the GPL or the LGPL are applicable instead
# of those above. If you wish to allow use of your version of this file only
# under the terms of either the GPL or the LGPL, and not to allow others to
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK *****
import logging
import Paths
import Parser
class Base:
'''Base class for all tests'''
def __init__(self):
if not hasattr(self, 'leafName'):
self.leafName = 'TODO'
logging.warning(' ' + self + ' does not have leafName set, writing to TODO')
def run(self):
'''Run this test for all locales, returns a dictionary with results'''
pass
def serialize(self, result, saveHandler):
'''Serialize the previously generated result, writes the dictionary
by default'''
return saveHandler(result, self.leafName)
pass
def failureTest(self, myResult, failureResult):
pass
import CompareLocales
class CompareTest(Base):
'''Test class to compare locales'''
def __init__(self, apps = ['browser', 'mail']):
'''Initializes the test object'''
self.apps = apps
pass
def run(self):
'''Runs CompareLocales.compare()'''
return CompareLocales.compare(apps=self.apps)
def serialize(self, result, saveHandler):
'''Serialize the CompareLocales result by locale into
cmp-details-ab-CD
and a compacted version into
cmp-data
'''
class Separator:
def __init__(self):
self.leafBase = 'cmp-details-'
self.components = Paths.Components(['browser','mail'])
def getDetails(self, res, locale):
dic = {}
res[locale]['tested'].sort()
self.collectList('missing', res[locale], dic)
self.collectList('obsolete', res[locale], dic)
saveHandler(dic, self.leafBase + locale + '.json')
def collectList(self, name, res, dic):
dic[name] = {}
if not res.has_key(name):
res[name] = []
counts = dict([(mod,0) for mod in res['tested']])
counts['total'] = len(res[name])
for mod, path, key in res[name]:
counts[self.components[mod]] +=1
if not dic[name].has_key(mod):
dic[name][mod] = {path:[key]}
continue
if not dic[name][mod].has_key(path):
dic[name][mod][path] = [key]
else:
dic[name][mod][path].append(key)
res[name] = counts
name += 'Files'
dic[name] = {}
if not res.has_key(name):
res[name] = []
counts = dict([(mod,0) for mod in res['tested']])
counts['total'] = len(res[name])
for mod, path in res[name]:
counts[self.components[mod]] +=1
if not dic[name].has_key(mod):
dic[name][mod] = [path]
else:
dic[name][mod].append(path)
res[name] = counts
s = Separator()
for loc, lResult in result.iteritems():
s.getDetails(result, loc)
saveHandler(result, 'cmp-data.json')
def failureTest(self, myResult, failureResult):
'''signal pass/warn/failure for each locale'''
def sumdata(data, part):
res = 0
for mod in [u'browser', u'toolkit']:
res += data[part][mod] + data[part + u'Files'][mod]
return res
def getState(data):
ret = 0
if sumdata(data, u'obsolete') > 0:
ret |= 1
if sumdata(data, u'missing') > 0:
ret |= 2
return ret
for loc, val in myResult.iteritems():
if not failureResult.has_key(loc):
failureResult[loc] = getState(val)
else:
failureResult |= getState(val)
from xml import sax
from types import DictType, FunctionType
import md5
from codecs import utf_8_encode
import re
import os
class SearchTest(Base):
"""Test class to collect information from search plugins and to
verify that they're doing something good.
"""
def __init__(self):
'''Set up the test class with a good leaf name'''
self.leafName = 'search-results.json'
pass
def run(self):
'''Collect all data from the MozSearch plugins in both the /cvsroot
repository for en-US and the /l10n repository for locales
'''
class DummyHandler(sax.handler.ContentHandler):
def startDocument(self):
self.md5 = md5.new()
self.indent = ''
self.engine = {'urls':[]}
self.lNames = []
self.textField = None
self.content = ''
return
def endDocument(self):
self.engine['md5'] = self.md5.hexdigest()
return
def startElementNS(self, (ns, local), qname, attrs):
if self.textField:
logging.warning('Found Element, but expected CDATA.')
self.indent += ' '
if ns != u'http://www.mozilla.org/2006/browser/search/':
raise UserWarning, ('bad namespace: ' + ns)
self.lNames.append(local)
handler = self.getOpenHandler()
if handler:
handler(self, attrs)
self.update(ns+local)
for qna in attrs.getQNames():
self.update(qna[0] + qna[1] + attrs.getValueByQName(qna))
return
def endElementNS(self, (ns, local), qname):
if self.textField:
self.engine[self.textField] = self.content
self.textField = None
self.content = ''
self.lNames.pop()
self.indent = self.indent[0:-2]
def characters(self, content):
self.update(content)
if not self.textField:
return
self.content += content
def update(self, content):
self.md5.update(utf_8_encode(content)[0])
def openURL(self, attrs):
entry = {'params':{},
'type': attrs.getValueByQName(u'type'),
'template': attrs.getValueByQName(u'template')}
self.engine['urls'].append(entry)
def handleParam(self, attrs):
try:
self.engine['urls'][-1]['params'][attrs.getValueByQName(u'name')] = attrs.getValueByQName(u'value')
except KeyError:
raise UserWarning, 'bad param'
return
def handleMozParam(self, attrs):
mp = None
try:
mp = { 'name': attrs.getValueByQName(u'name'),
'condition': attrs.getValueByQName(u'condition'),
'trueValue': attrs.getValueByQName(u'trueValue'),
'falseValue': attrs.getValueByQName(u'falseValue')}
except KeyError:
try:
mp = {'name': attrs.getValueByQName(u'name'),
'condition': attrs.getValueByQName(u'condition'),
'pref': attrs.getValueByQName(u'pref')}
except KeyError:
raise UserWarning, 'bad mozParam'
if self.engine['urls'][-1].has_key('MozParams'):
self.engine['urls'][-1]['MozParams'].append(mp)
else:
self.engine['urls'][-1]['MozParams'] = [mp]
return
def handleShortName(self, attrs):
self.textField = 'ShortName'
return
def handleImage(self, attrs):
self.textField = 'Image'
return
def getOpenHandler(self):
return self.getHandler(DummyHandler.openHandlers)
def getHandler(self, handlers):
for local in self.lNames:
if type(handlers) != DictType or not handlers.has_key(local):
return
handlers = handlers[local]
if handlers.has_key('_handler'):
return handlers['_handler']
return
openHandlers = {'SearchPlugin':
{'ShortName': {'_handler': handleShortName},
'Image': {'_handler': handleImage},
'Url':{'_handler': openURL,
'Param': {'_handler':handleParam},
'MozParam': {'_handler':handleMozParam}
}
}
}
handler = DummyHandler()
parser = sax.make_parser()
parser.setContentHandler(handler)
parser.setFeature(sax.handler.feature_namespaces, True)
locales = [loc.strip() for loc in open('mozilla/browser/locales/all-locales')]
locales.insert(0, 'en-US')
sets = {}
details = {}
for loc in locales:
l = logging.getLogger('locales.' + loc)
try:
lst = open(Paths.get_path('browser',loc,'searchplugins/list.txt'),'r')
except IOError:
l.error("Locale " + loc + " doesn't have search plugins")
details[Paths.get_path('browser',loc,'searchplugins/list.txt')] = {
'error': 'not found'
}
continue
sets[loc] = {'list': []}
regprop = Paths.get_path('browser', loc, 'chrome/browser-region/region.properties')
p = Parser.getParser(regprop)
p.read(regprop)
orders = {}
for key, val in p:
m = re.match('browser.search.order.([1-9])', key)
if m:
orders[val.strip()] = int(m.group(1))
elif key == 'browser.search.defaultenginename':
sets[loc]['default'] = val.strip()
sets[loc]['orders'] = orders
for fn in lst:
name = fn.strip()
if len(name) == 0:
continue
leaf = 'searchplugins/' + name + '.xml'
_path = Paths.get_path('browser','en-US', leaf)
if not os.access(_path, os.R_OK):
_path = Paths.get_path('browser', loc, leaf)
l.debug('testing ' + _path)
sets[loc]['list'].append(_path)
try:
parser.parse(_path)
except IOError:
l.error("can't open " + _path)
details[_path] = {'_name': name, 'error': 'not found'}
continue
except UserWarning, ex:
l.error("error in searchplugin " + _path)
details[_path] = {'_name': name, 'error': ex.args[0]}
continue
except sax._exceptions.SAXParseException, ex:
l.error("error in searchplugin " + _path)
details[_path] = {'_name': name, 'error': ex.args[0]}
continue
details[_path] = handler.engine
details[_path]['_name'] = name
engines = {'locales': sets,
'details': details}
return engines
def failureTest(self, myResult, failureResult):
'''signal pass/warn/failure for each locale
Just signaling errors in individual plugins for now.
'''
for loc, val in myResult['locales'].iteritems():
l = logging.getLogger('locales.' + loc)
# Verify that there are no errors in the engine parsing,
# and that there default engine is the first one.
if (not val['orders'].has_key(val['default'])) or val['orders'][val['default']] != 1:
l.error('Default engine is not first in order in locale ' + loc)
if not failureResult.has_key(loc):
failureResult[loc] = 2
else:
failureResult[loc] |= 2
for p in val['list']:
# no logging, that is already reported above
if myResult['details'][p].has_key('error'):
if not failureResult.has_key(loc):
failureResult[loc] = 2
else:
failureResult[loc] |= 2
class RSSReaderTest(Base):
"""Test class to collect information about RSS readers and to
verify that they might be working.
"""
def __init__(self):
'''Set up the test class with a good leaf name'''
self.leafName = 'feed-reader-results.json'
pass
def run(self):
'''Collect the data from browsers region.properties for all locales
'''
locales = [loc.strip() for loc in open('mozilla/browser/locales/all-locales')]
uri = re.compile('browser\\.contentHandlers\\.types\\.([0-5])\\.uri')
title = re.compile('browser\\.contentHandlers\\.types\\.([0-5])\\.title')
res = {}
for loc in locales:
l = logging.getLogger('locales.' + loc)
regprop = Paths.get_path('browser', loc, 'chrome/browser-region/region.properties')
p = Parser.getParser(regprop)
p.read(regprop)
uris = {}
titles = {}
for key, val in p:
m = uri.match(key)
if m:
o = int(m.group(1))
if uris.has_key(o):
l.error('Double definition of RSS reader ' + o)
uris[o] = val.strip()
else:
m = title.match(key)
if m:
o = int(m.group(1))
if titles.has_key(o):
l.error('Double definition of RSS reader ' + o)
titles[o] = val.strip()
ind = sorted(uris.keys())
if ind != range(len(ind)) or ind != sorted(titles.keys()):
l.error('RSS Readers are badly set up')
res[loc] = [(titles[o], uris[o]) for o in ind]
return res
class BookmarksTest(Base):
"""Test class to collect information about bookmarks and check their
structure.
"""
def __init__(self):
'''Set up the test class with a good leaf name'''
self.leafName = 'bookmarks-results.json'
pass
def run(self):
'''Collect the data from bookmarks.html for all locales
'''
locales = [loc.strip() for loc in open('mozilla/browser/locales/all-locales')]
bm = Parser.BookmarksParser()
res = {}
for loc in locales:
try:
bm.read('l10n/%s/browser/profile/bookmarks.html'%loc)
res[loc] = bm.getDetails()
except Exception, e:
logging.getLogger('locale.%s'%loc).error('Bookmarks are busted, %s'%e)
return res
def failureTest(self, myResult, failureResult):
'''signal pass/warn/failure for each locale
Just signaling errors for now.
'''
locales = [loc.strip() for loc in open('mozilla/browser/locales/all-locales')]
bm = Parser.BookmarksParser()
bm.read('mozilla/browser/locales/en-US/profile/bookmarks.html')
enUSDetails = bm.getDetails()
for loc in locales:
if not myResult.has_key(loc):
if not failureResult.has_key(loc):
failureResult[loc] = 2
else:
failureResult[loc] |= 2

Просмотреть файл

Просмотреть файл

@ -1,124 +0,0 @@
#! python
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
# The contents of this file are subject to the Mozilla Public License Version
# 1.1 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
# http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is l10n test automation.
#
# The Initial Developer of the Original Code is
# Mozilla Foundation
# Portions created by the Initial Developer are Copyright (C) 2006
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# Axel Hecht <l10n@mozilla.com>
#
# Alternatively, the contents of this file may be used under the terms of
# either the GNU General Public License Version 2 or later (the "GPL"), or
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
# in which case the provisions of the GPL or the LGPL are applicable instead
# of those above. If you wish to allow use of your version of this file only
# under the terms of either the GPL or the LGPL, and not to allow others to
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK *****
import logging
from optparse import OptionParser
from pprint import pprint
from Mozilla import Paths, CompareLocales
usage = 'usage: %prog [options] language1 [language2 ...]'
parser = OptionParser(usage=usage)
parser.add_option('-a', '--application', default='browser',
help='compare localizations for the specified application'+
' [default: browser]')
parser.add_option('-v', '--verbose', action='count', dest='v', default=0,
help='Make more noise')
parser.add_option('-q', '--quiet', action='count', dest='q', default=0,
help='Make more noise')
(options, args) = parser.parse_args()
if len(args) == 0:
parser.error('At least one language required')
# log as verbose or quiet as we want, warn by default
logging.basicConfig(level=(logging.WARNING - (options.v - options.q)*10))
# import Paths loaded all-locales for both browser and mail, we overwrite
# that with our settings before calling into CompareLocales
locales = {options.application: args}
# actually compare the localizations
res = CompareLocales.compare(testLocales=locales)
# helper class to merge all the lists into more consice
# dicts
class Separator:
def __init__(self, apps):
self.components = Paths.Components(apps)
pass
def getDetails(self, res, locale):
dic = {}
res[locale]['tested'].sort()
self.collectList('missing', res[locale], dic)
self.collectList('obsolete', res[locale], dic)
return dic
def collectList(self, name, res, dic):
dic[name] = {}
if name not in res:
res[name] = []
counts = dict([(mod,0) for mod in res['tested']])
counts['total'] = len(res[name])
for mod, path, key in res[name]:
counts[self.components[mod]] +=1
if mod not in dic[name]:
dic[name][mod] = {path:[key]}
continue
if path not in dic[name][mod]:
dic[name][mod][path] = [key]
else:
dic[name][mod][path].append(key)
res[name] = counts
name += 'Files'
dic[name] = {}
if name not in res:
res[name] = []
counts = dict([(mod,0) for mod in res['tested']])
counts['total'] = len(res[name])
for mod, path in res[name]:
counts[self.components[mod]] +=1
if mod not in dic[name]:
dic[name][mod] = [path]
else:
dic[name][mod].append(path)
res[name] = counts
s = Separator([options.application])
# pretty print results for all localizations
for loc in args:
print(loc + ':')
pprint(s.getDetails(res, loc))
result = res[loc]
pprint(result)
rate = result['changed']*100/ \
(result['changed'] + result['unchanged'] + \
result['missing']['total'])
print('%d%% of entries changed' % rate)

Просмотреть файл

@ -1,199 +0,0 @@
#! python
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
# The contents of this file are subject to the Mozilla Public License Version
# 1.1 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
# http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is l10n test automation.
#
# The Initial Developer of the Original Code is
# Mozilla Foundation
# Portions created by the Initial Developer are Copyright (C) 2007
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# Axel Hecht <l10n@mozilla.com>
#
# Alternatively, the contents of this file may be used under the terms of
# either the GNU General Public License Version 2 or later (the "GPL"), or
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
# in which case the provisions of the GPL or the LGPL are applicable instead
# of those above. If you wish to allow use of your version of this file only
# under the terms of either the GPL or the LGPL, and not to allow others to
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK *****
import logging
import os.path
import re
from optparse import OptionParser
from pprint import pprint
from zipfile import ZipFile
from Mozilla import Parser
usage = 'usage: %prog [options] language-pack reference-pack'
parser = OptionParser(usage=usage)
parser.add_option('-v', '--verbose', action='count', dest='v', default=0,
help='Report more detail')
parser.add_option('-q', '--quiet', action='count', dest='q', default=0,
help='Report less detail')
(options, args) = parser.parse_args()
if len(args) != 2:
parser.error('language pack and reference pack required')
# log as verbose or quiet as we want, warn by default
logging.basicConfig(level=(logging.WARNING - (options.v - options.q)*10))
# we expect two jar files
assert args[0].endswith('.jar') and args[1].endswith('.jar') \
, "Only jar files supported at the moment"
l10n_jar = ZipFile(args[0])
if l10n_jar.testzip():
parser.error('bad language pack: ' + args[0])
l10n_locale = os.path.basename(args[0][:-4])
ref_jar = ZipFile(args[1])
if ref_jar.testzip():
parser.error('bad language pack: ' + args[1])
ref_locale = os.path.basename(args[1][:-4])
l10n_entries = set(l10n_jar.namelist())
ref_entries = set(ref_jar.namelist())
common_entries = l10n_entries & ref_entries
l10n_entries = sorted(l10n_entries - common_entries)
ref_entries = sorted(ref_entries - common_entries)
common_entries = sorted(common_entries)
result = {'missing':[],'obsolete':[],
'missingFiles':[],'obsoleteFiles':[],
'changed':0,'unchanged':0,'keys':0}
key = re.compile('[kK]ey')
# helper function to compare two jar entries
def compareFiles(l10n_name, ref_name):
try:
parser = Parser.getParser(ref_name)
except UserWarning:
logging.warning(" Can't compare " + ref_name)
return
parser.parse(ref_jar.read(ref_name))
enTmp = parser.mapping()
parser.parse(l10n_jar.read(l10n_name))
for k,v in parser:
if k not in enTmp:
result['obsolete'].append((l10n_name,k))
continue
enVal = enTmp[k]
del enTmp[k]
if key.search(k):
result['keys'] += 1
else:
if enVal == v:
result['unchanged'] +=1
logging.info('%s in %s unchanged' %
(k, name))
else:
result['changed'] +=1
result['missing'] += [(l10n_name,k) for k in enTmp.keys()]
# compare those entries with identical name
for name in common_entries:
compareFiles(name, name)
# compare those entries with different name.
# if the path matches locale/ab-CD/foo, replace the
# language code with @AB_CD@ to compare
#
# We detect missing and obsolete files here, too.
l10n_key = ref_key = None
while len(l10n_entries) and len(ref_entries):
# we need to check the next entry in the tested pack
if not l10n_key:
l10n_key = l10n_entry = l10n_entries.pop(0)
if l10n_key.startswith('locale/' + l10n_locale) and \
not l10n_key.endswith('/'):
# it's a locale/ab-CD file, but not a directory
l10n_key = l10n_key.replace('locale/' + l10n_locale, 'locale/@AB_CD@')
else:
# directories and non-locale/ab-CD files are assumed to be obsolete
l10n_key = None
result['obsoleteFiles'].append(l10n_entry)
continue
# we need to check the next entry in the reference pack
if not ref_key:
ref_key = ref_entry = ref_entries.pop(0)
if ref_key.startswith('locale/' + ref_locale) and \
not ref_key.endswith('/'):
ref_key = ref_key.replace('locale/' + ref_locale, 'locale/@AB_CD@')
else:
ref_key = None
result['missingFiles'].append(ref_entry)
continue
# check if we found matching files
if l10n_key != ref_key:
# not, report missing or obsolete, and skip
if l10n_key < ref_key:
l10n_key = None
result['obsoleteFiles'].append(l10n_entry)
else:
ref_key = None
result['missingFiles'].append(ref_entry)
continue
compareFiles(l10n_entry, ref_entry)
# both entries dealt with, unset keys to pop new ones in both jars
l10n_key = ref_key = None
# remaining files are either missing or obsolete
result['missingFiles'] += ref_entries
result['obsoleteFiles'] += l10n_entries
# collapse the arrays to a more consice hash.
dic = dict()
def collectList(name):
dic[name] = {}
if name not in result:
result[name] = []
for path, key in result[name]:
if path not in dic[name]:
dic[name][path] = [key]
else:
dic[name][path].append(key)
dic[name][path].sort()
name += 'Files'
dic[name] = []
if name not in result:
result[name] = []
for path in result[name]:
dic[name].append(path)
collectList('missing')
collectList('obsolete')
pprint(dic)
rate = result['changed']*100/ \
(result['changed'] + result['unchanged'] + result['missing'])
print('%d%% of entries changed' % rate)

Просмотреть файл

@ -1,249 +0,0 @@
#! python
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
# The contents of this file are subject to the Mozilla Public License Version
# 1.1 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
# http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is l10n test automation.
#
# The Initial Developer of the Original Code is
# Mozilla Foundation
# Portions created by the Initial Developer are Copyright (C) 2006
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# Axel Hecht <l10n@mozilla.com>
#
# Alternatively, the contents of this file may be used under the terms of
# either the GNU General Public License Version 2 or later (the "GPL"), or
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
# in which case the provisions of the GPL or the LGPL are applicable instead
# of those above. If you wish to allow use of your version of this file only
# under the terms of either the GPL or the LGPL, and not to allow others to
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK *****
import logging
import sys
import os
import os.path
from datetime import datetime
import time
from optparse import OptionParser
import gzip
import codecs
from Mozilla import Parser, CompareLocales, Paths, Tests
import simplejson
#
# Helper classes
#
#
# Logging
#
class LogHandler(logging.Handler):
def __init__(self):
self.log = []
logging.Handler.__init__(self)
def emit(self, record):
self.log.append((record.name, record.levelname, record.getMessage().strip()))
#
# JSON with optional gzip
#
class Wrapper:
def __init__(self, path, name):
self.p = os.path.join(path, name)
self.n = name
self.f = None
if opts.gzip:
self.p += '.gz'
def open(self, mode):
if self.f:
self.f.close()
if opts.gzip:
mode += 'b'
self.f = open(self.p, mode)
if opts.gzip:
self.f = gzip.GzipFile(fileobj = self.f, filename = self.n)
self.w = codecs.getwriter('utf-8')(self.f)
self.r = codecs.getreader('utf-8')(self.f)
def write(self, str):
self.w.write(str)
def read(self, size = -1):
return self.r.read(size)
def rewind(self):
if opts.gzip:
self.f.rewind()
else:
self.f.seek(0,0)
def close(self):
if opts.gzip:
f = self.f.fileobj;
self.f.close()
if opts.gzip:
f.close()
self.w = self.r = self.f = None
#
# Helper function for JSON output with optional gzip
#
def saveJSON(dic, localName):
name = os.path.join(basePath, localName) ;
if opts.gzip:
f = open(name + '.gz', 'wb')
s = gzip.GzipFile(fileobj = f, filename = localName)
else:
f = open(name, 'w')
s = f
sw = codecs.getwriter('utf-8')(s)
sw.write(simplejson.dumps(dic, sort_keys=True))
sw.reset()
if opts.gzip:
s.close()
f.close()
lvl = logging.WARNING
date = datetime.utcnow().replace(second=0,microsecond=0).isoformat(' ')
# parse commandline arguments
cp = OptionParser(version='0.2')
cp.add_option('-v', '--verbose', action='count', dest='v', default=0,
help='Make more noise')
cp.add_option('-q', '--quiet', action='count', dest='q', default=0,
help='Make less noise')
cp.add_option('-O', '--base-dir', type='string', dest='target',
default='results',
help='Destination base directory')
cp.add_option('-c', '--checkout', action='store_true', dest='checkout',
default=False,
help='Run make -f client.mk l10n-checkout [Default: not]')
cp.add_option('-d', '--date', type='string', dest='date',
help='Explicit start date or subdir [Default: now]')
cp.add_option('-z',action="store_true", dest="gzip", default=False,
help='Use gzip compression for output')
cp.add_option('-w','--enable-waterfall', action="store_true",
dest="waterfall", default=False,
help='Update waterfall data')
cp.add_option('--end-date', type='string', dest='enddate',
help='Explicit (faked) end date')
cp.add_option('--application', type='string',
help='Test only one app, by default tests browser and mail')
opts, optlist = cp.parse_args(sys.argv[1:])
#
# Set up Logging
#
logging.basicConfig(level=(logging.WARNING + 10*(opts.q - opts.v)))
# Add a handler to store the output
h = LogHandler()
logging.getLogger('').addHandler(h)
#
# Check that we're in the right location and check out if requested
#
try:
os.chdir('mozilla')
if opts.checkout:
env = ''
l = logging.getLogger('cvsco')
if opts.date:
env = 'MOZ_CO_DATE="' + opts.date + ' +0" '
fh = os.popen(env + 'make -f client.mk l10n-checkout')
for ln in fh:
l.info(ln.strip())
if fh.close():
raise Exception('cvs checkout failed')
os.chdir('..')
except Exception,e:
sys.exit(str(e))
if not opts.date:
opts.date = date # use default set above
logging.debug(' Ensure output directory')
# replace : with -
opts.date = opts.date.replace(':','-')
if not os.path.isdir(opts.target):
sys.exit('error: ' + opts.target + ' is not a directory')
if opts.waterfall:
startdate = time.mktime(time.strptime(opts.date, '%Y-%m-%d %H-%M-%S')) + time.altzone
basePath = os.path.join(opts.target, opts.date)
if not os.path.isdir(basePath):
os.mkdir(basePath)
apps = ['browser', 'mail']
if opts.application:
apps = [opts.application]
tests = [Tests.CompareTest(apps = apps),
Tests.SearchTest(),
Tests.RSSReaderTest(),
Tests.BookmarksTest()]
drop = {}
for test in tests:
res = test.run()
test.serialize(res, saveJSON)
if opts.waterfall:
test.failureTest(res, drop)
if not opts.waterfall:
saveJSON(h.log, 'buildlog.json')
sys.exit()
if opts.enddate:
endtime = time.mktime(time.strptime(opts.enddate, '%Y-%m-%d %H:%M:%S')) + time.altzone
else:
endtime = time.mktime(datetime.now().timetuple())
f = None
w = Wrapper(opts.target, 'waterfall.json')
if os.path.isfile(w.p):
w.open('r')
water = simplejson.load(w)
else:
water = []
water.append((opts.date, (startdate, endtime), drop))
#
# Check if we need to rotate the waterfall
#
rotateLen = 24
if len(water) > rotateLen * 1.5:
# rotate, maximum of 16 logs
suffix = ''
if opts.gzip:
suffix = '.gz'
fnames = [os.path.join(opts.target, 'waterfall-%x.json'%i) + suffix for i in range(16)]
# remove oldest log
if os.path.isfile(fnames[15]):
os.remove(fnames[15])
for l in range(14, -1, -1):
if os.path.isfile(fnames[l]):
os.rename(fnames[l], fnames[l+1])
w0 = Wrapper('.', fnames[0])
w0.open('w')
simplejson.dump(water[:rotateLen], w0, sort_keys=True)
w0.close()
water = water[rotateLen:]
w.open('w')
simplejson.dump(water, w, sort_keys=True)
w.close()
saveJSON(h.log, 'buildlog.json')

Просмотреть файл

@ -1,105 +0,0 @@
#!python
# ***** BEGIN LICENSE BLOCK *****
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
#
# The contents of this file are subject to the Mozilla Public License Version
# 1.1 (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
# http://www.mozilla.org/MPL/
#
# Software distributed under the License is distributed on an "AS IS" basis,
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
# for the specific language governing rights and limitations under the
# License.
#
# The Original Code is l10n test automation.
#
# The Initial Developer of the Original Code is
# Mozilla Foundation
# Portions created by the Initial Developer are Copyright (C) 2006
# the Initial Developer. All Rights Reserved.
#
# Contributor(s):
# Axel Hecht <l10n@mozilla.com>
#
# Alternatively, the contents of this file may be used under the terms of
# either the GNU General Public License Version 2 or later (the "GPL"), or
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
# in which case the provisions of the GPL or the LGPL are applicable instead
# of those above. If you wish to allow use of your version of this file only
# under the terms of either the GPL or the LGPL, and not to allow others to
# use your version of this file under the terms of the MPL, indicate your
# decision by deleting the provisions above and replace them with the notice
# and other provisions required by the GPL or the LGPL. If you do not delete
# the provisions above, a recipient may use your version of this file under
# the terms of any one of the MPL, the GPL or the LGPL.
#
# ***** END LICENSE BLOCK *****
import sys
import logging
from optparse import OptionParser
from urlparse import urlparse
import httplib
from urllib2 import urlopen
EN_US_FEED = 'http://newsrss.bbc.co.uk/rss/newsonline_world_edition/front_page/rss.xml'
FEEDSERVER = '%s.fxfeeds.mozilla.com'
FEEDPATH = '/%s/firefox/headlines.xml'
L10NFEEDS = 'http://wiki.mozilla.org/Firefox2/L10n_Feed_Redirects?action=raw'
op = OptionParser()
op.add_option('--oldid', dest='oldid',
help='explicitly give a version number on the wiki')
op.add_option('-v', dest='verbose', action='count', default=0,
help='increase verbosity')
(options, args) = op.parse_args()
if len(args) != 1:
sys.exit('all-locales or shipped-locales path expected')
logging.basicConfig(level=(logging.WARNING - options.verbose*10))
if options.oldid:
L10NFEEDS += '&oldid=' + options.oldid
lFeeds = urlopen(L10NFEEDS)
redirs = {}
for row in lFeeds:
d, loc, url = row.split(' ', 2)
redirs[loc] = url.strip()
# parse all-locales and shipped-locales, only take first bunch
lFile = open(args[0])
locales = [ln.split(' ', 1)[0].strip() for ln in lFile]
# ignore ja-JP-mac, same bookmarks as ja
def not_ja_JP_mac(loc): return loc != 'ja-JP-mac'
locales = filter(not_ja_JP_mac, locales)
for loc in locales:
logging.debug('testing ' + loc)
server = FEEDSERVER % loc
path = FEEDPATH % loc
while server.endswith('mozilla.com'):
url = None
conn = httplib.HTTPConnection(server)
conn.request('HEAD', path)
r = conn.getresponse()
if r.status != 302:
logging.error('mozilla.com loses feed for ' + loc)
server = ''
continue
url = r.getheader('location')
server, path = urlparse(url)[1:3]
conn.close()
refurl = EN_US_FEED
if redirs.has_key(loc):
refurl = redirs[loc]
if url != refurl:
print loc, "FAIL"
logging.info(str(url) + ' is not ' + refurl)
else:
logging.debug(loc + ' PASS')

Просмотреть файл

@ -1,171 +0,0 @@
#! python
from xml import sax
from types import DictType, FunctionType
import md5
import os
import sys
import re
import logging
from codecs import utf_8_encode
from Mozilla import Paths, Parser
import simplejson
lvl = logging.WARNING
# parse commandline arguments
argsiter = sys.argv.__iter__()
# drop command
argsiter.next()
for arg in argsiter:
if arg == '-V':
lvl -= 10
logging.basicConfig(level=lvl)
class DummyHandler(sax.handler.ContentHandler):
def startDocument(self):
self.md5 = md5.new()
self.indent = ''
self.engine = {'urls':[]}
self.lNames = []
self.textField = None
return
def endDocument(self):
self.engine['md5'] = self.md5.hexdigest()
return
def startElementNS(self, (ns, local), qname, attrs):
self.indent += ' '
if ns != u'http://www.mozilla.org/2006/browser/search/':
raise UserWarning, ('bad namespace: ' + ns)
self.lNames.append(local)
handler = self.getOpenHandler()
if handler:
handler(self, attrs)
self.update(ns+local)
for qna in attrs.getQNames():
self.update(qna[0] + qna[1] + attrs.getValueByQName(qna))
return
def endElementNS(self, (ns, local), qname):
self.lNames.pop()
self.indent = self.indent[0:-2]
def characters(self, content):
self.update(content)
if not self.textField:
return
self.engine[self.textField] = content
self.textField = None
def update(self, content):
self.md5.update(utf_8_encode(content)[0])
def openURL(self, attrs):
entry = {'params':{},
'type': attrs.getValueByQName(u'type'),
'template': attrs.getValueByQName(u'template')}
self.engine['urls'].append(entry)
def handleParam(self, attrs):
try:
self.engine['urls'][-1]['params'][attrs.getValueByQName(u'name')] = attrs.getValueByQName(u'value')
except KeyError:
raise UserWarning, 'bad param'
return
def handleMozParam(self, attrs):
try:
self.engine['urls'][-1]['MozParams'] = {
'name': attrs.getValueByQName(u'name'),
'condition': attrs.getValueByQName(u'condition'),
'trueValue': attrs.getValueByQName(u'trueValue'),
'falseValue': attrs.getValueByQName(u'falseValue')}
except KeyError:
raise UserWarning, 'bad mozParam'
return
def handleShortName(self, attrs):
self.textField = 'ShortName'
return
def handleImage(self, attrs):
self.textField = 'Image'
return
def getOpenHandler(self):
return self.getHandler(DummyHandler.openHandlers)
def getHandler(self, handlers):
for local in self.lNames:
if type(handlers) != DictType or not handlers.has_key(local):
return
handlers = handlers[local]
if handlers.has_key('_handler'):
return handlers['_handler']
return
openHandlers = {'SearchPlugin':
{'ShortName': {'_handler': handleShortName},
'Image': {'_handler': handleImage},
'Url':{'_handler': openURL,
'Param': {'_handler':handleParam},
'MozParam': {'_handler':handleMozParam}
}
}
}
handler = DummyHandler()
parser = sax.make_parser()
parser.setContentHandler(handler)
parser.setFeature(sax.handler.feature_namespaces, True)
locales = [loc.strip() for loc in open('mozilla/browser/locales/all-locales')]
locales.insert(0, 'en-US')
sets = {}
details = {}
for loc in locales:
try:
lst = open(Paths.get_path('browser',loc,'searchplugins/list.txt'),'r')
except IOError:
logging.error("Locale " + loc + " doesn't have search plugins")
details[Paths.get_path('browser',loc,'searchplugins/list.txt')] = {
'error': 'not found'
}
continue
sets[loc] = {'list': []}
regprop = Paths.get_path('browser', loc, 'chrome/browser-region/region.properties')
p = Parser.getParser(regprop)
p.read(regprop)
orders = {}
for key, val in p:
m = re.match('browser.search.order.([1-9])', key)
if m:
orders[val.strip()] = int(m.group(1))
sets[loc]['orders'] = orders
for fn in lst:
name = fn.strip()
leaf = 'searchplugins/' + name + '.xml'
_path = Paths.get_path('browser','en-US', leaf)
if not os.access(_path, os.R_OK):
_path = Paths.get_path('browser', loc, leaf)
logging.info('testing ' + _path)
sets[loc]['list'].append(_path)
try:
parser.parse(_path)
except IOError:
logging.error("can't open " + _path)
details[_path] = {'_name': name, 'error': 'not found'}
continue
except UserWarning, ex:
logging.error("error in searchplugin " + _path)
details[_path] = {'_name': name, 'error': ex.args[0]}
continue
except sax._exceptions.SAXParseException, ex:
logging.error("error in searchplugin " + _path)
details[_path] = {'_name': name, 'error': ex.args[0]}
continue
details[_path] = handler.engine
details[_path]['_name'] = name
engines = {'locales': sets,
'details': details}
enginelist = details.keys()
enginelist.sort()
fp = open('search-results.js','w')
fp.write('results = ')
simplejson.dump(engines, fp, sort_keys=True)
fp.close()
print enginelist

Просмотреть файл

@ -1,32 +0,0 @@
from distutils.core import setup
from distutils.cmd import Command
import glob
class web(Command):
description = 'install web files'
user_options = [('target=','d','base directory for installation')]
def initialize_options(self):
self.target = None
pass
def finalize_options(self):
pass
def run(self):
self.ensure_dirname('target')
for f in glob.glob('web/*.*'):
if f.find('/CVS') >=0 or f.find('~') >= 0:
continue
self.copy_file(f, self.target)
setup(name="l10n-tools",
version="0.2",
author="Axel Hecht",
author_email="l10n@mozilla.com",
scripts=['scripts/compare-locales', 'scripts/verify-search',
'scripts/test-locales',
'scripts/verify-rss-redirects'],
package_dir={'': 'lib'},
packages=['Mozilla'],
cmdclass={'web': web}
)

Просмотреть файл

@ -1,147 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla.
*
* The Initial Developer of the Original Code is
* Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2006
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Axel Hecht <axel@pike.org>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
var bookmarksView = {
__proto__: baseView,
setUpHandlers: function() {
_t = this;
},
destroyHandlers: function() {
},
// Helper methods
createFullTree: function ct(aDetails, aNode, aName) {
if (!aDetails || ! (aDetails instanceof Object))
return;
var cat = new YAHOO.widget.TextNode(aName, aNode, true);
for each (postfix in ["Files", ""]) {
var subRes = aDetails[aName + postfix];
var append = postfix ? ' (files)' : '';
for (mod in subRes) {
var mn = new YAHOO.widget.TextNode(mod + append, cat, true);
for (fl in subRes[mod]) {
if (postfix) {
new YAHOO.widget.TextNode(subRes[mod][fl], mn, false);
continue;
}
var fn = new YAHOO.widget.TextNode(fl, mn, false);
var keys = [];
for each (k in subRes[mod][fl]) {
keys.push(k);
}
new YAHOO.widget.HTMLNode("<pre>" + keys.join("\n") + "</pre>", fn, true, false);
}
}
}
return cat;
}
};
var bookmarksController = {
__proto__: baseController,
get path() {
return 'results/' + this.tag + '/bookmarks-results.json';
},
beforeSelect: function() {
this.result = {};
this.isShown = false;
bookmarksView.setUpHandlers();
var _t = this;
var callback = function(obj) {
delete _t.req;
if (view != bookmarksView) {
// ignore, we have switched again
return;
}
_t.result = obj;
bookmarksView.updateView(keys(_t.result));
};
this.req = JSON.get('results/' + this.tag + '/bookmarks-results.json', callback);
},
beforeUnSelect: function() {
if (this.req) {
this.req.abort();
delete this.req;
}
bookmarksView.destroyHandlers();
},
showView: function(aClosure) {
// json onload handler does this;
},
getContent: function(aLoc) {
var row = view.getCell();
var inner = document.createElement('div');
row.appendChild(inner);
var r = this.result[aLoc];
var id = "bookmarks-" + aLoc;
inner.id = id;
var hasDetails = true;
t = new YAHOO.widget.TreeView(inner);
var d = this.result[aLoc];
var innerContent = d['__title__'];
function createChildren(aData, aParent, isOpen) {
if ('children' in aData) {
// Folder
innerContent = aData['__title__'];
if ('__desc__' in aData && aData['__desc__']) {
innerContent += '<br><em>' + aData['__desc__'] + '</em>';
}
var nd = new YAHOO.widget.HTMLNode(innerContent, aParent, isOpen, true);
for each (child in aData['children']) {
createChildren(child, nd, true);
}
}
else {
// Link
innerContent = '';
if ('ICON' in aData) {
innerContent = '<img src="' + aData['ICON'] + '">';
}
innerContent += '<a href="' + aData['HREF'] + '">' +
aData['__title__'] + '</a>';
if ('FEEDURL' in aData) {
innerContent += '<a href="' + aData['FEEDURL'] + '">&nbsp;<em>(FEED)</em></a>';
}
new YAHOO.widget.HTMLNode(innerContent, aParent, false, false);
}
}
createChildren(d, t.getRoot(), false);
t.draw();
return row;
}
};
controller.addPane('Bookmarks', 'bookmarks', bookmarksController,
bookmarksView);

Просмотреть файл

@ -1,409 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla.
*
* The Initial Developer of the Original Code is
* Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2006
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Axel Hecht <axel@pike.org>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
var controller = {}, view = {};
const kModules = ['browser','mail','toolkit'];
const Tier1 = ['en-GB', 'fr', 'de', 'ja', 'ja-JP-mac', 'pl', 'es-ES'];
const Tier2 = ['zh-CN', 'zh-TW', 'cs', 'da', 'nl', 'fi', 'hu', 'it', 'ko', 'pt-BR', 'pt-PT', 'ru', 'es-AR', 'sv-SE', 'tr'];
tierMap = {};
for each (var loc in Tier1) tierMap[loc] = 'Tier-1';
for each (var loc in Tier2) tierMap[loc] = 'Tier-2';
function keys(obj) {
var k = [];
for (var f in obj) k.push(f);
k.sort();
return k;
}
function JSON_c() {
this._requests = [];
this._getRequest = function() {
for each (var req in this._requests) {
if (!req.status)
return req;
}
req = new XMLHttpRequest();
this._requests.push(req);
return req;
};
};
JSON_c.prototype = {
cache : {
MAX_SIZE: 6,
_objs: {},
_lru: [],
get: function(aURL) {
if (!(aURL in this._objs)) {
return null;
}
var i = this._lru.indexOf(aURL);
for (var j = i; j>0; j--) {
this._lru[j] = this._lru[j-1];
}
this._lru[0] = aURL;
return this._objs[aURL];
},
put: function(aURL, aObject) {
this._lru.unshift(aURL);
this._objs[aURL] = aObject;
}
},
get : function(aURL, aCallback) {
var obj = this.cache.get(aURL);
if (obj) {
controller.delay(controller, aCallback, [obj]);
return;
}
var _t = this;
var req = this._getRequest();
req.overrideMimeType("text/plain"); // don't parse XML, this is js
req.onerror = function(event) {
_t.handleFailure(event.target);
event.stopPropagation();
};
req.onload = function(event) {
_t.handleSuccess(event.target);
event.stopPropagation();
};
req._mURL = aURL;
if (aCallback) {
req.callback = aCallback;
}
req.open("GET", aURL, true);
try {
req.send(null);
} catch (e) {
// work around send sending errors, but not the callback
this.handleFailure(req);
}
return req;
},
// callbacks
handleSuccess : function(o) {
if (o.responseText === undefined)
throw "expected response text in handleSuccess";
if (o.callback) {
var obj = eval('('+o.responseText+')');
this.cache.put(o._mURL, obj);
o.callback(obj);
delete o.callback;
}
},
handleFailure : function(o) {
YAHOO.widget.Logger("load failed with " + o.status + " " + o.statusText);
}
};
var JSON = new JSON_c();
baseView = {
init: function() {
this.content = document.getElementById('content');
var checks = document.getElementById('checks');
checks.addEventListener("click", view.onClickDisplay, true);
for (var i = 0; i < checks.childNodes.length; i++) {
if (checks.childNodes[i] instanceof HTMLInputElement) {
this.setTierDisplay(checks.childNodes[i]);
}
}
},
showHeader: function() {
document.getElementById('head').innerHTML='<td class="locale">Locale</td>';
},
updateView: function(aLocales, aClosure) {
YAHOO.widget.Logger.log('updateView called');
this.showHeader();
var oldIndex = 0;
var selection = null;
for each (loc in aLocales) {
var id = "row-" + loc;
var oldChild = this.content.childNodes[oldIndex++];
var t;
if (oldChild) {
t = oldChild;
t.innerHTML = '';
if (t.id != id) {
// we don't have the right row, make sure to remove the ID
// from the pre-existing one, just in case
var obsRow = document.getElementById(id);
if (obsRow) {
obsRow.id = '';
}
}
}
else {
t = document.createElement("tr");
this.content.appendChild(t);
}
t.id = id;
t.className = '';
if (tierMap[loc])
t.className += ' ' + tierMap[loc];
else
t.className += ' Tier-3';
t.innerHTML = '<td class="locale">' + loc + '</td>';
t.appendChild(controller.getContent(loc));
};
while ((oldChild = this.content.childNodes[oldIndex])) {
this.content.removeChild(oldChild);
}
},
addTab: function(aName, aKey) {
var tab = document.createElement('li');
tab.textContent = aName;
tab.id = '_tab_' + aKey;
document.getElementById('tabs').appendChild(tab);
tab.onclick = function(event){return controller.select(aKey);};
},
selectTab: function(aKey) {
var tabs = document.getElementById('tabs');
var id = '_tab_' + aKey;
for (var i=0; i < tabs.childNodes.length; i++) {
var tab = tabs.childNodes[i];
var toBeSelected = tab.id == id;
if (toBeSelected) {
tab.setAttribute('selected','selected');
}
else {
tab.removeAttribute('selected');
}
}
return true;
},
onClickDisplay: function(event) {
if (event.target.localName != 'input') {
return false;
}
var handler = function() {return function(){view.setTierDisplay(event.target)}};
window.setTimeout(handler(),10);
return true;
},
setTierDisplay: function(aTier, aTruth) {
if (aTruth === undefined && aTier instanceof HTMLInputElement) {
aTruth = aTier.checked;
}
var disable = aTruth;
var name = aTier;
if (aTier instanceof HTMLInputElement) {
name = aTier.name;
}
var id = 'style-' + name;
document.getElementById(id).disabled = disable;
return false;
},
setTag: function(aTag) {
document.getElementById('tag-view').value = aTag;
},
getCell: function() {
return document.createElement('td');
},
getClass: function(aLoc) {
if (tierMap[aLoc]) {
return tierMap[aLoc];
}
return 'Tier-3';
}
};
baseController = {
_l: [],
_c: null,
_pending: [],
_target: null,
_tag: '.',
beforeUnSelect: function(){},
beforeSelect: function(){},
get locales() {
return this._l;
},
get tag() {
return baseController._tag;
},
set tag(aTag) {
baseController._tag = aTag;
view.setTag(aTag);
},
get path() {
throw 'not implemented';
},
addLocales: function(lst) {
var nl = lst.filter(function(el,i,a) {return this._l.indexOf(el) < 0;}, this);
this._l = this._l.concat(nl);
this._l.sort();
},
select: function(aKey) {
if (this._target == aKey) {
return;
}
if (this._target)
this._c[this._target].controller.beforeUnSelect();
this._target = aKey;
var nCV = this._c[this._target];
view = nCV.view;
controller = nCV.controller;
controller.beforeSelect();
controller._target = aKey;
view.selectTab(aKey);
this.delay(controller, controller.showView, []);
//controller.ensureData(aKey, nCV.controller.showView, nCV.controller);
},
ensureData: function(aKey, aCallback, aController) {
var p = a;
},
showView: function(aClosure) {
view.updateView(controller.locales, aClosure);
},
showLog: function(aTag, aLocale) {
var _t = this;
var dlgProps = { xy: ["1em", "1em"], height: "40em", width: "40em",
modal:true, draggable:false }
var dlg = new YAHOO.widget.SimpleDialog("log-dlg", dlgProps);
var prefix = '';
if (aLocale) {
prefix = '[' + aLocale + '] ';
}
dlg.setHeader(prefix + 'build log, ' + aTag);
dlg.setBody('Loading &hellip;');
var okButton = {
text: 'OK',
handler: function(){
this.hide();
this.destroy()
},
isDefault: true
};
dlg.cfg.queueProperty("buttons", [okButton]);
dlg.render(document.body);
dlg.moveTo(10, 10);
document.body.scrollTop = 0;
var callback = function(obj) {
_t.handleLog.apply(_t, [obj, dlg, aLocale]);
};
JSON.get('results/' + aTag + '/buildlog.json', callback);
},
handleLog: function(aLog, aDlg, aLocale) {
var df = document.createDocumentFragment();
var filter = function(lr) {
return true;
}
if (aLocale) {
filter = function(lr) {
var logName = lr[0];
var level = lr[1];
var msg = lr[2];
var loc = '/' + aLocale + '/';
if (logName == 'cvsco') {
return msg.indexOf('mozilla/') >= 0 ||
msg.indexOf(loc) >= 0 ||
msg.indexOf('make[') >= 0 ||
msg.indexOf('checkout') >= 0;
}
if (logName == 'locales') {
return msg.indexOf(loc) >= 0;
}
return logName == ('locales.' + aLocale);
}
}
for each (var r in aLog) {
if (!filter(r)) {
continue;
}
var d = document.createElement('pre');
d.className = 'log-row ' + r[1];
// XXX filter on r[0:1]
d.textContent = r[2];
df.appendChild(d);
}
aDlg.setBody(df);
},
showDetails: function(aTag, aLoc) {
var cells = [];
for (var key in baseController._c) {
if (key != 'waterfall') {
cells.push(baseController._c[key].controller.getContent(aLoc));
}
}
},
getContent: function(aLoc) {
if (! this._target) return;
return this._c[this._target].getContent(aLoc);
},
addPane: function(aName, aKey, aController, aView) {
if (! this._c) {
this._pending.push([aName, aKey, aController, aView]);
return;
}
view.addTab(aName, aKey);
this._c[aKey] = {controller: aController, view: aView};
},
loaded: function() {
this._c = {};
for each (var c in this._pending) {
this.addPane.apply(this, c);
}
this.select(this._pending[0][1]);
delete this._pending;
},
delay: function(context, f, args) {
window.setTimeout(function(){f.apply(context,args);}, 10);
}
};
var outlineController = {
__proto__: baseController,
getHeader: function() {
var h = document.createElement('th');
h.textContent = 'Details';
return h;
},
getContent: function(aLoc) {
var cell = view.getCell();
cell.innerHTML = 'Details for ' + aLoc;
return cell;
}
};
var outlineView = {
__proto__: baseView
};
//baseController.addPane('Outline', 'outline', outlineController, outlineView);
view = baseView;
controller = baseController;

Просмотреть файл

@ -1,200 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla.
*
* The Initial Developer of the Original Code is
* Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2006
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Axel Hecht <axel@pike.org>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
var comparisonView = {
__proto__: baseView,
setUpHandlers: function() {
_t = this;
//this.omv = function(event){_t.onMouseOver.apply(_t, [event]);};
//this.omo = function(event){_t.onMouseOut.apply(_t, [event]);};
//this.content.addEventListener("mouseover", this.omv, true);
//this.content.addEventListener("mouseout", this.omv, true);
},
destroyHandlers: function() {
//this.content.removeEventListener("mouseover", this.omv, true);
//this.content.removeEventListener("mouseout", this.omv, true);
},
// Helper methods
createFullTree: function ct(aDetails, aNode, aName) {
if (!aDetails || ! (aDetails instanceof Object))
return;
var cat = new YAHOO.widget.TextNode(aName, aNode, true);
for each (postfix in ["Files", ""]) {
var subRes = aDetails[aName + postfix];
var append = postfix ? ' (files)' : '';
for (mod in subRes) {
var mn = new YAHOO.widget.TextNode(mod + append, cat, true);
for (fl in subRes[mod]) {
if (postfix) {
new YAHOO.widget.TextNode(subRes[mod][fl], mn, false);
continue;
}
var fn = new YAHOO.widget.TextNode(fl, mn, false);
var keys = [];
for each (k in subRes[mod][fl]) {
keys.push(k);
}
keys.sort();
new YAHOO.widget.HTMLNode("<pre>" + keys.join("\n") + "</pre>", fn, true, false);
}
}
}
return cat;
}
};
var comparisonController = {
__proto__: baseController,
get path() {
return 'results/' + this.tag + '/cmp-data.json';
},
beforeSelect: function() {
this.result = {};
this.isShown = false;
comparisonView.setUpHandlers();
var _t = this;
var callback = function(obj) {
delete _t.req;
if (view != comparisonView) {
// ignore, we have switched again
return;
}
_t.result = obj;
comparisonView.updateView(keys(_t.result));
};
this.req = JSON.get('results/' + this.tag + '/cmp-data.json', callback);
},
beforeUnSelect: function() {
if (this.req) {
this.req.abort();
delete this.req;
}
comparisonView.destroyHandlers();
},
showView: function(aClosure) {
// json onload handler does this;
},
getContent: function(aLoc) {
var row = view.getCell();
var inner = document.createElement('div');
row.appendChild(inner);
var r = this.result[aLoc];
var id = "tree-" + aLoc;
inner.id = id;
var hasDetails = true;
if (r.missing.total + r.missingFiles.total) {
inner.className = "has_missing";
}
else if (r.obsolete.total + r.obsoleteFiles.total) {
inner.className = "has_obsolete";
}
else {
inner.className = "is_good";
hasDetails = false;
}
t = new YAHOO.widget.TreeView(inner);
var _l = aLoc;
var rowCollector = {
_c : '',
pushCell: function(content, class) {
this._c += '<td';
if (content == 0)
class += ' zero'
if (class)
this._c += ' class="' + class + '"';
this._c += '>' + content + '</td>';
},
get content() {return '<table class="locale-row"><tr>' +
this._c + '</tr></table>';}
};
for each (app in kModules) {
var class;
if (r.tested.indexOf(app) < 0) {
class = 'void';
}
else if (r.missing[app] + r.missingFiles[app]) {
class = 'missing';
}
else if (r.obsolete[app] + r.obsoleteFiles[app]) {
class = 'obsolete';
}
else {
class = "good";
}
rowCollector.pushCell(app, 'app-res ' + class);
}
rowCollector.pushCell(r.missingFiles.total, "missing count");
rowCollector.pushCell(r.missing.total, "missing count");
rowCollector.pushCell(r.obsoleteFiles.total, "obsolete count");
rowCollector.pushCell(r.obsolete.total, "obsolete count");
rowCollector.pushCell(r.unchanged +r.changed, "good count");
var tld = new YAHOO.widget.HTMLNode(rowCollector.content, t.getRoot(), false, hasDetails);
if (hasDetails) {
tld.__cl_locale = aLoc;
tld.__do_load = true;
tmp = new YAHOO.widget.HTMLNode("<span class='ygtvloading'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>&nbsp;loading&hellip;", tld, true, true);
var l = aLoc;
var _c = this;
var expander = function(node) {
if (!node.__do_load)
return true;
var callback = function(aRes) {
comparisonView.createFullTree(aRes, node, 'missing');
comparisonView.createFullTree(aRes, node, 'obsolete');
delete node.__do_load;
node.tree.removeNode(node.children[0]);
node.refresh();
};
JSON.get('results/' + _c.tag + '/cmp-details-'+aLoc+'.json', callback);
}
t.onExpand = expander;
delete expander;
}
t.draw();
var rowToggle = function(){
YAHOO.util.Event.addListener(tld.getContentEl(), "click",
function(){tld.toggle();}, tld, true);
};
YAHOO.util.Event.onAvailable(tld.contentElId, rowToggle, tld);
//YAHOO.util.Event.addListener(tld.getContentEl(), "click", rowToggle, tld, true);
return row;
}
};
controller.addPane('Compare', 'comparison', comparisonController,
comparisonView);
//controller.addLocales(keys(results.locales));

Просмотреть файл

@ -1,94 +0,0 @@
<!-- ***** BEGIN LICENSE BLOCK *****
- Version: MPL 1.1/GPL 2.0/LGPL 2.1
-
- The contents of this file are subject to the Mozilla Public License Version
- 1.1 (the "License"); you may not use this file except in compliance with
- the License. You may obtain a copy of the License at
- http://www.mozilla.org/MPL/
-
- Software distributed under the License is distributed on an "AS IS" basis,
- WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
- for the specific language governing rights and limitations under the
- License.
-
- The Original Code is Mozilla.
-
- The Initial Developer of the Original Code is
- Mozilla Foundation.
- Portions created by the Initial Developer are Copyright (C) 2006
- the Initial Developer. All Rights Reserved.
-
- Contributor(s):
- Axel Hecht <axel@pike.org>
-
- Alternatively, the contents of this file may be used under the terms of
- either the GNU General Public License Version 2 or later (the "GPL"), or
- the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
- in which case the provisions of the GPL or the LGPL are applicable instead
- of those above. If you wish to allow use of your version of this file only
- under the terms of either the GPL or the LGPL, and not to allow others to
- use your version of this file under the terms of the MPL, indicate your
- decision by deleting the provisions above and replace them with the notice
- and other provisions required by the LGPL or the GPL. If you do not delete
- the provisions above, a recipient may use your version of this file under
- the terms of any one of the MPL, the GPL or the LGPL.
-
- ***** END LICENSE BLOCK ***** -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<title>1.8.1 Locales status</title>
<style type="text/css" id="style-Tier-1">
.Tier-1 {display: none}
</style>
<style type="text/css" id="style-Tier-2">
.Tier-2 {display: none}
</style>
<style type="text/css" id="style-Tier-3">
.Tier-3 {display: none}
</style>
<style type="text/css">
div {min-height: 5px;}
</style>
<link rel="stylesheet" type="text/css" href="yui/examples/treeview/css/local/tree.css">
<link rel="stylesheet" type="text/css" href="yui/build/container/assets/container.css">
<link rel="stylesheet" type="text/css" href="layout.css">
<script type="text/javascript" src="yui/build/yahoo/yahoo.js"></script>
<script type="text/javascript" src="yui/build/dom/dom.js"></script>
<script type="text/javascript" src="yui/build/event/event.js"></script>
<script type="text/javascript" src="yui/build/logger/logger.js"></script>
<script type="text/javascript" src="yui/build/treeview/treeview.js"></script>
<script type="text/javascript" src="yui/build/calendar/calendar.js"></script>
<script type="text/javascript" src="yui/build/dragdrop/dragdrop.js"></script>
<script type="text/javascript" src="yui/build/container/container.js"></script>
<script type="text/javascript" src="code-base.js"></script>
<script type="text/javascript" src="waterfall-code.js"></script>
<script type="text/javascript" src="comparison-code.js"></script>
<script type="text/javascript" src="search-code.js"></script>
<script type="text/javascript" src="bookmarks-code.js"></script>
<script type="text/javascript" src="rss-reader-code.js"></script>
</head>
<body onload="">
<div id="sidebar">
<p id="checks">Showing Tier 1
<input type="checkbox" name="Tier-1" checked>&nbsp;
2 <input type="checkbox" name="Tier-2" checked>&nbsp;
3 <input type="checkbox" name="Tier-3" checked> for
</p>
<input type="text" id="tag-view" size="30">
</div>
<h1>Locale Tests</h1>
<div id="menu">
<ul id="tabs"></ul>
</div>
<table id="main" cellspacing="0" border="1px" cellpadding="2px">
<thead>
<tr id="head"></tr>
</thead>
<tbody id="content"></tbody>
</table>
<script type="text/javascript" src="post.js"></script>
</body>
</html>

Просмотреть файл

@ -1,133 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla.
*
* The Initial Developer of the Original Code is
* Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2006
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Axel Hecht <axel@pike.org>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#sidebar {
float: right;
margin-top: -8px;
}
#menu li[selected] {
background-color: lightgrey;
border-style: inset inset none inset;
}
#menu li {
display: block;
float: left;
font-weight: bold;
padding: .5em;
margin-left:1px;
margin-right:1px;
border-style: outset outset none outset;
-moz-border-radius-topleft: 15px;
-moz-border-radius-topright: 15px;
}
#main {
clear: left;
}
body {
overflow: scroll;
}
#content {
vertical-align: top;
}
div.is_good {
padding-left: 16px;
}
.missing, .busted {
background-color: red;
}
.obsolete, .fair {
background-color: orange;
}
.zero {
opacity: .3;
background-color: green !important;
}
.good {
background-color: limegreen;
}
.void {
color: grey;
background-color: lightgrey;
}
td.locale {
width: 4em;
}
td.app-res {
width: 4em;
}
td.count {
padding-left:3px;
padding-right: 3px;
width: 3.5em;
text-align: right;
}
div.calbordered {
float: none;
}
/* waterfall view */
#log-dlg {
overflow: scroll;
}
.log-row {
margin: 0pt;
}
.ERROR {
background-color: coral;
}
/* search view */
td.ordered {border: 2px solid black;}
td.error {background-color: coral;}
td.conflict {background-color: grey;}
td.enUS {opacity: .5;}
/* feedreader view */
.feedreader { border: thin solid lightgrey }

Просмотреть файл

@ -1,40 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla.
*
* The Initial Developer of the Original Code is
* Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2006
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Axel Hecht <axel@pike.org>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
view.init();
controller.addLocales(keys(tierMap));
controller.loaded();

Просмотреть файл

@ -1,93 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla.
*
* The Initial Developer of the Original Code is
* Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2006
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Axel Hecht <axel@pike.org>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
var rssController = {
__proto__: baseController,
get path() {
return 'results/' + this.tag + '/feed-reader-results.json';
},
beforeSelect: function() {
this.hashes = {};
rssView.setUpHandlers();
var _t = this;
var callback = function(obj) {
delete _t.req;
if (view != rssView) {
// ignore, we have switched again
return;
}
_t.result = obj;
rssView.updateView(keys(_t.result));
};
this.req = JSON.get('results/' + this.tag + '/feed-reader-results.json',
callback);
},
beforeUnSelect: function() {
rssView.destroyHandlers();
},
showView: function(aClosure) {
// json onload handler does this;
},
getContent: function(aLoc) {
var row = document.createDocumentFragment();
var lst = this.result[aLoc];
var _t = this;
for each (var pair in lst) {
//YAHOO.widget.Logger.log('testing ' + path);
var td = document.createElement('td');
td.className = 'feedreader';
td.innerHTML = pair[0];
td.title = pair[1];
row.appendChild(td);
}
return row;
}
};
var rssView = {
__proto__: baseView,
setUpHandlers: function() {
_t = this;
},
destroyHandlers: function() {
if (this._dv) {
this._dv.hide();
}
}
};
controller.addPane('RSS', 'rss', rssController, rssView);
//controller.addLocales(keys(results.locales));

Просмотреть файл

@ -1,241 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla.
*
* The Initial Developer of the Original Code is
* Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2006
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Axel Hecht <axel@pike.org>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
var searchController = {
__proto__: baseController,
get path() {
return 'results/' + this.tag + '/search-results.json';
},
beforeSelect: function() {
this.hashes = {};
searchView.setUpHandlers();
var _t = this;
var callback = function(obj) {
delete _t.req;
if (view != searchView) {
// ignore, we have switched again
return;
}
_t.result = obj;
searchView.updateView(keys(_t.result.locales));
};
this.req = JSON.get('results/' + this.tag + '/search-results.json',
callback);
},
beforeUnSelect: function() {
this.hashes = {};
searchView.destroyHandlers();
},
showView: function(aClosure) {
// json onload handler does this;
},
getContent: function(aLoc) {
var row = document.createDocumentFragment();
var lst = this.result.locales[aLoc].list;
var _t = this;
lst.sort(function(a,b){return _t.cmp.apply(_t,[a,b])});
var orders = this.result.locales[aLoc].orders;
if (orders) {
var explicit = [];
var implicit = [];
for (var sn in orders) {
if (explicit[sn]) {
fatal = true;
break;
}
explicit[sn] = orders[sn];
}
explicit = [];
for each (var path in lst) {
var shortName = this.result.details[path].ShortName;
if (orders[shortName]) {
explicit[orders[shortName] - 1] = path;
}
else {
implicit.push(path);
}
}
lst = explicit.concat(implicit);
}
row.innerHTML = '<td class="locale"><a href="https://bugzilla.mozilla.org/buglist.cgi?query_format=advanced&amp;short_desc_type=regexp&amp;short_desc=' + aLoc + '%5B%20-%5D&amp;chfieldto=Now&amp;field0-0-0=blocked&amp;type0-0-0=substring&amp;value0-0-0=347914">bug</a></td>';
for each (var path in lst) {
//YAHOO.widget.Logger.log('testing ' + path);
var innerContent;
var cl = '';
if (path.match(/^mozilla/)) {
cl += ' enUS';
}
var localName = path.substr(path.lastIndexOf('/') + 1);
if (this.result.details[path].error) {
innerContent = 'error in ' + localName;
cl += ' error';
}
else {
var shortName = this.result.details[path].ShortName;
var img = this.result.details[path].Image;
if (this.result.locales[aLoc].orders && this.result.locales[aLoc].orders[shortName]) {
cl += " ordered";
}
innerContent = '<img src="' + img + '">' + shortName;
}
var td = document.createElement('td');
td.className = 'searchplugin' + cl;
td.innerHTML = innerContent;
row.appendChild(td);
td.details = this.result.details[path];
// test the hash code
if (td.details.error) {
// ignore errorenous plugins
continue;
}
if (this.hashes[localName]) {
this.hashes[localName].nodes.push(td);
if (this.hashes[localName].conflict) {
td.className += ' conflict';
}
else if (this.hashes[localName].key != td.details.md5) {
this.hashes[localName].conflict = true;
for each (td in this.hashes[localName].nodes) {
td.className += ' conflict';
}
}
}
else {
this.hashes[localName] = {key: td.details.md5, nodes: [td]};
}
}
for (localName in this.hashes) {
if ( ! ('conflict' in this.hashes[localName])) {
continue;
}
locs = [];
for each (var td in this.hashes[localName].nodes) {
locs.push(td.parentNode.firstChild.textContent);
}
YAHOO.widget.Logger.log('difference in ' + localName + ' for ' + locs.join(', '));
}
return row;
},
cmp: function(l,r) {
var lName = this.result.details[l].ShortName;
var rName = this.result.details[r].ShortName;
if (lName) lName = lName.toLowerCase();
if (rName) rName = rName.toLowerCase();
return lName < rName ? -1 : lName > rName ? 1 : 0;
}
};
var searchView = {
__proto__: baseView,
setUpHandlers: function() {
_t = this;
this.omv = function(event){_t.onMouseOver.apply(_t, [event]);};
this.omo = function(event){_t.onMouseOut.apply(_t, [event]);};
this.content.addEventListener("mouseover", this.omv, true);
this.content.addEventListener("mouseout", this.omv, true);
},
destroyHandlers: function() {
this.content.removeEventListener("mouseover", this.omv, true);
this.content.removeEventListener("mouseout", this.omv, true);
if (this._dv) {
this._dv.hide();
}
},
onMouseOver: function(event) {
if (!event.target.details)
return;
var _e = {
details: event.target.details,
clientX: event.clientX,
clientY: event.clientY
};
this.pending = setTimeout(function(){searchView.showDetail(_e);}, 500);
},
onMouseOut: function(event) {
if (this.pending) {
clearTimeout(this.pending);
delete this.pending;
return;
}
if (!event.target.details)
return;
},
showDetail: function(event) {
delete this.pending;
if (!this._dv) {
this._dv = new YAHOO.widget.Panel('dv', {visible:true,draggable:true,constraintoviewport:true});
this._dv.beforeHideEvent.subscribe(function(){delete this._dv;}, null);
}
var dt = event.details;
if (dt.error) {
this._dv.setHeader("Error");
this._dv.setBody(dt.error);
}
else {
this._dv.setHeader("Details");
var c = '';
var q = 'test';
var len = 0;
for each (var url in dt.urls) {
var uc = url.template;
var sep = (uc.indexOf('?') > -1) ? '&amp;' : '?';
for (var p in url.params) {
uc += sep + p + '=' + url.params[p];
sep = '&amp;';
}
uc = uc.replace('{searchTerms}', q);
var mpContent = '';
if (url.MozParams) {
for each (var mp in url.MozParams) {
// add at least the yahoo prefs
if (mp.condition == 'pref') {
mpContent += ', using pref ' + mp.name + '=' + mp.pref;
}
}
}
c += '<button onclick="window.open(this.textContent)">' + uc + '</button>' +mpContent+ '<br>';
len = len < c.length ? c.length : len;
}
this._dv.setBody(c);
}
this._dv.render(document.body);
this._dv.moveTo(event.clientX + window.scrollX, event.clientY + window.scrollY);
this._dv.show();
}
};
controller.addPane('Search', 'search', searchController, searchView);
//controller.addLocales(keys(results.locales));

Просмотреть файл

@ -1,191 +0,0 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla.
*
* The Initial Developer of the Original Code is
* Mozilla Foundation.
* Portions created by the Initial Developer are Copyright (C) 2006
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* Axel Hecht <axel@pike.org>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
var waterfallView = {
__proto__: baseView,
scale: 1/60,
unstyle: function() {
this.content.innerHTML = '';
},
updateView: function(aResult) {
YAHOO.widget.Logger.log('waterfallView.updateView called');
var head = document.getElementById('head');
head.innerHTML = '<th></th>';
this.content.innerHTML = '';
for each (var loc in controller.locales) {
var h = document.createElement('th');
h.className = 'wf-locale-head ' + view.getClass(loc);
h.textContent = loc;
head.appendChild(h);
}
var heads = head.childNodes;
var lastDate = -1;
function pad(aNumber, length) {
str = String(aNumber);
while (str.length < length) {
str = '0' + str;
}
return str;
};
for (var i = aResult.length - 1; i >= 0; i--) {
var wf = document.createElement('tr');
wf.className = 'waterfall-row';
wf.setAttribute('style','vertical-align: top;');
this.content.appendChild(wf);
var b = aResult[i];
var height = Math.floor((b[1][1] - b[1][0]) * this.scale);
var style = "height: " + height + "px;";
wf.setAttribute('style', style);
var cell = view.getCell();
cell.className = 'cell-label';
var d = this.getUTCDate(b[0]);
var label = pad(d.getUTCHours(), 2) + ':' +
pad(d.getUTCMinutes(), 2);
if (lastDate != d.getUTCDate()) {
lastDate = d.getUTCDate();
label = d.getUTCDate() +'/'+ (d.getUTCMonth()+1) + '<br>' + label;
}
cell.innerHTML = label +
'<br><a href="javascript:controller.showLog(\'' + b[0] + '\');">L</a>';
wf.appendChild(cell);
var locs = keys(b[2]);
var h = 1;
for each (loc in locs) {
if (h >= heads.length) {
YAHOO.widget.Logger.log("dropping result for " + loc);
continue;
}
while (heads[h].textContent < loc) {
// we don't have a result for this column in this build
cell = view.getCell();
cell.className = view.getClass(heads[h].textContent)
wf.appendChild(cell);
h++;
if (h >= heads.length) {
YAHOO.widget.Logger.log("dropping result for " + loc);
continue;
}
}
if (heads[h].textContent > loc) {
YAHOO.widget.Logger.log("dropping result for " + loc);
continue;
}
cell = view.getCell();
cell.innerHTML = '<a href="javascript:controller.showLog(\'' +
b[0] + '\',\'' + loc + '\');">L</a> <a href="javascript:controller.showDetails(\'' +
b[0] + '\',\'' + loc + '\');">B</a>';
if (b[2][loc] & 2) {
cell.className = 'busted ';
}
else if (b[2][loc] & 1) {
cell.className = 'fair ';
}
else {
cell.className = 'good ';
}
cell.className += ' ' + view.getClass(loc);
wf.appendChild(cell);
h++;
}
if (i == 0) {
continue;
}
// XXX don't make output sparse
continue;
wf = document.createElement('tr');
wf.className = 'waterfall-row';
wf.setAttribute('style','vertical-align: top;');
this.content.appendChild(wf);
var b = aResult[i];
var height = Math.floor((b[1][0] - aResult[i-1][1][1]) * this.scale);
var style = "height: " + height + "px;";
wf.setAttribute('style', style);
//var cell = view.getCell();
}
},
setUpHandlers: function() {
_t = this;
},
destroyHandlers: function() {
},
// Helper functions
getUTCDate: function(aTag) {
var D = new Date();
var d = aTag.split(/[ -]/).map(function(aEl){return Number(aEl);});
d[1] -= 1; // adjust month
D.setTime(Date.UTC.apply(null,d));
return D;
}
};
var waterfallController = {
__proto__: baseController,
get path() {
return 'results/waterfall.json';
},
beforeSelect: function() {
this.result = {};
this.isShown = false;
waterfallView.setUpHandlers();
var _t = this;
var callback = function(obj) {
delete _t.req;
if (view != waterfallView) {
// ignore, we have switched again
return;
}
_t.result = obj;
_t.tag = obj[obj.length - 1][0]; // set the subdir to latest build
controller.addLocales(keys(obj[obj.length - 1][2]));
waterfallView.updateView(_t.result);
};
this.req = JSON.get('results/waterfall.json', callback);
},
beforeUnSelect: function() {
if (this.req) {
this.req.abort();
delete this.req;
}
waterfallView.unstyle();
waterfallView.destroyHandlers();
},
showView: function(aClosure) {
// json onload handler does this;
}
};
controller.addPane('Tinder', 'waterfall', waterfallController,
waterfallView);