Pamac 2.0
- complete rewrite in vala - it now directly depends on libalpm so it is easier to maintain - it is faster and uses less memory - alpm bindings for vala, other people could be interested - a DBus daemon which can perform every tasks which need root access using polkit to check authorization, it can be used by any other program. - pamac-manager and pamac-updater as you know before but with some new design, try them ! - the progress dialog now includes a terminal, it permits to launch yaourt which is used now to build packages from AUR. - reinstall a package - install optional dependencies of a package - mark a package as explicitly installed
This commit is contained in:
95
src/Makefile
Normal file
95
src/Makefile
Normal file
@@ -0,0 +1,95 @@
|
||||
|
||||
COMMON_VALA_FLAGS = --pkg=libalpm \
|
||||
--pkg=gio-2.0 \
|
||||
--pkg=posix \
|
||||
--pkg=json-glib-1.0 \
|
||||
--pkg=libsoup-2.4 \
|
||||
--vapidir=../vapi \
|
||||
--Xcc=-I../util \
|
||||
-X -D_FILE_OFFSET_BITS=64 \
|
||||
-X -DGETTEXT_PACKAGE="pamac" \
|
||||
--target-glib=2.38
|
||||
|
||||
COMMON_SOURCES = ../util/alpm-util.c \
|
||||
alpm_config.vala \
|
||||
pamac_config.vala \
|
||||
aur.vala \
|
||||
common.vala
|
||||
|
||||
MANAGER_GRESOURCE_FILE = ../resources/pamac.manager.gresource.xml
|
||||
|
||||
UPDATER_GRESOURCE_FILE = ../resources/pamac.updater.gresource.xml
|
||||
|
||||
INSTALLER_GRESOURCE_FILE = ../resources/pamac.installer.gresource.xml
|
||||
|
||||
DIALOGS_FILES = choose_provider_dialog.vala \
|
||||
transaction_sum_dialog.vala \
|
||||
transaction_info_dialog.vala \
|
||||
progress_dialog.vala
|
||||
|
||||
pamac-daemon: ../vapi/libalpm.vapi ../vapi/polkit-gobject-1.vapi $(COMMON_SOURCES) daemon.vala
|
||||
valac -o pamac-daemon \
|
||||
$(COMMON_VALA_FLAGS) \
|
||||
--pkg=polkit-gobject-1 \
|
||||
--thread \
|
||||
$(COMMON_SOURCES) \
|
||||
daemon.vala
|
||||
|
||||
pamac-tray: ../vapi/libalpm.vapi $(COMMON_SOURCES) tray.vala
|
||||
valac -o pamac-tray \
|
||||
$(COMMON_VALA_FLAGS) \
|
||||
--pkg=gtk+-3.0 \
|
||||
--pkg=libnotify \
|
||||
$(COMMON_SOURCES) \
|
||||
tray.vala
|
||||
|
||||
pamac-manager: ../vapi/libalpm.vapi $(COMMON_SOURCES) $(DIALOGS_FILES) choose_dep_dialog.vala preferences_dialog.vala history_dialog.vala packages_chooser_dialog.vala ../resources/manager_resources.c package.vala transaction.vala packages_model.vala manager_window.vala manager.vala
|
||||
valac -o pamac-manager \
|
||||
$(COMMON_VALA_FLAGS) \
|
||||
--pkg=gtk+-3.0 \
|
||||
--pkg=gmodule-2.0 \
|
||||
--pkg=gdk-3.0 \
|
||||
--pkg=vte-2.91 \
|
||||
--gresources=$(MANAGER_GRESOURCE_FILE) \
|
||||
$(COMMON_SOURCES) \
|
||||
$(DIALOGS_FILES) \
|
||||
choose_dep_dialog.vala \
|
||||
preferences_dialog.vala \
|
||||
history_dialog.vala \
|
||||
packages_chooser_dialog.vala \
|
||||
../resources/manager_resources.c \
|
||||
package.vala \
|
||||
transaction.vala \
|
||||
packages_model.vala \
|
||||
manager_window.vala \
|
||||
manager.vala
|
||||
|
||||
pamac-updater: ../vapi/libalpm.vapi $(COMMON_SOURCES) $(DIALOGS_FILES) preferences_dialog.vala ../resources/updater_resources.c transaction.vala updater_window.vala updater.vala
|
||||
valac -o pamac-updater \
|
||||
$(COMMON_VALA_FLAGS) \
|
||||
--pkg=gtk+-3.0 \
|
||||
--pkg=gmodule-2.0 \
|
||||
--pkg=vte-2.91 \
|
||||
--gresources=$(UPDATER_GRESOURCE_FILE) \
|
||||
$(COMMON_SOURCES) \
|
||||
$(DIALOGS_FILES) \
|
||||
preferences_dialog.vala \
|
||||
../resources/updater_resources.c \
|
||||
transaction.vala \
|
||||
updater_window.vala \
|
||||
updater.vala
|
||||
|
||||
pamac-install: ../vapi/libalpm.vapi $(COMMON_SOURCES) $(DIALOGS_FILES) ../resources/installer_resources.c transaction.vala installer.vala
|
||||
valac -o pamac-install \
|
||||
$(COMMON_VALA_FLAGS) \
|
||||
--pkg=gtk+-3.0 \
|
||||
--pkg=gmodule-2.0 \
|
||||
--pkg=vte-2.91 \
|
||||
--gresources=$(INSTALLER_GRESOURCE_FILE) \
|
||||
$(COMMON_SOURCES) \
|
||||
$(DIALOGS_FILES) \
|
||||
../resources/installer_resources.c \
|
||||
transaction.vala \
|
||||
installer.vala
|
||||
|
||||
binaries: pamac-daemon pamac-tray pamac-updater pamac-manager pamac-install
|
322
src/alpm_config.vala
Normal file
322
src/alpm_config.vala
Normal file
@@ -0,0 +1,322 @@
|
||||
/*
|
||||
* pamac-vala
|
||||
*
|
||||
* Copyright (C) 2014 Guillaume Benoit <guillaume@manjaro.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a get of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace Alpm {
|
||||
class Repo {
|
||||
public string name;
|
||||
public SigLevel siglevel;
|
||||
public string[] urls;
|
||||
|
||||
public Repo (string name) {
|
||||
this.name = name;
|
||||
urls = {};
|
||||
}
|
||||
}
|
||||
|
||||
public class Config {
|
||||
string rootdir;
|
||||
string dbpath;
|
||||
string gpgdir;
|
||||
string logfile;
|
||||
string arch;
|
||||
double deltaratio;
|
||||
int usesyslog;
|
||||
int checkspace;
|
||||
string[] cachedir;
|
||||
string[] ignoregroup;
|
||||
string[] ignorepkg;
|
||||
string[] noextract;
|
||||
string[] noupgrade;
|
||||
string[] holdpkg;
|
||||
string[] syncfirst;
|
||||
SigLevel defaultsiglevel;
|
||||
SigLevel localfilesiglevel;
|
||||
SigLevel remotefilesiglevel;
|
||||
Repo[] repo_order;
|
||||
|
||||
public Config (string path) {
|
||||
rootdir = "/";
|
||||
dbpath = "/var/lib/pacman";
|
||||
gpgdir = "/etc/pacman.d/gnupg/";
|
||||
logfile = "/var/log/pacman.log";
|
||||
arch = Posix.utsname().machine;
|
||||
cachedir = {"/var/cache/pacman/pkg/"};
|
||||
holdpkg = {};
|
||||
syncfirst = {};
|
||||
ignoregroup = {};
|
||||
ignorepkg = {};
|
||||
noextract = {};
|
||||
noupgrade = {};
|
||||
usesyslog = 0;
|
||||
checkspace = 0;
|
||||
deltaratio = 0.7;
|
||||
defaultsiglevel = SigLevel.PACKAGE | SigLevel.PACKAGE_OPTIONAL | SigLevel.DATABASE | SigLevel.DATABASE_OPTIONAL;
|
||||
localfilesiglevel = SigLevel.USE_DEFAULT;
|
||||
remotefilesiglevel = SigLevel.USE_DEFAULT;
|
||||
repo_order = {};
|
||||
// parse conf file
|
||||
parse_file (path);
|
||||
}
|
||||
|
||||
public string[] get_syncfirst () {
|
||||
return syncfirst;
|
||||
}
|
||||
|
||||
public string[] get_holdpkg () {
|
||||
return holdpkg;
|
||||
}
|
||||
|
||||
public string[] get_ignore_pkgs () {
|
||||
string[] ignore_pkgs = {};
|
||||
unowned Group? group = null;
|
||||
Handle? handle = this.get_handle ();
|
||||
if (handle != null) {
|
||||
foreach (string name in ignorepkg)
|
||||
ignore_pkgs += name;
|
||||
foreach (string grp_name in ignoregroup) {
|
||||
group = handle.localdb.get_group (grp_name);
|
||||
if (group != null) {
|
||||
foreach (unowned Package found_pkg in group.packages)
|
||||
ignore_pkgs += found_pkg.name;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ignore_pkgs;
|
||||
}
|
||||
|
||||
public Handle? get_handle () {
|
||||
Alpm.Errno error;
|
||||
Handle? handle = new Handle (rootdir, dbpath, out error);
|
||||
if (handle == null) {
|
||||
stderr.printf ("Failed to initialize alpm library" + " (%s)\n".printf(Alpm.strerror (error)));
|
||||
return handle;
|
||||
}
|
||||
// define options
|
||||
handle.gpgdir = gpgdir;
|
||||
handle.logfile = logfile;
|
||||
handle.arch = arch;
|
||||
handle.deltaratio = deltaratio;
|
||||
handle.usesyslog = usesyslog;
|
||||
handle.checkspace = checkspace;
|
||||
handle.defaultsiglevel = defaultsiglevel;
|
||||
handle.localfilesiglevel = localfilesiglevel;
|
||||
handle.remotefilesiglevel = remotefilesiglevel;
|
||||
foreach (string dir in cachedir)
|
||||
handle.add_cachedir (dir);
|
||||
foreach (string name in ignoregroup)
|
||||
handle.add_ignoregroup (name);
|
||||
foreach (string name in ignorepkg)
|
||||
handle.add_ignorepkg (name);
|
||||
foreach (string name in noextract)
|
||||
handle.add_noextract (name);
|
||||
foreach (string name in noupgrade)
|
||||
handle.add_noupgrade (name);
|
||||
// register dbs
|
||||
foreach (Repo repo in repo_order) {
|
||||
unowned DB db = handle.register_syncdb (repo.name, repo.siglevel);
|
||||
foreach (string url in repo.urls) {
|
||||
db.add_server (url.replace ("$repo", repo.name).replace ("$arch", handle.arch));
|
||||
}
|
||||
}
|
||||
return handle;
|
||||
}
|
||||
|
||||
public void parse_file (string path, string? section = null) {
|
||||
string current_section = section;
|
||||
var file = GLib.File.new_for_path (path);
|
||||
if (file.query_exists () == false)
|
||||
GLib.stderr.printf ("File '%s' doesn't exist.\n", file.get_path ());
|
||||
else {
|
||||
try {
|
||||
// Open file for reading and wrap returned FileInputStream into a
|
||||
// DataInputStream, so we can read line by line
|
||||
var dis = new DataInputStream (file.read ());
|
||||
string line;
|
||||
// Read lines until end of file (null) is reached
|
||||
while ((line = dis.read_line (null)) != null) {
|
||||
line = line.strip ();
|
||||
if (line.length == 0) continue;
|
||||
if (line[0] == '#') continue;
|
||||
if (line[0] == '[' && line[line.length-1] == ']') {
|
||||
current_section = line[1:-1];
|
||||
if (current_section != "options") {
|
||||
Repo repo = new Repo (current_section);
|
||||
repo.siglevel = defaultsiglevel;
|
||||
repo_order += repo;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
string[] splitted = line.split ("=");
|
||||
string _key = splitted[0].strip ();
|
||||
string _value = null;
|
||||
if (splitted[1] != null)
|
||||
_value = splitted[1].strip ();
|
||||
if (_key == "Include")
|
||||
parse_file (_value, current_section);
|
||||
if (current_section == "options") {
|
||||
if (_key == "GPGDir")
|
||||
gpgdir = _value;
|
||||
else if (_key == "LogFile")
|
||||
logfile = _value;
|
||||
else if (_key == "Architecture") {
|
||||
if (_value == "auto")
|
||||
arch = Posix.utsname ().machine;
|
||||
else
|
||||
arch = _value;
|
||||
} else if (_key == "UseDelta")
|
||||
deltaratio = double.parse (_value);
|
||||
else if (_key == "UseSysLog")
|
||||
usesyslog = 1;
|
||||
else if (_key == "CheckSpace")
|
||||
checkspace = 1;
|
||||
else if (_key == "SigLevel")
|
||||
defaultsiglevel = define_siglevel (defaultsiglevel, _value);
|
||||
else if (_key == "LocalSigLevel")
|
||||
localfilesiglevel = merge_siglevel (defaultsiglevel, define_siglevel (localfilesiglevel, _value));
|
||||
else if (_key == "RemoteSigLevel")
|
||||
remotefilesiglevel = merge_siglevel (defaultsiglevel, define_siglevel (remotefilesiglevel, _value));
|
||||
else if (_key == "HoldPkg") {
|
||||
foreach (string name in _value.split (" ")) {
|
||||
holdpkg += name;
|
||||
}
|
||||
} else if (_key == "SyncFirst") {
|
||||
foreach (string name in _value.split (" ")) {
|
||||
syncfirst += name;
|
||||
}
|
||||
} else if (_key == "CacheDir") {
|
||||
foreach (string dir in _value.split (" ")) {
|
||||
cachedir += dir;
|
||||
}
|
||||
} else if (_key == "IgnoreGroup") {
|
||||
foreach (string name in _value.split (" ")) {
|
||||
ignoregroup += name;
|
||||
}
|
||||
} else if (_key == "IgnorePkg") {
|
||||
foreach (string name in _value.split (" ")) {
|
||||
ignorepkg += name;
|
||||
}
|
||||
} else if (_key == "Noextract") {
|
||||
foreach (string name in _value.split (" ")) {
|
||||
noextract += name;
|
||||
}
|
||||
} else if (_key == "NoUpgrade") {
|
||||
foreach (string name in _value.split (" ")) {
|
||||
noupgrade += name;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
foreach (Repo _repo in repo_order) {
|
||||
if (_repo.name == current_section) {
|
||||
if (_key == "Server")
|
||||
_repo.urls += _value;
|
||||
else if (_key == "SigLevel")
|
||||
_repo.siglevel = define_siglevel (defaultsiglevel, _value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (GLib.Error e) {
|
||||
GLib.stderr.printf("%s\n", e.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public SigLevel define_siglevel (SigLevel default_level, string conf_string) {
|
||||
foreach (string directive in conf_string.split(" ")) {
|
||||
bool affect_package = false;
|
||||
bool affect_database = false;
|
||||
if ("Package" in directive) affect_package = true;
|
||||
else if ("Database" in directive) affect_database = true;
|
||||
else {
|
||||
affect_package = true;
|
||||
affect_database = true;
|
||||
}
|
||||
if ("Never" in directive) {
|
||||
if (affect_package) {
|
||||
default_level &= ~SigLevel.PACKAGE;
|
||||
default_level |= SigLevel.PACKAGE_SET;
|
||||
}
|
||||
if (affect_database) default_level &= ~SigLevel.DATABASE;
|
||||
}
|
||||
else if ("Optional" in directive) {
|
||||
if (affect_package) {
|
||||
default_level |= SigLevel.PACKAGE;
|
||||
default_level |= SigLevel.PACKAGE_OPTIONAL;
|
||||
default_level |= SigLevel.PACKAGE_SET;
|
||||
}
|
||||
if (affect_database) {
|
||||
default_level |= SigLevel.DATABASE;
|
||||
default_level |= SigLevel.DATABASE_OPTIONAL;
|
||||
}
|
||||
}
|
||||
else if ("Required" in directive) {
|
||||
if (affect_package) {
|
||||
default_level |= SigLevel.PACKAGE;
|
||||
default_level &= ~SigLevel.PACKAGE_OPTIONAL;
|
||||
default_level |= SigLevel.PACKAGE_SET;
|
||||
}
|
||||
if (affect_database) {
|
||||
default_level |= SigLevel.DATABASE;
|
||||
default_level &= ~SigLevel.DATABASE_OPTIONAL;
|
||||
}
|
||||
}
|
||||
else if ("TrustedOnly" in directive) {
|
||||
if (affect_package) {
|
||||
default_level &= ~SigLevel.PACKAGE_MARGINAL_OK;
|
||||
default_level &= ~SigLevel.PACKAGE_UNKNOWN_OK;
|
||||
default_level |= SigLevel.PACKAGE_TRUST_SET;
|
||||
}
|
||||
if (affect_database) {
|
||||
default_level &= ~SigLevel.DATABASE_MARGINAL_OK;
|
||||
default_level &= ~SigLevel.DATABASE_UNKNOWN_OK;
|
||||
}
|
||||
}
|
||||
else if ("TrustAll" in directive) {
|
||||
if (affect_package) {
|
||||
default_level |= SigLevel.PACKAGE_MARGINAL_OK;
|
||||
default_level |= SigLevel.PACKAGE_UNKNOWN_OK;
|
||||
default_level |= SigLevel.PACKAGE_TRUST_SET;
|
||||
}
|
||||
if (affect_database) {
|
||||
default_level |= SigLevel.DATABASE_MARGINAL_OK;
|
||||
default_level |= SigLevel.DATABASE_UNKNOWN_OK;
|
||||
}
|
||||
}
|
||||
else GLib.stderr.printf("unrecognized siglevel: %s\n", conf_string);
|
||||
}
|
||||
default_level &= ~SigLevel.USE_DEFAULT;
|
||||
return default_level;
|
||||
}
|
||||
|
||||
public SigLevel merge_siglevel (SigLevel base_level, SigLevel over_level) {
|
||||
if ((over_level & SigLevel.USE_DEFAULT) != 0) over_level = base_level;
|
||||
else {
|
||||
if ((over_level & SigLevel.PACKAGE_SET) == 0) {
|
||||
over_level |= base_level & SigLevel.PACKAGE;
|
||||
over_level |= base_level & SigLevel.PACKAGE_OPTIONAL;
|
||||
}
|
||||
if ((over_level & SigLevel.PACKAGE_TRUST_SET) == 0) {
|
||||
over_level |= base_level & SigLevel.PACKAGE_MARGINAL_OK;
|
||||
over_level |= base_level & SigLevel.PACKAGE_UNKNOWN_OK;
|
||||
}
|
||||
}
|
||||
return over_level;
|
||||
}
|
||||
}
|
||||
}
|
120
src/aur.vala
Normal file
120
src/aur.vala
Normal file
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* pamac-vala
|
||||
*
|
||||
* Copyright (C) 2014 Guillaume Benoit <guillaume@manjaro.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a get of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace AUR {
|
||||
// AUR urls
|
||||
const string aur_url = "http://aur.archlinux.org";
|
||||
const string rpc_url = aur_url + "/rpc.php";
|
||||
const string rpc_search = "?type=search&arg=";
|
||||
const string rpc_info = "?type=info&arg=";
|
||||
const string rpc_multiinfo = "?type=multiinfo";
|
||||
const string rpc_multiinfo_arg = "&arg[]=";
|
||||
const string aur_url_id = "/packages.php?setlang=en&ID=";
|
||||
|
||||
public Json.Array search (string[] needles) {
|
||||
Json.Array prev_inter = new Json.Array ();
|
||||
string uri = rpc_url + rpc_search + Uri.escape_string (needles[0]);
|
||||
var session = new Soup.Session ();
|
||||
var message = new Soup.Message ("GET", uri);
|
||||
var parser = new Json.Parser ();
|
||||
unowned Json.Object root_object;
|
||||
session.send_message (message);
|
||||
try {
|
||||
parser.load_from_data ((string) message.response_body.flatten ().data, -1);
|
||||
root_object = parser.get_root ().get_object ();
|
||||
prev_inter = root_object.get_array_member ("results");
|
||||
} catch (Error e) {
|
||||
print (e.message);
|
||||
}
|
||||
int length = needles.length;
|
||||
if (length == 1)
|
||||
return prev_inter;
|
||||
int i = 1;
|
||||
Json.Array inter = new Json.Array ();
|
||||
Json.Array found = new Json.Array ();
|
||||
while (i < length) {
|
||||
inter = new Json.Array ();
|
||||
uri = rpc_url + rpc_search + Uri.escape_string (needles[i]);
|
||||
message = new Soup.Message ("GET", uri);
|
||||
session.send_message (message);
|
||||
try {
|
||||
parser.load_from_data ((string) message.response_body.flatten ().data, -1);
|
||||
root_object = parser.get_root ().get_object ();
|
||||
found = root_object.get_array_member ("results");
|
||||
} catch (Error e) {
|
||||
print (e.message);
|
||||
}
|
||||
foreach (Json.Node prev_inter_node in prev_inter.get_elements ()) {
|
||||
foreach (Json.Node found_node in found.get_elements ()) {
|
||||
if (strcmp (prev_inter_node.get_object ().get_string_member ("Name"),
|
||||
found_node.get_object ().get_string_member ("Name")) == 0) {
|
||||
inter.add_element (prev_inter_node);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (i != (length -1))
|
||||
prev_inter = inter;
|
||||
i += 1;
|
||||
}
|
||||
return inter;
|
||||
}
|
||||
|
||||
public Json.Object? info (string pkgname) {
|
||||
unowned Json.Object? pkg_info = null;
|
||||
string uri = rpc_url + rpc_info + pkgname;
|
||||
var session = new Soup.Session ();
|
||||
var message = new Soup.Message ("GET", uri);
|
||||
session.send_message (message);
|
||||
|
||||
try {
|
||||
var parser = new Json.Parser ();
|
||||
parser.load_from_data ((string) message.response_body.flatten ().data, -1);
|
||||
pkg_info = parser.get_root ().get_object ().get_object_member ("results");
|
||||
} catch (Error e) {
|
||||
stderr.printf ("Failed to get infos about %s from AUR\n", pkgname);
|
||||
print (e.message);
|
||||
}
|
||||
return pkg_info;
|
||||
}
|
||||
|
||||
public Json.Array multiinfo (string[] pkgnames) {
|
||||
Json.Array results = new Json.Array ();
|
||||
var builder = new StringBuilder ();
|
||||
builder.append (rpc_url);
|
||||
builder.append (rpc_multiinfo);
|
||||
foreach (string pkgname in pkgnames) {
|
||||
builder.append (rpc_multiinfo_arg);
|
||||
builder.append (pkgname);
|
||||
}
|
||||
var session = new Soup.Session ();
|
||||
var message = new Soup.Message ("GET", builder.str);
|
||||
session.send_message (message);
|
||||
|
||||
try {
|
||||
var parser = new Json.Parser ();
|
||||
parser.load_from_data ((string) message.response_body.flatten ().data, -1);
|
||||
|
||||
unowned Json.Object root_object = parser.get_root ().get_object ();
|
||||
results = root_object.get_array_member ("results");
|
||||
} catch (Error e) {
|
||||
print (e.message);
|
||||
}
|
||||
return results;
|
||||
}
|
||||
}
|
54
src/choose_dep_dialog.vala
Normal file
54
src/choose_dep_dialog.vala
Normal file
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* pamac-vala
|
||||
*
|
||||
* Copyright (C) 2014 Guillaume Benoit <guillaume@manjaro.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a get of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace Pamac {
|
||||
|
||||
[GtkTemplate (ui = "/org/manjaro/pamac/manager/choose_dep_dialog.ui")]
|
||||
public class ChooseDependenciesDialog : Gtk.Dialog {
|
||||
|
||||
[GtkChild]
|
||||
public Gtk.Label label;
|
||||
[GtkChild]
|
||||
public Gtk.TreeView treeview;
|
||||
[GtkChild]
|
||||
public Gtk.CellRendererToggle renderertoggle;
|
||||
|
||||
public Gtk.ListStore deps_list;
|
||||
|
||||
public ChooseDependenciesDialog (Gtk.ApplicationWindow? window) {
|
||||
Object (transient_for: window, use_header_bar: 0);
|
||||
|
||||
deps_list = new Gtk.ListStore (3, typeof (bool), typeof (string), typeof (string));
|
||||
treeview.set_model (deps_list);
|
||||
}
|
||||
|
||||
[GtkCallback]
|
||||
void on_renderertoggle_toggled (string path) {
|
||||
Gtk.TreeIter iter;
|
||||
GLib.Value val;
|
||||
bool selected;
|
||||
if (deps_list.get_iter_from_string (out iter, path)) {;
|
||||
deps_list.get_value (iter, 0, out val);
|
||||
selected = val.get_boolean ();
|
||||
selected = (!selected);
|
||||
deps_list.set_value (iter, 0, selected);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
34
src/choose_provider_dialog.vala
Normal file
34
src/choose_provider_dialog.vala
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* pamac-vala
|
||||
*
|
||||
* Copyright (C) 2014 Guillaume Benoit <guillaume@manjaro.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a get of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace Pamac {
|
||||
|
||||
[GtkTemplate (ui = "/org/manjaro/pamac/transaction/choose_provider_dialog.ui")]
|
||||
public class ChooseProviderDialog : Gtk.Dialog {
|
||||
|
||||
[GtkChild]
|
||||
public Gtk.Label label;
|
||||
[GtkChild]
|
||||
public Gtk.ComboBoxText comboboxtext;
|
||||
|
||||
public ChooseProviderDialog (Gtk.ApplicationWindow? window) {
|
||||
Object (transient_for: window, use_header_bar: 0);
|
||||
}
|
||||
}
|
||||
}
|
214
src/common.vala
Normal file
214
src/common.vala
Normal file
@@ -0,0 +1,214 @@
|
||||
/*
|
||||
* pamac-vala
|
||||
*
|
||||
* Copyright (C) 2014 Guillaume Benoit <guillaume@manjaro.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a get of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace Pamac {
|
||||
public struct UpdatesInfos {
|
||||
public string name;
|
||||
public string version;
|
||||
public string db_name;
|
||||
public string tarpath;
|
||||
public uint64 download_size;
|
||||
}
|
||||
|
||||
public enum Mode {
|
||||
MANAGER,
|
||||
UPDATER,
|
||||
NO_CONFIRM
|
||||
}
|
||||
|
||||
public struct ErrorInfos {
|
||||
public string str;
|
||||
public string[] details;
|
||||
public ErrorInfos () {
|
||||
str = "";
|
||||
details = {};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public string format_size (uint64 size) {
|
||||
float KiB_size = size / 1024;
|
||||
if (KiB_size < 1000) {
|
||||
string size_string = dgettext ("pamac", "%.0f KiB").printf (KiB_size);
|
||||
return size_string;
|
||||
} else {
|
||||
string size_string = dgettext ("pamac", "%.2f MiB").printf (KiB_size / 1024);
|
||||
return size_string;
|
||||
}
|
||||
}
|
||||
|
||||
public int pkgcmp (Alpm.Package pkg1, Alpm.Package pkg2) {
|
||||
return strcmp (pkg1.name, pkg2.name);
|
||||
}
|
||||
|
||||
public unowned Alpm.List<Alpm.Package?> search_all_dbs (Alpm.Handle handle, Alpm.List<string?> needles) {
|
||||
unowned Alpm.List<Alpm.Package?> syncpkgs = null;
|
||||
unowned Alpm.List<Alpm.Package?> result = null;
|
||||
|
||||
result = handle.localdb.search (needles);
|
||||
|
||||
foreach (unowned Alpm.DB db in handle.syncdbs) {
|
||||
if (syncpkgs.length == 0)
|
||||
syncpkgs = db.search (needles);
|
||||
else {
|
||||
syncpkgs.join (db.search (needles).diff (syncpkgs, (Alpm.List.CompareFunc) pkgcmp));
|
||||
}
|
||||
}
|
||||
|
||||
result.join (syncpkgs.diff (result, (Alpm.List.CompareFunc) pkgcmp));
|
||||
//result.sort ((Alpm.List.CompareFunc) pkgcmp);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public unowned Alpm.List<Alpm.Package?> group_pkgs_all_dbs (Alpm.Handle handle, string grp_name) {
|
||||
unowned Alpm.List<Alpm.Package?> result = null;
|
||||
|
||||
unowned Alpm.Group? grp = handle.localdb.get_group (grp_name);
|
||||
if (grp != null) {
|
||||
foreach (unowned Alpm.Package pkg in grp.packages)
|
||||
result.add (pkg);
|
||||
}
|
||||
|
||||
result.join (Alpm.find_group_pkgs (handle.syncdbs, grp_name).diff (result, (Alpm.List.CompareFunc) pkgcmp));
|
||||
|
||||
//result.sort ((Alpm.List.CompareFunc) pkgcmp);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public unowned Alpm.List<Alpm.Package?> get_all_pkgs (Alpm.Handle handle) {
|
||||
unowned Alpm.List<Alpm.Package?> syncpkgs = null;
|
||||
unowned Alpm.List<Alpm.Package?> result = null;
|
||||
|
||||
result = handle.localdb.pkgcache.copy ();
|
||||
|
||||
foreach (unowned Alpm.DB db in handle.syncdbs) {
|
||||
if (syncpkgs.length == 0)
|
||||
syncpkgs = db.pkgcache.copy ();
|
||||
else {
|
||||
syncpkgs.join (db.pkgcache.diff (syncpkgs, (Alpm.List.CompareFunc) pkgcmp));
|
||||
}
|
||||
}
|
||||
|
||||
result.join (syncpkgs.diff (result, (Alpm.List.CompareFunc) pkgcmp));
|
||||
//result.sort ((Alpm.List.CompareFunc) pkgcmp);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public unowned Alpm.Package? get_syncpkg (Alpm.Handle handle, string name) {
|
||||
unowned Alpm.Package? pkg = null;
|
||||
foreach (unowned Alpm.DB db in handle.syncdbs) {
|
||||
pkg = db.get_pkg (name);
|
||||
if (pkg != null)
|
||||
break;
|
||||
}
|
||||
return pkg;
|
||||
}
|
||||
|
||||
public Pamac.UpdatesInfos[] get_syncfirst_updates (Alpm.Handle handle, string[] syncfirst) {
|
||||
Pamac.UpdatesInfos infos = Pamac.UpdatesInfos ();
|
||||
Pamac.UpdatesInfos[] syncfirst_infos = {};
|
||||
unowned Alpm.Package? pkg = null;
|
||||
unowned Alpm.Package? candidate = null;
|
||||
foreach (string name in syncfirst) {
|
||||
pkg = Alpm.find_satisfier (handle.localdb.pkgcache, name);
|
||||
if (pkg != null) {
|
||||
candidate = Alpm.sync_newversion (pkg, handle.syncdbs);
|
||||
if (candidate != null) {
|
||||
infos.name = candidate.name;
|
||||
infos.version = candidate.version;
|
||||
infos.db_name = candidate.db.name;
|
||||
infos.tarpath = "";
|
||||
infos.download_size = candidate.download_size;
|
||||
syncfirst_infos += infos;
|
||||
}
|
||||
}
|
||||
}
|
||||
return syncfirst_infos;
|
||||
}
|
||||
|
||||
public Pamac.UpdatesInfos[] get_repos_updates (Alpm.Handle handle, string[] ignore_pkgs) {
|
||||
unowned Alpm.Package? candidate = null;
|
||||
Pamac.UpdatesInfos infos = Pamac.UpdatesInfos ();
|
||||
Pamac.UpdatesInfos[] updates = {};
|
||||
foreach (unowned Alpm.Package local_pkg in handle.localdb.pkgcache) {
|
||||
// continue only if the local pkg is not in IgnorePkg or IgnoreGroup
|
||||
if ((local_pkg.name in ignore_pkgs) == false) {
|
||||
candidate = Alpm.sync_newversion (local_pkg, handle.syncdbs);
|
||||
if (candidate != null) {
|
||||
infos.name = candidate.name;
|
||||
infos.version = candidate.version;
|
||||
infos.db_name = candidate.db.name;
|
||||
infos.tarpath = "";
|
||||
infos.download_size = candidate.download_size;
|
||||
updates += infos;
|
||||
}
|
||||
}
|
||||
}
|
||||
return updates;
|
||||
}
|
||||
|
||||
public Pamac.UpdatesInfos[] get_aur_updates (Alpm.Handle handle, string[] ignore_pkgs) {
|
||||
unowned Alpm.Package? sync_pkg = null;
|
||||
unowned Alpm.Package? candidate = null;
|
||||
string[] local_pkgs = {};
|
||||
Pamac.UpdatesInfos infos = Pamac.UpdatesInfos ();
|
||||
Pamac.UpdatesInfos[] aur_updates = {};
|
||||
// get local pkgs
|
||||
foreach (unowned Alpm.Package local_pkg in handle.localdb.pkgcache) {
|
||||
// continue only if the local pkg is not in IgnorePkg or IgnoreGroup
|
||||
if ((local_pkg.name in ignore_pkgs) == false) {
|
||||
// check updates from AUR only for local packages
|
||||
foreach (unowned Alpm.DB db in handle.syncdbs) {
|
||||
sync_pkg = Alpm.find_satisfier (db.pkgcache, local_pkg.name);
|
||||
if (sync_pkg != null)
|
||||
break;
|
||||
}
|
||||
if (sync_pkg == null) {
|
||||
// check update from AUR only if no package from dbs will replace it
|
||||
candidate = Alpm.sync_newversion (local_pkg, handle.syncdbs);
|
||||
if (candidate == null) {
|
||||
local_pkgs += local_pkg.name;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// get aur updates
|
||||
Json.Array aur_pkgs = AUR.multiinfo (local_pkgs);
|
||||
int cmp;
|
||||
string version;
|
||||
string name;
|
||||
foreach (Json.Node node in aur_pkgs.get_elements ()) {
|
||||
unowned Json.Object pkg_info = node.get_object ();
|
||||
version = pkg_info.get_string_member ("Version");
|
||||
name = pkg_info.get_string_member ("Name");
|
||||
cmp = Alpm.pkg_vercmp (version, handle.localdb.get_pkg (name).version);
|
||||
if (cmp == 1) {
|
||||
infos.name = name;
|
||||
infos.version = version;
|
||||
infos.db_name = "AUR";
|
||||
infos.tarpath = pkg_info.get_string_member ("URLPath");
|
||||
infos.download_size = 0;
|
||||
aur_updates += infos;
|
||||
}
|
||||
}
|
||||
return aur_updates;
|
||||
}
|
727
src/daemon.vala
Normal file
727
src/daemon.vala
Normal file
@@ -0,0 +1,727 @@
|
||||
/*
|
||||
* pamac-vala
|
||||
*
|
||||
* Copyright (C) 2014 Guillaume Benoit <guillaume@manjaro.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a get of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using Alpm;
|
||||
using Polkit;
|
||||
|
||||
// i18n
|
||||
const string GETTEXT_PACKAGE = "pamac";
|
||||
|
||||
Pamac.Daemon pamac_daemon;
|
||||
MainLoop loop;
|
||||
|
||||
namespace Pamac {
|
||||
[DBus (name = "org.manjaro.pamac")]
|
||||
public class Daemon : Object {
|
||||
string[] syncfirst;
|
||||
string[] holdpkg;
|
||||
string[] ignorepkg;
|
||||
Handle? handle;
|
||||
public uint64 previous_percent;
|
||||
int force_refresh;
|
||||
bool emit_refreshed_signal;
|
||||
public Cond provider_cond;
|
||||
public Mutex provider_mutex;
|
||||
public int? choosen_provider;
|
||||
|
||||
public signal void emit_event (uint event, string[] details);
|
||||
public signal void emit_providers (string depend, string[] providers);
|
||||
public signal void emit_progress (uint progress, string pkgname, int percent, uint n_targets, uint current_target);
|
||||
public signal void emit_download (string filename, uint64 xfered, uint64 total);
|
||||
public signal void emit_totaldownload (uint64 total);
|
||||
public signal void emit_log (uint level, string msg);
|
||||
public signal void emit_refreshed (ErrorInfos error);
|
||||
public signal void emit_trans_prepared (ErrorInfos error);
|
||||
public signal void emit_trans_committed (ErrorInfos error);
|
||||
|
||||
public Daemon () {
|
||||
}
|
||||
|
||||
private void init_alpm_config () {
|
||||
var alpm_config = new Alpm.Config ("/etc/pacman.conf");
|
||||
syncfirst = alpm_config.get_syncfirst ();
|
||||
holdpkg = alpm_config.get_holdpkg ();
|
||||
ignorepkg = alpm_config.get_ignore_pkgs ();
|
||||
handle = alpm_config.get_handle ();
|
||||
if (handle == null) {
|
||||
ErrorInfos err = ErrorInfos ();
|
||||
err.str = _("Failed to initialize alpm library");
|
||||
emit_trans_committed (err);
|
||||
} else {
|
||||
handle.eventcb = (EventCallBack) cb_event;
|
||||
handle.progresscb = (ProgressCallBack) cb_progress;
|
||||
handle.questioncb = (QuestionCallBack) cb_question;
|
||||
handle.dlcb = (DownloadCallBack) cb_download;
|
||||
handle.totaldlcb = (TotalDownloadCallBack) cb_totaldownload;
|
||||
handle.logcb = (LogCallBack) cb_log;
|
||||
}
|
||||
previous_percent = 0;
|
||||
}
|
||||
|
||||
public void write_config (HashTable<string,string> new_conf, GLib.BusName sender) {
|
||||
var pamac_config = new Pamac.Config ("/etc/pamac.conf");
|
||||
try {
|
||||
Polkit.Authority authority = Polkit.Authority.get_sync (null);
|
||||
Polkit.Subject subject = Polkit.SystemBusName.new (sender);
|
||||
Polkit.AuthorizationResult result = authority.check_authorization_sync (
|
||||
subject,
|
||||
"org.manjaro.pamac.commit",
|
||||
null,
|
||||
Polkit.CheckAuthorizationFlags.ALLOW_USER_INTERACTION,
|
||||
null
|
||||
);
|
||||
if (result.get_is_authorized ()) {
|
||||
pamac_config.write (new_conf);
|
||||
}
|
||||
} catch (GLib.Error e) {
|
||||
stderr.printf ("%s\n", e.message);
|
||||
}
|
||||
}
|
||||
|
||||
public void set_pkgreason (string pkgname, uint reason, GLib.BusName sender) {
|
||||
try {
|
||||
Polkit.Authority authority = Polkit.Authority.get_sync (null);
|
||||
Polkit.Subject subject = Polkit.SystemBusName.new (sender);
|
||||
Polkit.AuthorizationResult result = authority.check_authorization_sync (
|
||||
subject,
|
||||
"org.manjaro.pamac.commit",
|
||||
null,
|
||||
Polkit.CheckAuthorizationFlags.ALLOW_USER_INTERACTION,
|
||||
null
|
||||
);
|
||||
if (result.get_is_authorized ()) {
|
||||
init_alpm_config ();
|
||||
unowned Package? pkg = handle.localdb.get_pkg (pkgname);
|
||||
if (pkg != null)
|
||||
pkg.reason = (PkgReason) reason;
|
||||
}
|
||||
} catch (GLib.Error e) {
|
||||
stderr.printf ("%s\n", e.message);
|
||||
}
|
||||
}
|
||||
|
||||
private int refresh_real () {
|
||||
init_alpm_config ();
|
||||
ErrorInfos err = ErrorInfos ();
|
||||
string[] details = {};
|
||||
int success = 0;
|
||||
int ret = handle.trans_init (0);
|
||||
if (ret == 0) {
|
||||
foreach (var db in handle.syncdbs) {
|
||||
ret = db.update (force_refresh);
|
||||
if (ret >= 0) {
|
||||
success++;
|
||||
}
|
||||
}
|
||||
// We should always succeed if at least one DB was upgraded - we may possibly
|
||||
// fail later with unresolved deps, but that should be rare, and would be expected
|
||||
if (success == 0) {
|
||||
err.str = _("Failed to synchronize any databases");
|
||||
details += Alpm.strerror (handle.errno ());
|
||||
err.details = details;
|
||||
}
|
||||
trans_release ();
|
||||
} else {
|
||||
err.str = _("Failed to synchronize any databases");
|
||||
details += Alpm.strerror (handle.errno ());
|
||||
err.details = details;
|
||||
}
|
||||
if (emit_refreshed_signal)
|
||||
emit_refreshed (err);
|
||||
return success;
|
||||
}
|
||||
|
||||
public void refresh (int force, bool emit_signal) {
|
||||
force_refresh = force;
|
||||
emit_refreshed_signal = emit_signal;
|
||||
try {
|
||||
new Thread<int>.try ("refresh thread", (ThreadFunc) refresh_real);
|
||||
} catch (GLib.Error e) {
|
||||
stderr.printf ("%s\n", e.message);
|
||||
}
|
||||
}
|
||||
|
||||
public UpdatesInfos[] get_updates () {
|
||||
init_alpm_config ();
|
||||
var pamac_config = new Pamac.Config ("/etc/pamac.conf");
|
||||
UpdatesInfos[] updates = {};
|
||||
updates = get_syncfirst_updates (handle, syncfirst);
|
||||
if (updates.length != 0) {
|
||||
return updates;
|
||||
} else {
|
||||
updates = get_repos_updates (handle, ignorepkg);
|
||||
if (pamac_config.enable_aur) {
|
||||
UpdatesInfos[] aur_updates = get_aur_updates (handle, ignorepkg);
|
||||
foreach (var infos in aur_updates)
|
||||
updates += infos;
|
||||
}
|
||||
return updates;
|
||||
}
|
||||
}
|
||||
|
||||
public ErrorInfos trans_init (TransFlag transflags) {
|
||||
init_alpm_config ();
|
||||
ErrorInfos err = ErrorInfos ();
|
||||
string[] details = {};
|
||||
int ret = handle.trans_init (transflags);
|
||||
if (ret == -1) {
|
||||
err.str = _("Failed to init transaction");
|
||||
details += Alpm.strerror (handle.errno ());
|
||||
err.details = details;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
public ErrorInfos trans_sysupgrade (int enable_downgrade) {
|
||||
ErrorInfos err = ErrorInfos ();
|
||||
string[] details = {};
|
||||
int ret = handle.trans_sysupgrade (enable_downgrade);
|
||||
if (ret == -1) {;
|
||||
err.str = _("Failed to prepare transaction");
|
||||
details += Alpm.strerror (handle.errno ());
|
||||
err.details = details;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
public ErrorInfos trans_add_pkg (string pkgname) {
|
||||
ErrorInfos err = ErrorInfos ();
|
||||
string[] details = {};
|
||||
unowned Package? pkg = null;
|
||||
pkg = handle.find_dbs_satisfier (handle.syncdbs, pkgname);
|
||||
//foreach (var db in handle.syncdbs) {
|
||||
//pkg = find_satisfier (db.pkgcache, pkgname);
|
||||
//if (pkg != null)
|
||||
//break;
|
||||
//}
|
||||
if (pkg == null) {
|
||||
err.str = _("Failed to prepare transaction");
|
||||
details += _("target not found: %s").printf (pkgname);
|
||||
err.details = details;
|
||||
return err;
|
||||
}
|
||||
int ret = handle.trans_add_pkg (pkg);
|
||||
if (ret == -1) {
|
||||
Alpm.Errno errno = handle.errno ();
|
||||
if (errno == Errno.TRANS_DUP_TARGET || errno == Errno.PKG_IGNORED)
|
||||
// just skip duplicate or ignored targets
|
||||
return err;
|
||||
else {
|
||||
err.str = _("Failed to prepare transaction");
|
||||
details += "%s: %s".printf (pkg.name, Alpm.strerror (errno));
|
||||
err.details = details;
|
||||
return err;
|
||||
}
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
public ErrorInfos trans_load_pkg (string pkgpath) {
|
||||
ErrorInfos err = ErrorInfos ();
|
||||
string[] details = {};
|
||||
Package* pkg = handle.load_file (pkgpath, 1, handle.localfilesiglevel);
|
||||
if (pkg == null) {
|
||||
err.str = _("Failed to prepare transaction");
|
||||
details += "%s: %s".printf (pkgpath, Alpm.strerror (handle.errno ()));
|
||||
err.details = details;
|
||||
return err;
|
||||
} else {
|
||||
int ret = handle.trans_add_pkg (pkg);
|
||||
if (ret == -1) {
|
||||
Alpm.Errno errno = handle.errno ();
|
||||
if (errno == Errno.TRANS_DUP_TARGET || errno == Errno.PKG_IGNORED)
|
||||
// just skip duplicate or ignored targets
|
||||
return err;
|
||||
else {
|
||||
err.str = _("Failed to prepare transaction");
|
||||
details += "%s: %s".printf (pkg->name, Alpm.strerror (errno));
|
||||
err.details = details;
|
||||
return err;
|
||||
}
|
||||
// free the package because it will not be used
|
||||
delete pkg;
|
||||
}
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
public ErrorInfos trans_remove_pkg (string pkgname) {
|
||||
ErrorInfos err = ErrorInfos ();
|
||||
string[] details = {};
|
||||
unowned Package? pkg = handle.localdb.get_pkg (pkgname);
|
||||
if (pkg == null) {
|
||||
err.str = _("Failed to prepare transaction");
|
||||
details += _("target not found: %s").printf (pkgname);
|
||||
err.details = details;
|
||||
return err;
|
||||
}
|
||||
int ret = handle.trans_remove_pkg (pkg);
|
||||
if (ret == -1) {
|
||||
err.str = _("Failed to prepare transaction");
|
||||
details += "%s: %s".printf (pkg.name, Alpm.strerror (handle.errno ()));
|
||||
err.details = details;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
public int trans_prepare_real () {
|
||||
ErrorInfos err = ErrorInfos ();
|
||||
string[] details = {};
|
||||
Alpm.List<void*> err_data = null;
|
||||
int ret = handle.trans_prepare (out err_data);
|
||||
if (ret == -1) {
|
||||
Alpm.Errno errno = handle.errno ();
|
||||
err.str = _("Failed to prepare transaction");
|
||||
string detail = Alpm.strerror (errno);
|
||||
switch (errno) {
|
||||
case Errno.PKG_INVALID_ARCH:
|
||||
detail += ":";
|
||||
details += detail;
|
||||
foreach (void *i in err_data) {
|
||||
char *pkgname = i;
|
||||
details += _("package %s does not have a valid architecture").printf (pkgname);
|
||||
}
|
||||
break;
|
||||
case Errno.UNSATISFIED_DEPS:
|
||||
detail += ":";
|
||||
details += detail;
|
||||
foreach (void *i in err_data) {
|
||||
DepMissing *miss = i;
|
||||
string depstring = miss->depend.compute_string ();
|
||||
details += _("%s: requires %s").printf (miss->target, depstring);
|
||||
}
|
||||
break;
|
||||
case Errno.CONFLICTING_DEPS:
|
||||
detail += ":";
|
||||
details += detail;
|
||||
foreach (void *i in err_data) {
|
||||
Conflict *conflict = i;
|
||||
detail = _("%s and %s are in conflict").printf (conflict->package1, conflict->package2);
|
||||
// only print reason if it contains new information
|
||||
if (conflict->reason.mod != DepMod.ANY) {
|
||||
detail += " (%s)".printf (conflict->reason.compute_string ());
|
||||
}
|
||||
details += detail;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
details += detail;
|
||||
break;
|
||||
}
|
||||
err.details = details;
|
||||
trans_release ();
|
||||
} else {
|
||||
// Search for holdpkg in target list
|
||||
bool found_locked_pkg = false;
|
||||
foreach (var pkg in handle.trans_to_remove ()) {
|
||||
if (pkg.name in holdpkg) {
|
||||
details += _("%s needs to be removed but it is a locked package").printf (pkg.name);
|
||||
found_locked_pkg = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found_locked_pkg) {
|
||||
err.str = _("Failed to prepare transaction");
|
||||
err.details = details;
|
||||
trans_release ();
|
||||
}
|
||||
}
|
||||
emit_trans_prepared (err);
|
||||
return ret;
|
||||
}
|
||||
|
||||
public void trans_prepare () {
|
||||
try {
|
||||
new Thread<int>.try ("prepare thread", (ThreadFunc) trans_prepare_real);
|
||||
} catch (GLib.Error e) {
|
||||
stderr.printf ("%s\n", e.message);
|
||||
}
|
||||
}
|
||||
|
||||
public void choose_provider (int provider) {
|
||||
provider_mutex.lock ();
|
||||
choosen_provider = provider;
|
||||
provider_cond.signal ();
|
||||
provider_mutex.unlock ();
|
||||
}
|
||||
|
||||
public UpdatesInfos[] trans_to_add () {
|
||||
UpdatesInfos info = UpdatesInfos ();
|
||||
UpdatesInfos[] infos = {};
|
||||
foreach (var pkg in handle.trans_to_add ()) {
|
||||
info.name = pkg.name;
|
||||
info.version = pkg.version;
|
||||
// if pkg was load from a file, pkg.db is null
|
||||
if (pkg.db != null)
|
||||
info.db_name = pkg.db.name;
|
||||
else
|
||||
info.db_name = "";
|
||||
info.tarpath = "";
|
||||
info.download_size = pkg.download_size;
|
||||
infos += info;
|
||||
}
|
||||
return infos;
|
||||
}
|
||||
|
||||
public UpdatesInfos[] trans_to_remove () {
|
||||
UpdatesInfos info = UpdatesInfos ();
|
||||
UpdatesInfos[] infos = {};
|
||||
foreach (var pkg in handle.trans_to_remove ()) {
|
||||
info.name = pkg.name;
|
||||
info.version = pkg.version;
|
||||
info.db_name = pkg.db.name;
|
||||
info.tarpath = "";
|
||||
info.download_size = pkg.download_size;
|
||||
infos += info;
|
||||
}
|
||||
return infos;
|
||||
}
|
||||
|
||||
private int trans_commit_real () {
|
||||
ErrorInfos err = ErrorInfos ();
|
||||
string[] details = {};
|
||||
Alpm.List<void*> err_data = null;
|
||||
int ret = handle.trans_commit (out err_data);
|
||||
if (ret == -1) {
|
||||
Alpm.Errno errno = handle.errno ();
|
||||
err.str = _("Failed to commit transaction");
|
||||
string detail = Alpm.strerror (errno);
|
||||
switch (errno) {
|
||||
case Alpm.Errno.FILE_CONFLICTS:
|
||||
detail += ":";
|
||||
details += detail;
|
||||
//TransFlag flags = handle.trans_get_flags ();
|
||||
//if ((flags & TransFlag.FORCE) != 0) {
|
||||
//details += _("unable to %s directory-file conflicts").printf ("--force");
|
||||
//}
|
||||
foreach (void *i in err_data) {
|
||||
FileConflict *conflict = i;
|
||||
switch (conflict->type) {
|
||||
case FileConflictType.TARGET:
|
||||
details += _("%s exists in both %s and %s").printf (conflict->file, conflict->target, conflict->ctarget);
|
||||
break;
|
||||
case FileConflictType.FILESYSTEM:
|
||||
details += _("%s: %s already exists in filesystem").printf (conflict->target, conflict->file);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case Alpm.Errno.PKG_INVALID:
|
||||
case Alpm.Errno.PKG_INVALID_CHECKSUM:
|
||||
case Alpm.Errno.PKG_INVALID_SIG:
|
||||
case Alpm.Errno.DLT_INVALID:
|
||||
detail += ":";
|
||||
details += detail;
|
||||
foreach (void *i in err_data) {
|
||||
char *filename = i;
|
||||
details += _("%s is invalid or corrupted").printf (filename);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
details += detail;
|
||||
break;
|
||||
}
|
||||
err.details = details;
|
||||
}
|
||||
trans_release ();
|
||||
emit_trans_committed (err);
|
||||
return ret;
|
||||
}
|
||||
|
||||
public void trans_commit (GLib.BusName sender) {
|
||||
try {
|
||||
Polkit.Authority authority = Polkit.Authority.get_sync (null);
|
||||
Polkit.Subject subject = Polkit.SystemBusName.new (sender);
|
||||
var result = new Polkit.AuthorizationResult (false, false, null);
|
||||
authority.check_authorization.begin (
|
||||
subject,
|
||||
"org.manjaro.pamac.commit",
|
||||
null,
|
||||
Polkit.CheckAuthorizationFlags.ALLOW_USER_INTERACTION,
|
||||
null,
|
||||
(obj, res) => {
|
||||
try {
|
||||
result = authority.check_authorization.end (res);
|
||||
if (result.get_is_authorized ()) {
|
||||
new Thread<int>.try ("commit thread", (ThreadFunc) trans_commit_real);
|
||||
} else {
|
||||
ErrorInfos err = ErrorInfos ();
|
||||
err.str = dgettext (null, "Authentication failed");
|
||||
emit_trans_committed (err);
|
||||
trans_release ();
|
||||
}
|
||||
} catch (GLib.Error e) {
|
||||
stderr.printf ("Polkit Error: %s\n", e.message);
|
||||
}
|
||||
}
|
||||
);
|
||||
} catch (GLib.Error e) {
|
||||
stderr.printf ("Polkit Error: %s\n", e.message);
|
||||
}
|
||||
}
|
||||
|
||||
public int trans_release () {
|
||||
return handle.trans_release ();
|
||||
}
|
||||
|
||||
public void trans_cancel () {
|
||||
handle.trans_interrupt ();
|
||||
handle.trans_release ();
|
||||
init_alpm_config ();
|
||||
}
|
||||
|
||||
public void quit () {
|
||||
GLib.File lockfile = GLib.File.new_for_path ("/var/lib/pacman/db.lck");
|
||||
if (lockfile.query_exists () == false)
|
||||
loop.quit ();
|
||||
}
|
||||
// End of Daemon Object
|
||||
}
|
||||
}
|
||||
|
||||
private void write_log_file (string event) {
|
||||
var now = new DateTime.now_local ();
|
||||
string log = "%s %s".printf (now.format ("[%Y-%m-%d %H:%M]"), event);
|
||||
var file = GLib.File.new_for_path ("/var/log/pamac.log");
|
||||
try {
|
||||
// creating a DataOutputStream to the file
|
||||
var dos = new DataOutputStream (file.append_to (FileCreateFlags.NONE));
|
||||
// writing a short string to the stream
|
||||
dos.put_string (log);
|
||||
} catch (GLib.Error e) {
|
||||
stderr.printf("%s\n", e.message);
|
||||
}
|
||||
}
|
||||
|
||||
private void cb_event (Event event, void *data1, void *data2) {
|
||||
string[] details = {};
|
||||
switch (event) {
|
||||
case Event.ADD_START:
|
||||
case Event.REMOVE_START:
|
||||
case Event.REINSTALL_START:
|
||||
unowned Package pkg = (Package) data1;
|
||||
details += pkg.name;
|
||||
details += pkg.version;
|
||||
break;
|
||||
case Event.ADD_DONE:
|
||||
unowned Package pkg = (Package) data1;
|
||||
string log = "Installed %s (%s)\n".printf (pkg.name, pkg.version);
|
||||
write_log_file (log);
|
||||
break;
|
||||
case Event.REMOVE_DONE:
|
||||
unowned Package pkg = (Package) data1;
|
||||
string log = "Removed %s (%s)\n".printf (pkg.name, pkg.version);
|
||||
write_log_file (log);
|
||||
break;
|
||||
case Event.REINSTALL_DONE:
|
||||
unowned Package pkg = (Package) data1;
|
||||
string log = "Reinstalled %s (%s)\n".printf (pkg.name, pkg.version);
|
||||
write_log_file (log);
|
||||
break;
|
||||
case Event.UPGRADE_START:
|
||||
case Event.DOWNGRADE_START:
|
||||
unowned Package new_pkg = (Package) data1;
|
||||
unowned Package old_pkg = (Package) data2;
|
||||
details += old_pkg.name;
|
||||
details += old_pkg.version;
|
||||
details += new_pkg.version;
|
||||
break;
|
||||
case Event.UPGRADE_DONE:
|
||||
unowned Package new_pkg = (Package) data1;
|
||||
unowned Package old_pkg = (Package) data2;
|
||||
string log = "Upgraded %s (%s -> %s)\n".printf (old_pkg.name, old_pkg.version, new_pkg.version);
|
||||
write_log_file (log);
|
||||
break;
|
||||
case Event.DOWNGRADE_DONE:
|
||||
unowned Package new_pkg = (Package) data1;
|
||||
unowned Package old_pkg = (Package) data2;
|
||||
string log = "Downgraded %s (%s -> %s)\n".printf (old_pkg.name, old_pkg.version, new_pkg.version);
|
||||
write_log_file (log);
|
||||
break;
|
||||
case Event.DELTA_PATCH_START:
|
||||
unowned string string1 = (string) data1;
|
||||
unowned string string2 = (string) data2;
|
||||
details += string1;
|
||||
details += string2;
|
||||
break;
|
||||
case Event.SCRIPTLET_INFO:
|
||||
unowned string info = (string) data1;
|
||||
details += info;
|
||||
write_log_file (info);
|
||||
break;
|
||||
case Event.OPTDEP_REQUIRED:
|
||||
unowned Package pkg = (Package) data1;
|
||||
Depend *depend = data2;
|
||||
details += pkg.name;
|
||||
details += depend->compute_string ();
|
||||
break;
|
||||
case Event.DATABASE_MISSING:
|
||||
unowned string db_name = (string) data1;
|
||||
details += db_name;
|
||||
break;
|
||||
//~ case Event.CHECKDEPS_START:
|
||||
//~ case Event.CHECKDEPS_DONE:
|
||||
//~ case Event.FILECONFLICTS_START:
|
||||
//~ case Event.FILECONFLICTS_DONE:
|
||||
//~ case Event.RESOLVEDEPS_START:
|
||||
//~ case Event.RESOLVEDEPS_DONE:
|
||||
//~ case Event.INTERCONFLICTS_START:
|
||||
//~ case Event.INTERCONFLICTS_DONE:
|
||||
//~ case Event.INTEGRITY_START:
|
||||
//~ case Event.INTEGRITY_DONE:
|
||||
//~ case Event.KEYRING_START:
|
||||
//~ case Event.KEYRING_DONE:
|
||||
//~ case Event.KEY_DOWNLOAD_START:
|
||||
//~ case Event.KEY_DOWNLOAD_DONE:
|
||||
//~ case Event.LOAD_START:
|
||||
//~ case Event.LOAD_DONE:
|
||||
//~ case Event.DELTA_INTEGRITY_START:
|
||||
//~ case Event.DELTA_INTEGRITY_DONE:
|
||||
//~ case Event.DELTA_PATCHES_START:
|
||||
//~ case Event.DELTA_PATCHES_DONE:
|
||||
//~ case Event.DELTA_PATCH_DONE:
|
||||
//~ case Event.DELTA_PATCH_FAILED:
|
||||
//~ case Event.RETRIEVE_START:
|
||||
//~ case Event.DISKSPACE_START:
|
||||
//~ case Event.DISKSPACE_DONE:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
pamac_daemon.emit_event ((uint) event, details);
|
||||
}
|
||||
|
||||
private void cb_question (Question question, void *data1, void *data2, void *data3, out int response) {
|
||||
switch (question) {
|
||||
case Question.INSTALL_IGNOREPKG:
|
||||
// Do not install package in IgnorePkg/IgnoreGroup
|
||||
response = 0;
|
||||
break;
|
||||
case Question.REPLACE_PKG:
|
||||
// Auto-remove conflicts in case of replaces
|
||||
response = 1;
|
||||
break;
|
||||
case Question.CONFLICT_PKG:
|
||||
// Auto-remove conflicts
|
||||
response = 1;
|
||||
break;
|
||||
case Question.REMOVE_PKGS:
|
||||
// Do not upgrade packages which have unresolvable dependencies
|
||||
response = 1;
|
||||
break;
|
||||
case Question.SELECT_PROVIDER:
|
||||
unowned Alpm.List<Package?> providers = (Alpm.List<Package?>) data1;
|
||||
Depend *depend = data2;
|
||||
string depend_str = depend->compute_string ();
|
||||
string[] providers_str = {};
|
||||
foreach (var pkg in providers) {
|
||||
providers_str += pkg.name;
|
||||
}
|
||||
pamac_daemon.provider_cond = Cond ();
|
||||
pamac_daemon.provider_mutex = Mutex ();
|
||||
pamac_daemon.choosen_provider = null;
|
||||
pamac_daemon.emit_providers (depend_str, providers_str);
|
||||
pamac_daemon.provider_mutex.lock ();
|
||||
while (pamac_daemon.choosen_provider == null) {
|
||||
pamac_daemon.provider_cond.wait (pamac_daemon.provider_mutex);
|
||||
}
|
||||
response = pamac_daemon.choosen_provider;
|
||||
pamac_daemon.provider_mutex.unlock ();
|
||||
break;
|
||||
case Question.CORRUPTED_PKG:
|
||||
// Auto-remove corrupted pkgs in cache
|
||||
response = 1;
|
||||
break;
|
||||
case Question.IMPORT_KEY:
|
||||
PGPKey *key = data1;
|
||||
// Do not get revoked key
|
||||
if (key->revoked == 1) response = 0;
|
||||
// Auto get not revoked key
|
||||
else response = 1;
|
||||
break;
|
||||
default:
|
||||
response = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void cb_progress (Progress progress, string pkgname, int percent, uint n_targets, uint current_target) {
|
||||
//~ switch (progress) {
|
||||
//~ case Progress.ADD_START:
|
||||
//~ case Progress.UPGRADE_START:
|
||||
//~ case Progress.DOWNGRADE_START:
|
||||
//~ case Progress.REINSTALL_START:
|
||||
//~ case Progress.REMOVE_START:
|
||||
//~ case Progress.CONFLICTS_START:
|
||||
//~ case Progress.DISKSPACE_START:
|
||||
//~ case Progress.INTEGRITY_START:
|
||||
//~ case Progress.KEYRING_START:
|
||||
//~ case Progress.LOAD_START:
|
||||
//~ default:
|
||||
//~ break;
|
||||
//~ }
|
||||
if ((uint64) percent != pamac_daemon.previous_percent) {
|
||||
pamac_daemon.previous_percent = (uint64) percent;
|
||||
pamac_daemon.emit_progress ((uint) progress, pkgname, percent, n_targets, current_target);
|
||||
}
|
||||
}
|
||||
|
||||
private void cb_download (string filename, uint64 xfered, uint64 total) {
|
||||
if (xfered != pamac_daemon.previous_percent) {
|
||||
pamac_daemon.previous_percent = xfered;
|
||||
pamac_daemon.emit_download (filename, xfered, total);
|
||||
}
|
||||
}
|
||||
|
||||
private void cb_totaldownload (uint64 total) {
|
||||
pamac_daemon.emit_totaldownload (total);
|
||||
}
|
||||
|
||||
private void cb_log (LogLevel level, string fmt, va_list args) {
|
||||
LogLevel logmask = LogLevel.ERROR | LogLevel.WARNING;
|
||||
if ((level & logmask) == 0)
|
||||
return;
|
||||
string? log = null;
|
||||
log = fmt.vprintf (args);
|
||||
if (log != null)
|
||||
pamac_daemon.emit_log ((uint) level, log);
|
||||
}
|
||||
|
||||
void on_bus_acquired (DBusConnection conn) {
|
||||
pamac_daemon = new Pamac.Daemon ();
|
||||
try {
|
||||
conn.register_object ("/org/manjaro/pamac", pamac_daemon);
|
||||
}
|
||||
catch (IOError e) {
|
||||
stderr.printf ("Could not register service\n");
|
||||
}
|
||||
}
|
||||
|
||||
void main () {
|
||||
// i18n
|
||||
Intl.setlocale (LocaleCategory.ALL, "");
|
||||
Intl.textdomain (GETTEXT_PACKAGE);
|
||||
|
||||
Bus.own_name (BusType.SYSTEM, "org.manjaro.pamac", BusNameOwnerFlags.NONE,
|
||||
on_bus_acquired,
|
||||
() => {},
|
||||
() => stderr.printf("Could not acquire name\n"));
|
||||
|
||||
loop = new MainLoop ();
|
||||
loop.run ();
|
||||
}
|
40
src/history_dialog.vala
Normal file
40
src/history_dialog.vala
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* pamac-vala
|
||||
*
|
||||
* Copyright (C) 2014 Guillaume Benoit <guillaume@manjaro.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a get of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace Pamac {
|
||||
|
||||
[GtkTemplate (ui = "/org/manjaro/pamac/manager/history_dialog.ui")]
|
||||
public class HistoryDialog : Gtk.Dialog {
|
||||
|
||||
[GtkChild]
|
||||
public Gtk.TextView textview;
|
||||
|
||||
public HistoryDialog (ManagerWindow window) {
|
||||
Object (transient_for: window, use_header_bar: 0);
|
||||
}
|
||||
|
||||
[GtkCallback]
|
||||
public void on_textview_size_allocate () {
|
||||
// auto-scrolling method
|
||||
var scrollable = textview as Gtk.Scrollable;
|
||||
var adj = scrollable.get_vadjustment ();
|
||||
adj.set_value (adj.get_upper () - adj.get_page_size ());
|
||||
}
|
||||
}
|
||||
}
|
106
src/installer.vala
Normal file
106
src/installer.vala
Normal file
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* pamac-vala
|
||||
*
|
||||
* Copyright (C) 2014 Guillaume Benoit <guillaume@manjaro.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a get of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace Pamac {
|
||||
|
||||
public class Installer: Gtk.Application {
|
||||
Transaction transaction;
|
||||
bool pamac_run;
|
||||
|
||||
public Installer () {
|
||||
application_id = "org.manjaro.pamac.install";
|
||||
flags |= ApplicationFlags.HANDLES_OPEN;
|
||||
}
|
||||
|
||||
public override void startup () {
|
||||
// i18n
|
||||
Intl.textdomain ("pamac");
|
||||
Intl.setlocale (LocaleCategory.ALL, "");
|
||||
|
||||
base.startup ();
|
||||
|
||||
pamac_run = check_pamac_running ();
|
||||
if (pamac_run) {
|
||||
var transaction_info_dialog = new TransactionInfoDialog (null);
|
||||
transaction_info_dialog.set_title (dgettext (null, "Error"));
|
||||
transaction_info_dialog.label.set_visible (true);
|
||||
transaction_info_dialog.label.set_markup (dgettext (null, "Pamac is already running"));
|
||||
transaction_info_dialog.expander.set_visible (false);
|
||||
transaction_info_dialog.run ();
|
||||
transaction_info_dialog.hide ();
|
||||
} else {
|
||||
transaction = new Pamac.Transaction (null);
|
||||
transaction.finished.connect (on_emit_trans_finished);
|
||||
this.hold ();
|
||||
}
|
||||
}
|
||||
|
||||
public override void activate () {
|
||||
if (pamac_run == false) {
|
||||
print ("\nError: Path(s) of tarball(s) to install is needed\n");
|
||||
transaction.stop_daemon ();
|
||||
this.release ();
|
||||
}
|
||||
}
|
||||
|
||||
public override void open (File[] files, string hint) {
|
||||
if (pamac_run == false) {
|
||||
foreach (File file in files) {
|
||||
string? path = file.get_path ();
|
||||
transaction.to_load.insert (path, path);
|
||||
}
|
||||
transaction.run ();
|
||||
}
|
||||
}
|
||||
|
||||
bool check_pamac_running () {
|
||||
Application app;
|
||||
bool run = false;
|
||||
app = new Application ("org.manjaro.pamac.manager", 0);
|
||||
try {
|
||||
app.register ();
|
||||
} catch (GLib.Error e) {
|
||||
stderr.printf ("%s\n", e.message);
|
||||
}
|
||||
run = app.get_is_remote ();
|
||||
if (run)
|
||||
return run;
|
||||
else {
|
||||
app = new Application ("org.manjaro.pamac.updater", 0);
|
||||
try {
|
||||
app.register ();
|
||||
} catch (GLib.Error e) {
|
||||
stderr.printf ("%s\n", e.message);
|
||||
}
|
||||
run = app.get_is_remote ();
|
||||
return run;
|
||||
}
|
||||
}
|
||||
|
||||
public void on_emit_trans_finished (bool error) {
|
||||
transaction.stop_daemon ();
|
||||
this.release ();
|
||||
}
|
||||
|
||||
public static int main (string[] args) {
|
||||
var installer = new Installer();
|
||||
return installer.run (args);
|
||||
}
|
||||
}
|
||||
}
|
95
src/manager.vala
Normal file
95
src/manager.vala
Normal file
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* pamac-vala
|
||||
*
|
||||
* Copyright (C) 2014 Guillaume Benoit <guillaume@manjaro.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a get of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace Pamac {
|
||||
|
||||
public class Manager : Gtk.Application {
|
||||
ManagerWindow manager_window;
|
||||
bool pamac_run;
|
||||
|
||||
public Manager () {
|
||||
application_id = "org.manjaro.pamac.manager";
|
||||
flags = ApplicationFlags.FLAGS_NONE;
|
||||
}
|
||||
|
||||
public override void startup () {
|
||||
// i18n
|
||||
Intl.textdomain ("pamac");
|
||||
Intl.setlocale (LocaleCategory.ALL, "");
|
||||
|
||||
base.startup ();
|
||||
|
||||
pamac_run = check_pamac_running ();
|
||||
if (pamac_run) {
|
||||
var transaction_info_dialog = new TransactionInfoDialog (null);
|
||||
transaction_info_dialog.set_title (dgettext (null, "Error"));
|
||||
transaction_info_dialog.label.set_visible (true);
|
||||
transaction_info_dialog.label.set_markup (dgettext (null, "Pamac is already running"));
|
||||
transaction_info_dialog.expander.set_visible (false);
|
||||
transaction_info_dialog.run ();
|
||||
transaction_info_dialog.hide ();
|
||||
} else
|
||||
manager_window = new ManagerWindow (this);
|
||||
}
|
||||
|
||||
public override void activate () {
|
||||
if (pamac_run == false) {
|
||||
manager_window.present ();
|
||||
while (Gtk.events_pending ())
|
||||
Gtk.main_iteration ();
|
||||
manager_window.show_all_pkgs ();
|
||||
}
|
||||
}
|
||||
|
||||
public override void shutdown () {
|
||||
base.shutdown ();
|
||||
if (pamac_run == false)
|
||||
manager_window.transaction.stop_daemon ();
|
||||
}
|
||||
|
||||
bool check_pamac_running () {
|
||||
Application app;
|
||||
bool run = false;
|
||||
app = new Application ("org.manjaro.pamac.updater", 0);
|
||||
try {
|
||||
app.register ();
|
||||
} catch (GLib.Error e) {
|
||||
stderr.printf ("%s\n", e.message);
|
||||
}
|
||||
run = app.get_is_remote ();
|
||||
if (run)
|
||||
return run;
|
||||
else {
|
||||
app = new Application ("org.manjaro.pamac.install", 0);
|
||||
try {
|
||||
app.register ();
|
||||
} catch (GLib.Error e) {
|
||||
stderr.printf ("%s\n", e.message);
|
||||
}
|
||||
run = app.get_is_remote ();
|
||||
return run;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static int main (string[] args) {
|
||||
var manager = new Manager ();
|
||||
return manager.run (args);
|
||||
}
|
||||
}
|
1174
src/manager_window.vala
Normal file
1174
src/manager_window.vala
Normal file
File diff suppressed because it is too large
Load Diff
61
src/package.vala
Normal file
61
src/package.vala
Normal file
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* pamac-vala
|
||||
*
|
||||
* Copyright (C) 2014 Guillaume Benoit <guillaume@manjaro.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a get of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace Pamac {
|
||||
public class Package: Object {
|
||||
public unowned Alpm.Package? alpm_pkg;
|
||||
public unowned Json.Object? aur_json;
|
||||
public string name;
|
||||
public string version;
|
||||
public string repo;
|
||||
public uint64 size;
|
||||
public string size_string;
|
||||
|
||||
public Package (Alpm.Package? alpm_pkg, Json.Object? aur_json) {
|
||||
if (alpm_pkg != null) {
|
||||
this.alpm_pkg = alpm_pkg;
|
||||
this.aur_json = null;
|
||||
name = alpm_pkg.name;
|
||||
version = alpm_pkg.version;
|
||||
if (alpm_pkg.db != null)
|
||||
repo = alpm_pkg.db.name;
|
||||
else
|
||||
repo = "";
|
||||
size = alpm_pkg.isize;
|
||||
size_string = format_size (alpm_pkg.isize);
|
||||
} else if (aur_json != null ) {
|
||||
this.alpm_pkg = null;
|
||||
this.aur_json = aur_json;
|
||||
name = aur_json.get_string_member ("Name");
|
||||
version = aur_json.get_string_member ("Version");
|
||||
repo = "AUR";
|
||||
size = 0;
|
||||
size_string = "";
|
||||
} else {
|
||||
this.alpm_pkg = null;
|
||||
this.aur_json = null;
|
||||
name = dgettext (null, "No package found");
|
||||
version = "";
|
||||
repo = "";
|
||||
size = 0;
|
||||
size_string = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
55
src/packages_chooser_dialog.vala
Normal file
55
src/packages_chooser_dialog.vala
Normal file
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* pamac-vala
|
||||
*
|
||||
* Copyright (C) 2014 Guillaume Benoit <guillaume@manjaro.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a get of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace Pamac {
|
||||
|
||||
[GtkTemplate (ui = "/org/manjaro/pamac/manager/packages_chooser_dialog.ui")]
|
||||
public class PackagesChooserDialog : Gtk.FileChooserDialog {
|
||||
|
||||
ManagerWindow window;
|
||||
Transaction transaction;
|
||||
|
||||
public PackagesChooserDialog (ManagerWindow window, Transaction transaction) {
|
||||
Object (transient_for: window, use_header_bar: 0);
|
||||
|
||||
Gtk.FileFilter package_filter = new Gtk.FileFilter ();
|
||||
package_filter.set_filter_name (dgettext (null, "Alpm Package"));
|
||||
package_filter.add_pattern ("*.pkg.tar.xz");
|
||||
this.add_filter (package_filter);
|
||||
|
||||
this.window = window;
|
||||
this.transaction = transaction;
|
||||
}
|
||||
|
||||
[GtkCallback]
|
||||
public void on_file_activated () {
|
||||
SList<string> packages_paths = this.get_filenames ();
|
||||
if (packages_paths.length () != 0) {
|
||||
foreach (string path in packages_paths) {
|
||||
transaction.to_load.insert (path, path);
|
||||
}
|
||||
window.get_window ().set_cursor (new Gdk.Cursor (Gdk.CursorType.WATCH));
|
||||
this.hide ();
|
||||
while (Gtk.events_pending ())
|
||||
Gtk.main_iteration ();
|
||||
transaction.run ();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
309
src/packages_model.vala
Normal file
309
src/packages_model.vala
Normal file
@@ -0,0 +1,309 @@
|
||||
/*
|
||||
* pamac-vala
|
||||
*
|
||||
* Copyright (C) 2014 Guillaume Benoit <guillaume@manjaro.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a get of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace Pamac {
|
||||
|
||||
public class PackagesModel : Object, Gtk.TreeModel {
|
||||
private GLib.List<Pamac.Package> all_pkgs;
|
||||
public ManagerWindow manager_window;
|
||||
|
||||
public PackagesModel (Alpm.List<Alpm.Package?>? alpm_pkgs, Json.Array? aur_pkgs, ManagerWindow manager_window) {
|
||||
this.manager_window = manager_window;
|
||||
all_pkgs = new GLib.List<Pamac.Package> ();
|
||||
foreach (unowned Alpm.Package alpm_pkg in alpm_pkgs) {
|
||||
all_pkgs.append (new Pamac.Package (alpm_pkg, null));
|
||||
}
|
||||
if (aur_pkgs != null) {
|
||||
unowned Json.Object pkg_info;
|
||||
string name;
|
||||
bool found;
|
||||
foreach (Json.Node node in aur_pkgs.get_elements ()) {
|
||||
pkg_info = node.get_object ();
|
||||
name = pkg_info.get_string_member ("Name");
|
||||
// add only the packages which are not already in the list
|
||||
found = false;
|
||||
foreach (Pamac.Package pkg in all_pkgs) {
|
||||
if (pkg.name == name) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (found == false)
|
||||
all_pkgs.append (new Pamac.Package (null, pkg_info));
|
||||
}
|
||||
}
|
||||
if (all_pkgs.length () == 0) {
|
||||
// create a fake "No package found" package
|
||||
all_pkgs.append (new Pamac.Package (null, null));
|
||||
}
|
||||
}
|
||||
|
||||
// TreeModel interface
|
||||
public Type get_column_type (int index) {
|
||||
switch (index) {
|
||||
case 0: // name
|
||||
case 2: // version
|
||||
case 3: // repo
|
||||
case 4: // installed size
|
||||
return typeof (string);
|
||||
case 1: // icon
|
||||
return typeof (Gdk.Pixbuf);
|
||||
default:
|
||||
return Type.INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
public Gtk.TreeModelFlags get_flags () {
|
||||
return Gtk.TreeModelFlags.LIST_ONLY | Gtk.TreeModelFlags.ITERS_PERSIST;
|
||||
}
|
||||
|
||||
public void get_value (Gtk.TreeIter iter, int column, out Value val) {
|
||||
Pamac.Package pkg = (Pamac.Package) iter.user_data;
|
||||
return_if_fail (pkg != null);
|
||||
switch (column) {
|
||||
case 0:
|
||||
val = Value (typeof (string));
|
||||
val.set_string (pkg.name);
|
||||
break;
|
||||
case 1:
|
||||
val = Value (typeof (Object));
|
||||
if (pkg.alpm_pkg != null) {
|
||||
if (pkg.name in manager_window.transaction.holdpkg)
|
||||
val.set_object (manager_window.locked_icon);
|
||||
else if (pkg.repo == "local") {
|
||||
if (manager_window.transaction.to_add.contains (pkg.name))
|
||||
val.set_object (manager_window.to_reinstall_icon);
|
||||
else if (manager_window.transaction.to_remove.contains (pkg.name))
|
||||
val.set_object (manager_window.to_remove_icon);
|
||||
else
|
||||
val.set_object (manager_window.installed_icon);
|
||||
} else if (manager_window.transaction.to_add.contains (pkg.name))
|
||||
val.set_object (manager_window.to_install_icon);
|
||||
else
|
||||
val.set_object (manager_window.uninstalled_icon);
|
||||
} else if (pkg.aur_json != null) {
|
||||
if (manager_window.transaction.to_build.contains (pkg.name))
|
||||
val.set_object (manager_window.to_install_icon);
|
||||
else
|
||||
val.set_object (manager_window.uninstalled_icon);
|
||||
} else {
|
||||
Object? object = null;
|
||||
val.set_object (object);
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
val = Value (typeof (string));
|
||||
val.set_string (pkg.version);
|
||||
break;
|
||||
case 3:
|
||||
val = Value (typeof (string));
|
||||
val.set_string (pkg.repo);
|
||||
break;
|
||||
case 4:
|
||||
val = Value (typeof (string));
|
||||
val.set_string (pkg.size_string);
|
||||
break;
|
||||
default:
|
||||
val = Value (Type.INVALID);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public bool get_iter (out Gtk.TreeIter iter, Gtk.TreePath path) {;
|
||||
if (path.get_depth () != 1 || all_pkgs.length () == 0) {
|
||||
return invalid_iter (out iter);
|
||||
}
|
||||
iter = Gtk.TreeIter ();
|
||||
int pos = path.get_indices ()[0];
|
||||
iter.stamp = pos;
|
||||
Pamac.Package pkg = all_pkgs.nth_data((uint) pos);
|
||||
iter.user_data = pkg;
|
||||
return true;
|
||||
}
|
||||
|
||||
public int get_n_columns () {
|
||||
// name, icon, version, repo, isize
|
||||
return 5;
|
||||
}
|
||||
|
||||
public Gtk.TreePath? get_path (Gtk.TreeIter iter) {
|
||||
return new Gtk.TreePath.from_indices (iter.stamp);
|
||||
}
|
||||
|
||||
public int iter_n_children (Gtk.TreeIter? iter) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public bool iter_next (ref Gtk.TreeIter iter) {
|
||||
int pos = (iter.stamp) + 1;
|
||||
if (pos >= all_pkgs.length ()) {
|
||||
return false;
|
||||
}
|
||||
iter.stamp = pos;
|
||||
Pamac.Package pkg = all_pkgs.nth_data((uint) pos);
|
||||
iter.user_data = pkg;
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool iter_previous (ref Gtk.TreeIter iter) {
|
||||
int pos = iter.stamp;
|
||||
if (pos >= 0) {
|
||||
return false;
|
||||
}
|
||||
iter.stamp = (--pos);
|
||||
Pamac.Package pkg = all_pkgs.nth_data((uint) pos);
|
||||
iter.user_data = pkg;
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool iter_nth_child (out Gtk.TreeIter iter, Gtk.TreeIter? parent, int n) {
|
||||
return invalid_iter (out iter);
|
||||
}
|
||||
|
||||
public bool iter_children (out Gtk.TreeIter iter, Gtk.TreeIter? parent) {
|
||||
return invalid_iter (out iter);
|
||||
}
|
||||
|
||||
public bool iter_has_child (Gtk.TreeIter iter) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public bool iter_parent (out Gtk.TreeIter iter, Gtk.TreeIter child) {
|
||||
return invalid_iter (out iter);
|
||||
}
|
||||
|
||||
private bool invalid_iter (out Gtk.TreeIter iter) {
|
||||
iter = Gtk.TreeIter ();
|
||||
iter.stamp = -1;
|
||||
return false;
|
||||
}
|
||||
|
||||
// custom sort functions
|
||||
public void sort_by_name (Gtk.SortType order) {
|
||||
CompareFunc<Pamac.Package> namecmp = (pkg_a, pkg_b) => {
|
||||
return strcmp (pkg_a.name, pkg_b.name);
|
||||
};
|
||||
all_pkgs.sort (namecmp);
|
||||
if (order == Gtk.SortType.DESCENDING)
|
||||
all_pkgs.reverse ();
|
||||
manager_window.name_column.sort_order = order;
|
||||
manager_window.state_column.sort_indicator = false;
|
||||
manager_window.name_column.sort_indicator = true;
|
||||
manager_window.version_column.sort_indicator = false;
|
||||
manager_window.repo_column.sort_indicator = false;
|
||||
manager_window.size_column.sort_indicator = false;
|
||||
manager_window.sortinfo.column_number = 0;
|
||||
manager_window.sortinfo.sort_type = order;
|
||||
}
|
||||
|
||||
public void sort_by_state (Gtk.SortType order) {
|
||||
CompareFunc<Pamac.Package> statecmp = (pkg_a, pkg_b) => {
|
||||
int state_a;
|
||||
int state_b;
|
||||
if (pkg_a.alpm_pkg != null) {
|
||||
if (pkg_a.repo == "local")
|
||||
state_a = 0;
|
||||
else
|
||||
state_a = 1;
|
||||
} else
|
||||
state_a = 1;
|
||||
if (pkg_b.alpm_pkg != null) {
|
||||
if (pkg_b.repo == "local")
|
||||
state_b = 0;
|
||||
else
|
||||
state_b = 1;
|
||||
} else
|
||||
state_b = 1;
|
||||
return (int) (state_a > state_b) - (int) (state_a < state_b);
|
||||
};
|
||||
all_pkgs.sort (statecmp);
|
||||
if (order == Gtk.SortType.DESCENDING)
|
||||
all_pkgs.reverse ();
|
||||
manager_window.state_column.sort_order = order;
|
||||
manager_window.state_column.sort_indicator = true;
|
||||
manager_window.name_column.sort_indicator = false;
|
||||
manager_window.version_column.sort_indicator = false;
|
||||
manager_window.repo_column.sort_indicator = false;
|
||||
manager_window.size_column.sort_indicator = false;
|
||||
manager_window.sortinfo.column_number = 1;
|
||||
manager_window.sortinfo.sort_type = order;
|
||||
}
|
||||
|
||||
public void sort_by_version (Gtk.SortType order) {
|
||||
CompareFunc<Pamac.Package> versioncmp = (pkg_a, pkg_b) => {
|
||||
return Alpm.pkg_vercmp (pkg_a.version, pkg_b.version);
|
||||
};
|
||||
all_pkgs.sort (versioncmp);
|
||||
if (order == Gtk.SortType.DESCENDING)
|
||||
all_pkgs.reverse ();
|
||||
manager_window.version_column.sort_order = order;
|
||||
manager_window.state_column.sort_indicator = false;
|
||||
manager_window.name_column.sort_indicator = false;
|
||||
manager_window.version_column.sort_indicator = true;
|
||||
manager_window.repo_column.sort_indicator = false;
|
||||
manager_window.size_column.sort_indicator = false;
|
||||
manager_window.sortinfo.column_number = 2;
|
||||
manager_window.sortinfo.sort_type = order;
|
||||
}
|
||||
|
||||
public void sort_by_repo (Gtk.SortType order) {
|
||||
CompareFunc<Pamac.Package> repocmp = (pkg_a, pkg_b) => {
|
||||
return strcmp (pkg_a.repo, pkg_b.repo);
|
||||
};
|
||||
all_pkgs.sort (repocmp);
|
||||
if (order == Gtk.SortType.DESCENDING)
|
||||
all_pkgs.reverse ();
|
||||
manager_window.repo_column.sort_order = order;
|
||||
manager_window.state_column.sort_indicator = false;
|
||||
manager_window.name_column.sort_indicator = false;
|
||||
manager_window.version_column.sort_indicator = false;
|
||||
manager_window.repo_column.sort_indicator = true;
|
||||
manager_window.size_column.sort_indicator = false;
|
||||
manager_window.sortinfo.column_number = 3;
|
||||
manager_window.sortinfo.sort_type = order;
|
||||
}
|
||||
|
||||
public void sort_by_size (Gtk.SortType order) {
|
||||
CompareFunc<Pamac.Package> sizecmp = (pkg_a, pkg_b) => {
|
||||
uint64 size_a;
|
||||
uint64 size_b;
|
||||
if (pkg_a.alpm_pkg != null)
|
||||
size_a = pkg_a.size;
|
||||
else
|
||||
size_a = 0;
|
||||
if (pkg_b.alpm_pkg != null)
|
||||
size_b = pkg_b.size;
|
||||
else
|
||||
size_b = 0;
|
||||
return (int) (size_a > size_b) - (int) (size_a < size_b);
|
||||
};
|
||||
all_pkgs.sort (sizecmp);
|
||||
if (order == Gtk.SortType.DESCENDING)
|
||||
all_pkgs.reverse ();
|
||||
manager_window.size_column.sort_order = order;
|
||||
manager_window.state_column.sort_indicator = false;
|
||||
manager_window.name_column.sort_indicator = false;
|
||||
manager_window.version_column.sort_indicator = false;
|
||||
manager_window.repo_column.sort_indicator = false;
|
||||
manager_window.size_column.sort_indicator = true;
|
||||
manager_window.sortinfo.column_number = 4;
|
||||
manager_window.sortinfo.sort_type = order;
|
||||
}
|
||||
}
|
||||
}
|
133
src/pamac_config.vala
Normal file
133
src/pamac_config.vala
Normal file
@@ -0,0 +1,133 @@
|
||||
/*
|
||||
* pamac-vala
|
||||
*
|
||||
* Copyright (C) 2014 Guillaume Benoit <guillaume@manjaro.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a get of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace Pamac {
|
||||
public class Config: Object {
|
||||
public uint64 refresh_period;
|
||||
public bool enable_aur;
|
||||
public bool recurse;
|
||||
public string conf_path;
|
||||
|
||||
public Config (string path) {
|
||||
this.conf_path = path;
|
||||
// set default options
|
||||
this.refresh_period = 4;
|
||||
this.enable_aur = false;
|
||||
this.recurse = false;
|
||||
// parse conf file
|
||||
this.parse_include_file (conf_path);
|
||||
}
|
||||
|
||||
public void parse_include_file (string path) {
|
||||
var file = GLib.File.new_for_path (path);
|
||||
if (file.query_exists () == false)
|
||||
GLib.stderr.printf ("File '%s' doesn't exist.\n", file.get_path ());
|
||||
else {
|
||||
try {
|
||||
// Open file for reading and wrap returned FileInputStream into a
|
||||
// DataInputStream, so we can read line by line
|
||||
var dis = new DataInputStream (file.read ());
|
||||
string line;
|
||||
// Read lines until end of file (null) is reached
|
||||
while ((line = dis.read_line (null)) != null) {
|
||||
line = line.strip ();
|
||||
if (line.length == 0) continue;
|
||||
if (line[0] == '#') continue;
|
||||
string[] splitted = line.split ("=");
|
||||
string _key = splitted[0].strip ();
|
||||
string _value = null;
|
||||
if (splitted[1] != null)
|
||||
_value = splitted[1].strip ();
|
||||
if (_key == "RefreshPeriod")
|
||||
this.refresh_period = uint64.parse (_value);
|
||||
else if (_key == "EnableAUR")
|
||||
this.enable_aur = true;
|
||||
else if (_key == "RemoveUnrequiredDeps")
|
||||
this.recurse = true;
|
||||
}
|
||||
} catch (GLib.Error e) {
|
||||
GLib.stderr.printf("%s\n", e.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void write (HashTable<string,string> new_conf) {
|
||||
var file = GLib.File.new_for_path (this.conf_path);
|
||||
if (file.query_exists () == false)
|
||||
GLib.stderr.printf ("File '%s' doesn't exist.\n", file.get_path ());
|
||||
else {
|
||||
try {
|
||||
// Open file for reading and wrap returned FileInputStream into a
|
||||
// DataInputStream, so we can read line by line
|
||||
var dis = new DataInputStream (file.read ());
|
||||
string line;
|
||||
string[] data = {};
|
||||
// Read lines until end of file (null) is reached
|
||||
while ((line = dis.read_line (null)) != null) {
|
||||
if (line.contains ("RefreshPeriod")) {
|
||||
if (new_conf.contains ("RefreshPeriod")) {
|
||||
string _value = new_conf.get ("RefreshPeriod");
|
||||
data += "RefreshPeriod = %s\n".printf (_value);
|
||||
this.refresh_period = uint64.parse (_value);
|
||||
} else
|
||||
data += line + "\n";
|
||||
} else if (line.contains ("EnableAUR")) {
|
||||
if (new_conf.contains ("EnableAUR")) {
|
||||
bool _value = bool.parse (new_conf.get ("EnableAUR"));
|
||||
if (_value == true)
|
||||
data += "EnableAUR\n";
|
||||
else
|
||||
data += "#EnableAUR\n";
|
||||
this.enable_aur = _value;
|
||||
} else
|
||||
data += line + "\n";
|
||||
} else if (line.contains ("RemoveUnrequiredDeps")) {
|
||||
if (new_conf.contains ("RemoveUnrequiredDeps")) {
|
||||
bool _value = bool.parse (new_conf.get ("RemoveUnrequiredDeps"));
|
||||
if (_value == true)
|
||||
data += "RemoveUnrequiredDeps\n";
|
||||
else
|
||||
data += "#RemoveUnrequiredDeps\n";
|
||||
this.enable_aur = _value;
|
||||
} else
|
||||
data += line + "\n";
|
||||
} else
|
||||
data += line + "\n";
|
||||
}
|
||||
// delete the file before rewrite it
|
||||
file.delete ();
|
||||
// creating a DataOutputStream to the file
|
||||
var dos = new DataOutputStream (file.create (FileCreateFlags.REPLACE_DESTINATION));
|
||||
foreach (string new_line in data) {
|
||||
// writing a short string to the stream
|
||||
dos.put_string (new_line);
|
||||
}
|
||||
} catch (GLib.Error e) {
|
||||
GLib.stderr.printf("%s\n", e.message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void reload () {
|
||||
this.enable_aur = false;
|
||||
this.recurse = false;
|
||||
this.parse_include_file (this.conf_path);
|
||||
}
|
||||
}
|
||||
}
|
40
src/preferences_dialog.vala
Normal file
40
src/preferences_dialog.vala
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* pamac-vala
|
||||
*
|
||||
* Copyright (C) 2014 Guillaume Benoit <guillaume@manjaro.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a get of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace Pamac {
|
||||
|
||||
[GtkTemplate (ui = "/org/manjaro/pamac/preferences/preferences_dialog.ui")]
|
||||
public class PreferencesDialog : Gtk.Dialog {
|
||||
|
||||
[GtkChild]
|
||||
public Gtk.Switch enable_aur_button;
|
||||
[GtkChild]
|
||||
public Gtk.Switch remove_unrequired_deps_button;
|
||||
[GtkChild]
|
||||
public Gtk.SpinButton refresh_period_spin_button;
|
||||
[GtkChild]
|
||||
public Gtk.Label refresh_period_label;
|
||||
|
||||
public PreferencesDialog (Gtk.ApplicationWindow window) {
|
||||
Object (transient_for: window, use_header_bar: 0);
|
||||
|
||||
refresh_period_label.set_markup (dgettext (null, "How often to check for updates, value in hours") +":");
|
||||
}
|
||||
}
|
||||
}
|
62
src/progress_dialog.vala
Normal file
62
src/progress_dialog.vala
Normal file
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* pamac-vala
|
||||
*
|
||||
* Copyright (C) 2014 Guillaume Benoit <guillaume@manjaro.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a get of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace Pamac {
|
||||
|
||||
[GtkTemplate (ui = "/org/manjaro/pamac/transaction/progress_dialog.ui")]
|
||||
public class ProgressDialog : Gtk.Dialog {
|
||||
|
||||
[GtkChild]
|
||||
public Gtk.ProgressBar progressbar;
|
||||
[GtkChild]
|
||||
public Gtk.Label action_label;
|
||||
[GtkChild]
|
||||
public Gtk.Button cancel_button;
|
||||
[GtkChild]
|
||||
public Gtk.Button close_button;
|
||||
[GtkChild]
|
||||
public Gtk.Expander expander;
|
||||
|
||||
Transaction transaction;
|
||||
|
||||
public ProgressDialog (Transaction transaction, Gtk.ApplicationWindow? window) {
|
||||
Object (transient_for: window, use_header_bar: 0);
|
||||
|
||||
this.transaction = transaction;
|
||||
}
|
||||
|
||||
[GtkCallback]
|
||||
public void on_close_button_clicked () {
|
||||
this.hide ();
|
||||
while (Gtk.events_pending ())
|
||||
Gtk.main_iteration ();
|
||||
}
|
||||
|
||||
[GtkCallback]
|
||||
public void on_cancel_button_clicked () {
|
||||
transaction.cancel ();
|
||||
transaction.clear_lists ();
|
||||
transaction.spawn_in_term ({"/usr/bin/echo", dgettext (null, "Transaction cancelled") + ".\n"});
|
||||
this.hide ();
|
||||
transaction.finished (false);
|
||||
while (Gtk.events_pending ())
|
||||
Gtk.main_iteration ();
|
||||
}
|
||||
}
|
||||
}
|
1019
src/transaction.vala
Normal file
1019
src/transaction.vala
Normal file
File diff suppressed because it is too large
Load Diff
40
src/transaction_info_dialog.vala
Normal file
40
src/transaction_info_dialog.vala
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* pamac-vala
|
||||
*
|
||||
* Copyright (C) 2014 Guillaume Benoit <guillaume@manjaro.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a get of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace Pamac {
|
||||
|
||||
[GtkTemplate (ui = "/org/manjaro/pamac/transaction/transaction_info_dialog.ui")]
|
||||
public class TransactionInfoDialog : Gtk.Dialog {
|
||||
|
||||
[GtkChild]
|
||||
public Gtk.Label label;
|
||||
[GtkChild]
|
||||
public Gtk.Expander expander;
|
||||
[GtkChild]
|
||||
public Gtk.TextView textview;
|
||||
|
||||
public Gtk.TextBuffer textbuffer;
|
||||
|
||||
public TransactionInfoDialog (Gtk.ApplicationWindow? window) {
|
||||
Object (transient_for: window, use_header_bar: 0);
|
||||
|
||||
textbuffer = textview.get_buffer ();
|
||||
}
|
||||
}
|
||||
}
|
41
src/transaction_sum_dialog.vala
Normal file
41
src/transaction_sum_dialog.vala
Normal file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* pamac-vala
|
||||
*
|
||||
* Copyright (C) 2014 Guillaume Benoit <guillaume@manjaro.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a get of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace Pamac {
|
||||
|
||||
[GtkTemplate (ui = "/org/manjaro/pamac/transaction/transaction_sum_dialog.ui")]
|
||||
public class TransactionSumDialog : Gtk.Dialog {
|
||||
|
||||
[GtkChild]
|
||||
public Gtk.Label top_label;
|
||||
[GtkChild]
|
||||
public Gtk.Label bottom_label;
|
||||
[GtkChild]
|
||||
public Gtk.TreeView treeview;
|
||||
|
||||
public Gtk.ListStore sum_list;
|
||||
|
||||
public TransactionSumDialog (Gtk.ApplicationWindow? window) {
|
||||
Object (transient_for: window, use_header_bar: 0);
|
||||
|
||||
sum_list = new Gtk.ListStore (2, typeof (string), typeof (string));
|
||||
treeview.set_model (sum_list);
|
||||
}
|
||||
}
|
||||
}
|
247
src/tray.vala
Normal file
247
src/tray.vala
Normal file
@@ -0,0 +1,247 @@
|
||||
/*
|
||||
* pamac-vala
|
||||
*
|
||||
* Copyright (C) 2014 Guillaume Benoit <guillaume@manjaro.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a get of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// i18n
|
||||
const string GETTEXT_PACKAGE = "pamac";
|
||||
|
||||
const string update_icon_name = "pamac-tray-update";
|
||||
const string noupdate_icon_name = "pamac-tray-no-update";
|
||||
const string noupdate_info = _("Your system is up-to-date");
|
||||
|
||||
namespace Pamac {
|
||||
[DBus (name = "org.manjaro.pamac")]
|
||||
public interface Daemon : Object {
|
||||
public abstract void refresh (int force, bool emit_signal) throws IOError;
|
||||
public abstract UpdatesInfos[] get_updates () throws IOError;
|
||||
[DBus (no_reply = true)]
|
||||
public abstract void quit () throws IOError;
|
||||
}
|
||||
|
||||
public class TrayIcon: Gtk.Application {
|
||||
Notify.Notification notification;
|
||||
Daemon daemon;
|
||||
Pamac.Config pamac_config;
|
||||
bool locked;
|
||||
uint refresh_timeout_id;
|
||||
Gtk.StatusIcon status_icon;
|
||||
Gtk.Menu menu;
|
||||
|
||||
public TrayIcon () {
|
||||
application_id = "org.manjaro.pamac.tray";
|
||||
flags = ApplicationFlags.FLAGS_NONE;
|
||||
}
|
||||
|
||||
void start_daemon () {
|
||||
try {
|
||||
daemon = Bus.get_proxy_sync (BusType.SYSTEM, "org.manjaro.pamac",
|
||||
"/org/manjaro/pamac");
|
||||
} catch (IOError e) {
|
||||
stderr.printf ("IOError: %s\n", e.message);
|
||||
}
|
||||
}
|
||||
|
||||
void stop_daemon () {
|
||||
try {
|
||||
daemon.quit ();
|
||||
} catch (IOError e) {
|
||||
stderr.printf ("IOError: %s\n", e.message);
|
||||
}
|
||||
}
|
||||
|
||||
// Create menu for right button
|
||||
void create_menu () {
|
||||
menu = new Gtk.Menu ();
|
||||
Gtk.MenuItem item;
|
||||
item = new Gtk.MenuItem.with_label (_("Update Manager"));
|
||||
item.activate.connect (execute_updater);
|
||||
menu.append (item);
|
||||
item = new Gtk.MenuItem.with_label (_("Package Manager"));
|
||||
item.activate.connect (execute_manager);
|
||||
menu.append (item);
|
||||
item = new Gtk.MenuItem.with_mnemonic (_("_Quit"));
|
||||
item.activate.connect (this.release);
|
||||
menu.append (item);
|
||||
menu.show_all ();
|
||||
}
|
||||
|
||||
// Show popup menu on right button
|
||||
void menu_popup (uint button, uint time) {
|
||||
menu.popup (null, null, null, button, time);
|
||||
}
|
||||
|
||||
void left_clicked () {
|
||||
if (status_icon.icon_name == "pamac-tray-update")
|
||||
execute_updater ();
|
||||
}
|
||||
|
||||
void execute_updater () {
|
||||
try {
|
||||
Process.spawn_async(null, new string[]{"/usr/bin/pamac-updater"}, null, SpawnFlags.SEARCH_PATH, null, null);
|
||||
} catch (Error e) {
|
||||
print(e.message);
|
||||
}
|
||||
}
|
||||
|
||||
void execute_manager () {
|
||||
try {
|
||||
Process.spawn_async(null, new string[]{"/usr/bin/pamac-manager"}, null, SpawnFlags.SEARCH_PATH, null, null);
|
||||
} catch (Error e) {
|
||||
print(e.message);
|
||||
}
|
||||
}
|
||||
|
||||
public void update_icon (string icon, string info) {
|
||||
status_icon.set_from_icon_name (icon);
|
||||
status_icon.set_tooltip_markup (info);
|
||||
}
|
||||
|
||||
bool refresh () {
|
||||
start_daemon ();
|
||||
try {
|
||||
daemon.refresh (0, false);
|
||||
} catch (IOError e) {
|
||||
stderr.printf ("IOError: %s\n", e.message);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void check_updates () {
|
||||
UpdatesInfos[] updates = {};
|
||||
bool pamac_run = check_pamac_running ();
|
||||
try {
|
||||
updates = daemon.get_updates ();
|
||||
} catch (IOError e) {
|
||||
stderr.printf ("IOError: %s\n", e.message);
|
||||
}
|
||||
uint updates_nb = updates.length;
|
||||
if (updates_nb == 0) {
|
||||
this.update_icon (noupdate_icon_name, noupdate_info);
|
||||
} else {
|
||||
string info = ngettext ("%u available update", "%u available updates", updates_nb).printf (updates_nb);
|
||||
this.update_icon (update_icon_name, info);
|
||||
if (pamac_run == false)
|
||||
show_notification (info);
|
||||
}
|
||||
if (pamac_run == false)
|
||||
stop_daemon ();
|
||||
}
|
||||
|
||||
void show_notification (string info) {
|
||||
//~ notification = new Notification (_("Update Manager"));
|
||||
//~ notification.set_body (info);
|
||||
//~ Gtk.IconTheme icon_theme = Gtk.IconTheme.get_default ();
|
||||
//~ Gdk.Pixbuf icon = icon_theme.load_icon ("system-software-update", 32, 0);
|
||||
//~ notification.set_icon (icon);
|
||||
//~ var action = new SimpleAction ("update", null);
|
||||
//~ action.activate.connect (execute_updater);
|
||||
//~ this.add_action (action);
|
||||
//~ notification.add_button (_("Show available updates"), "app.update");
|
||||
//~ this.send_notification (_("Update Manager"), notification);
|
||||
try {
|
||||
notification = new Notify.Notification (_("Update Manager"), info, "system-software-update");
|
||||
notification.add_action ("update", _("Show available updates"), execute_updater);
|
||||
notification.show ();
|
||||
} catch (Error e) {
|
||||
stderr.printf ("Notify Error: %s", e.message);
|
||||
}
|
||||
}
|
||||
|
||||
bool check_pamac_running () {
|
||||
Application app;
|
||||
bool run = false;
|
||||
app = new Application ("org.manjaro.pamac.manager", 0);
|
||||
try {
|
||||
app.register ();
|
||||
} catch (GLib.Error e) {
|
||||
stderr.printf ("%s\n", e.message);
|
||||
}
|
||||
run = app.get_is_remote ();
|
||||
if (run)
|
||||
return run;
|
||||
else {
|
||||
app = new Application ("org.manjaro.pamac.updater", 0);
|
||||
try {
|
||||
app.register ();
|
||||
} catch (GLib.Error e) {
|
||||
stderr.printf ("%s\n", e.message);
|
||||
}
|
||||
run = app.get_is_remote ();
|
||||
return run;
|
||||
}
|
||||
}
|
||||
|
||||
bool check_pacman_running () {
|
||||
GLib.File lockfile = GLib.File.new_for_path ("/var/lib/pacman/db.lck");
|
||||
if (locked) {
|
||||
if (lockfile.query_exists () == false) {
|
||||
locked = false;
|
||||
check_updates ();
|
||||
}
|
||||
} else {
|
||||
if (lockfile.query_exists () == true) {
|
||||
locked = true;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void launch_refresh_timeout (string? msg = null) {
|
||||
if (refresh_timeout_id != 0) {
|
||||
pamac_config.reload ();
|
||||
Source.remove (refresh_timeout_id);
|
||||
}
|
||||
refresh_timeout_id = Timeout.add_seconds ((uint) pamac_config.refresh_period*3600, refresh);
|
||||
}
|
||||
|
||||
public override void startup () {
|
||||
// i18n
|
||||
Intl.textdomain ("pamac");
|
||||
Intl.setlocale (LocaleCategory.ALL, "");
|
||||
|
||||
base.startup ();
|
||||
|
||||
pamac_config = new Pamac.Config ("/etc/pamac.conf");
|
||||
locked = false;
|
||||
refresh_timeout_id = 0;
|
||||
|
||||
status_icon = new Gtk.StatusIcon ();
|
||||
status_icon.set_visible (true);
|
||||
status_icon.activate.connect (left_clicked);
|
||||
create_menu ();
|
||||
status_icon.popup_menu.connect (menu_popup);
|
||||
|
||||
Notify.init (_("Update Manager"));
|
||||
|
||||
refresh ();
|
||||
launch_refresh_timeout ();
|
||||
Timeout.add (500, check_pacman_running);
|
||||
|
||||
this.hold ();
|
||||
}
|
||||
|
||||
public override void activate () {
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
public static int main (string[] args) {
|
||||
var tray_icon = new TrayIcon();
|
||||
return tray_icon.run (args);
|
||||
}
|
||||
}
|
||||
}
|
91
src/updater.vala
Normal file
91
src/updater.vala
Normal file
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* pamac-vala
|
||||
*
|
||||
* Copyright (C) 2014 Guillaume Benoit <guillaume@manjaro.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a get of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
namespace Pamac {
|
||||
|
||||
public class Updater : Gtk.Application {
|
||||
UpdaterWindow updater_window;
|
||||
bool pamac_run;
|
||||
|
||||
public Updater () {
|
||||
application_id = "org.manjaro.pamac.updater";
|
||||
flags = ApplicationFlags.FLAGS_NONE;
|
||||
}
|
||||
|
||||
public override void startup () {
|
||||
// i18n
|
||||
Intl.textdomain ("pamac");
|
||||
Intl.setlocale (LocaleCategory.ALL, "");
|
||||
|
||||
base.startup ();
|
||||
|
||||
pamac_run = check_pamac_running ();
|
||||
if (pamac_run) {
|
||||
var transaction_info_dialog = new TransactionInfoDialog (null);
|
||||
transaction_info_dialog.set_title (dgettext (null, "Error"));
|
||||
transaction_info_dialog.label.set_visible (true);
|
||||
transaction_info_dialog.label.set_markup (dgettext (null, "Pamac is already running"));
|
||||
transaction_info_dialog.expander.set_visible (false);
|
||||
transaction_info_dialog.run ();
|
||||
transaction_info_dialog.hide ();
|
||||
} else
|
||||
updater_window = new UpdaterWindow (this);
|
||||
}
|
||||
|
||||
public override void activate () {
|
||||
if (pamac_run == false)
|
||||
updater_window.present ();
|
||||
}
|
||||
|
||||
public override void shutdown () {
|
||||
base.shutdown ();
|
||||
if (pamac_run == false)
|
||||
updater_window.transaction.stop_daemon ();
|
||||
}
|
||||
|
||||
bool check_pamac_running () {
|
||||
Application app;
|
||||
bool run = false;
|
||||
app = new Application ("org.manjaro.pamac.manager", 0);
|
||||
try {
|
||||
app.register ();
|
||||
} catch (GLib.Error e) {
|
||||
stderr.printf ("%s\n", e.message);
|
||||
}
|
||||
run = app.get_is_remote ();
|
||||
if (run)
|
||||
return run;
|
||||
else {
|
||||
app = new Application ("org.manjaro.pamac.install", 0);
|
||||
try {
|
||||
app.register ();
|
||||
} catch (GLib.Error e) {
|
||||
stderr.printf ("%s\n", e.message);
|
||||
}
|
||||
run = app.get_is_remote ();
|
||||
return run;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static int main (string[] args) {
|
||||
var updater = new Updater ();
|
||||
return updater.run (args);
|
||||
}
|
||||
}
|
192
src/updater_window.vala
Normal file
192
src/updater_window.vala
Normal file
@@ -0,0 +1,192 @@
|
||||
/*
|
||||
* pamac-vala
|
||||
*
|
||||
* Copyright (C) 2014 Guillaume Benoit <guillaume@manjaro.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a get of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
using Gtk;
|
||||
|
||||
namespace Pamac {
|
||||
|
||||
[GtkTemplate (ui = "/org/manjaro/pamac/updater/updater_window.ui")]
|
||||
public class UpdaterWindow : Gtk.ApplicationWindow {
|
||||
|
||||
[GtkChild]
|
||||
public Label top_label;
|
||||
[GtkChild]
|
||||
public TreeView updates_treeview;
|
||||
[GtkChild]
|
||||
public Label bottom_label;
|
||||
[GtkChild]
|
||||
public Button apply_button;
|
||||
|
||||
public ListStore updates_list;
|
||||
public Pamac.Config pamac_config;
|
||||
public Pamac.Transaction transaction;
|
||||
|
||||
PreferencesDialog preferences_dialog;
|
||||
|
||||
public UpdaterWindow (Gtk.Application application) {
|
||||
Object (application: application);
|
||||
|
||||
pamac_config = new Pamac.Config ("/etc/pamac.conf");
|
||||
|
||||
updates_list = new Gtk.ListStore (2, typeof (string), typeof (string));
|
||||
updates_treeview.set_model (updates_list);
|
||||
|
||||
transaction = new Transaction (this as ApplicationWindow);
|
||||
transaction.mode = Mode.UPDATER;
|
||||
transaction.check_aur = pamac_config.enable_aur;
|
||||
transaction.finished.connect (on_emit_trans_finished);
|
||||
|
||||
preferences_dialog = new PreferencesDialog (this as ApplicationWindow);
|
||||
|
||||
bottom_label.set_visible (false);
|
||||
apply_button.set_sensitive (false);
|
||||
|
||||
on_refresh_button_clicked ();
|
||||
}
|
||||
|
||||
[GtkCallback]
|
||||
public void on_preferences_button_clicked () {
|
||||
bool enable_aur = pamac_config.enable_aur;
|
||||
bool recurse = pamac_config.recurse;
|
||||
uint64 refresh_period = pamac_config.refresh_period;
|
||||
preferences_dialog.enable_aur_button.set_active (enable_aur);
|
||||
preferences_dialog.remove_unrequired_deps_button.set_active (recurse);
|
||||
preferences_dialog.refresh_period_spin_button.set_value (refresh_period);
|
||||
int response = preferences_dialog.run ();
|
||||
while (Gtk.events_pending ())
|
||||
Gtk.main_iteration ();
|
||||
if (response == ResponseType.OK) {
|
||||
HashTable<string,string> new_conf = new HashTable<string,string> (str_hash, str_equal);
|
||||
enable_aur = preferences_dialog.enable_aur_button.get_active ();
|
||||
recurse = preferences_dialog.remove_unrequired_deps_button.get_active ();
|
||||
refresh_period = (uint64) preferences_dialog.refresh_period_spin_button.get_value ();
|
||||
if (enable_aur != pamac_config.enable_aur) {
|
||||
new_conf.insert ("EnableAUR", enable_aur.to_string ());
|
||||
}
|
||||
if (recurse != pamac_config.recurse)
|
||||
new_conf.insert ("RemoveUnrequiredDeps", recurse.to_string ());
|
||||
if (refresh_period != pamac_config.refresh_period)
|
||||
new_conf.insert ("RefreshPeriod", refresh_period.to_string ());
|
||||
if (new_conf.size () != 0) {
|
||||
transaction.write_config (new_conf);
|
||||
pamac_config.reload ();
|
||||
set_updates_list.begin ();
|
||||
}
|
||||
}
|
||||
preferences_dialog.hide ();
|
||||
while (Gtk.events_pending ())
|
||||
Gtk.main_iteration ();
|
||||
}
|
||||
|
||||
[GtkCallback]
|
||||
public void on_apply_button_clicked () {
|
||||
this.get_window ().set_cursor (new Gdk.Cursor (Gdk.CursorType.WATCH));
|
||||
while (Gtk.events_pending ())
|
||||
Gtk.main_iteration ();
|
||||
transaction.sysupgrade (0);
|
||||
}
|
||||
|
||||
[GtkCallback]
|
||||
public void on_refresh_button_clicked () {
|
||||
this.get_window ().set_cursor (new Gdk.Cursor (Gdk.CursorType.WATCH));
|
||||
while (Gtk.events_pending ())
|
||||
Gtk.main_iteration ();
|
||||
transaction.refresh (0);
|
||||
}
|
||||
|
||||
[GtkCallback]
|
||||
public void on_close_button_clicked () {
|
||||
this.application.quit ();
|
||||
}
|
||||
|
||||
public void on_emit_trans_finished (bool error) {
|
||||
set_updates_list.begin ();
|
||||
}
|
||||
|
||||
public async void set_updates_list () {
|
||||
TreeIter iter;
|
||||
string name;
|
||||
string size;
|
||||
uint64 dsize = 0;
|
||||
uint updates_nb = 0;
|
||||
this.get_window ().set_cursor (new Gdk.Cursor (Gdk.CursorType.WATCH));
|
||||
while (Gtk.events_pending ())
|
||||
Gtk.main_iteration ();
|
||||
top_label.set_markup ("");
|
||||
updates_list.clear ();
|
||||
// get syncfirst updates
|
||||
UpdatesInfos[] syncfirst_updates = get_syncfirst_updates (transaction.handle, transaction.syncfirst);
|
||||
if (syncfirst_updates.length != 0) {
|
||||
updates_nb = syncfirst_updates.length;
|
||||
foreach (UpdatesInfos infos in syncfirst_updates) {
|
||||
name = infos.name + " " + infos.version;
|
||||
if (infos.download_size != 0)
|
||||
size = format_size (infos.download_size);
|
||||
else
|
||||
size = "";
|
||||
dsize += infos.download_size;
|
||||
updates_list.insert_with_values (out iter, -1, 0, name, 1, size);
|
||||
}
|
||||
} else {
|
||||
while (Gtk.events_pending ())
|
||||
Gtk.main_iteration ();
|
||||
UpdatesInfos[] updates = get_repos_updates (transaction.handle, transaction.ignorepkg);
|
||||
foreach (UpdatesInfos infos in updates) {
|
||||
name = infos.name + " " + infos.version;
|
||||
if (infos.download_size != 0)
|
||||
size = format_size (infos.download_size);
|
||||
else
|
||||
size = "";
|
||||
dsize += infos.download_size;
|
||||
updates_list.insert_with_values (out iter, -1, 0, name, 1, size);
|
||||
}
|
||||
updates_nb += updates.length;
|
||||
if (pamac_config.enable_aur) {
|
||||
UpdatesInfos[] aur_updates = get_aur_updates (transaction.handle, transaction.ignorepkg);
|
||||
updates_nb += aur_updates.length;
|
||||
foreach (UpdatesInfos infos in aur_updates) {
|
||||
name = infos.name + " " + infos.version;
|
||||
if (infos.download_size != 0)
|
||||
size = format_size (infos.download_size);
|
||||
else
|
||||
size = "";
|
||||
dsize += infos.download_size;
|
||||
updates_list.insert_with_values (out iter, -1, 0, name, 1, size);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (updates_nb == 0) {
|
||||
top_label.set_markup("<b>%s</b>".printf (dgettext (null, "Your system is up-to-date")));
|
||||
apply_button.set_sensitive (false);
|
||||
} else {
|
||||
top_label.set_markup("<b>%s</b>".printf (dngettext (null, "%u available update", "%u available updates", updates_nb).printf (updates_nb)));
|
||||
apply_button.set_sensitive (true);
|
||||
}
|
||||
if (dsize != 0) {
|
||||
bottom_label.set_markup("<b>%s: %s</b>".printf (dgettext (null, "Total download size"), format_size(dsize)));
|
||||
bottom_label.set_visible (true);
|
||||
} else
|
||||
bottom_label.set_visible (false);
|
||||
|
||||
this.get_window ().set_cursor (null);
|
||||
while (Gtk.events_pending ())
|
||||
Gtk.main_iteration ();
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user