зеркало из https://github.com/mozilla/pjs.git
bug 589313, remove obsolete l10n tests, those are hosted elsewhere, details in the bug. r/a=sayrer, NPOTB
This commit is contained in:
Родитель
8896fadf25
Коммит
cff57d723a
|
@ -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 <l10n@mozilla.com></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 <l10n@mozilla.com></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'] + '"> <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 …');
|
||||
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'> </span> loading…", 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>
|
||||
2 <input type="checkbox" name="Tier-2" checked>
|
||||
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&short_desc_type=regexp&short_desc=' + aLoc + '%5B%20-%5D&chfieldto=Now&field0-0-0=blocked&type0-0-0=substring&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) ? '&' : '?';
|
||||
for (var p in url.params) {
|
||||
uc += sep + p + '=' + url.params[p];
|
||||
sep = '&';
|
||||
}
|
||||
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);
|
Загрузка…
Ссылка в новой задаче