Compare commits

..

No commits in common. "2d8ae68d03b35d4378056a1600bb5e04acc9f24f" and "62bd1157b5610fd9eb45342b0f44b5410766c58e" have entirely different histories.

11 changed files with 171 additions and 227 deletions

View file

@ -1,60 +1,50 @@
# Qasim (القاسم)
[![Travis-CI](https://api.travis-ci.org/glenux/qasim.png?branch=master)](https://travis-ci.org/glenux/qasim) [![Code Climate](https://codeclimate.com/github/glenux/qasim/badges/gpa.svg)](https://codeclimate.com/github/glenux/qasim)
Qasim (القاسم)
==============
Qasim is a tool born to make your remote shares easily available from the system
tray, on your desktop !
It uses the FUSE filesystem, thus everything gets accessible both on graphical environments and under
command-line shell, on your favorite operating system (Linux, Windows, MacOsX, etc).
It uses FUSE filesystems, thus everything remains accessible even under
command-line shell, under your favorite operating system (Linux, Windows,
MacOsX).
## Requirements
Requirements
------------
Qasim require the `qtbindings` gems. It installs automatically along Qasim's
Qasim require the ``qtbindings`` gems. It installs automatically along qasim's
installation, but is quite long to build a native gem package.
__N.B :__ If you experience trouble with Qasim dues to Qt bindings, make sure
your Ruby installation was compiled with the `--enable-shared` option. If it was not, then reinstall it with the right arguments.
**N.B :** If you experience trouble with Qasim dues to Qt bindings, make sure
your Ruby installation was compiled with the ``--enable-shared`` option.
As an example, for ruby 1.9.3-p392 with rbenv :
If it was not, then reinstall it (let's say version 1.9.3-p392) with with :
$ CONFIGURE_OPTS="--enable-shared" rbenv install 1.9.3-p392
For others versions of ruby with rbenv you can try :
$ CONFIGURE_OPTS="--enable-shared" rbenv install $(rbenv version |awk '{ print $1; }')
Installation
------------
## Installation
To install Qasim, type the following command :
Simply run :
$ gem install qasim
## Usage
Usage
-----
Qasim two tools : the CLI, for command-line environments, and the GUI, for desktop environments.
Qasim provide two tools the CLI and the GUI.
### Using the CLI
To run the CLI, type :
$ qasim-cli command [options]
### Using the GUI
To run the GUI, type :
To run the GUI :
$ qasim-gui
Then Qasim icon (![quasim system tray](data/icons/qasim.32.png)) appears in your system tray. Click on that icon to mount your filesystems, change your preferences, etc.
Then click on the icon red-yellow-blue icon in the system tray.
## Contributing
Contributing
------------
1. Fork it ( http://github.com/glenux/qasim/fork )
2. Create your feature branch (`git checkout -b my-new-feature`)
@ -63,9 +53,10 @@ Then Qasim icon (![quasim system tray](data/icons/qasim.32.png)) appears in your
5. Create new Pull Request
## Copyright & License
Copyright & License
-------------------
Copyright (C) 2010-2017 Glenn Y. Rolland
Copyright (C) 2010-2014 Glenn Y. Rolland
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
@ -81,9 +72,8 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
## Alternatives
If Qasim does not suit your needs, you can try these tools :
Alternatives
------------
* [Mountoid](http://kde-apps.org/content/show.php/Mountoid?content=115943)
* [Xsshfs](http://david.mercereau.info/motclef/xsshfs/)

View file

@ -12,3 +12,11 @@ require 'qasim/config'
require 'qasim/map'
require 'qasim/map_manager'
## Plugins for maps
require 'qasim/map/generic'
require 'qasim/map/smb'
require 'qasim/map/ssh'
require 'qasim/map/webdav'

View file

@ -2,7 +2,10 @@ require 'qasim/qasim_qrc'
require 'qasim/ui'
module Qasim
class QasimApp ; end
class QasimApp
def initialize
end
end
class QasimGui < QasimApp
@ -55,15 +58,13 @@ module Qasim
previous_host = nil
@map_manager.sort do |mx,my|
mx.name <=> my.name
mx.host <=> my.host
end.each do |map|
#if map.host != previous_host and not previous_host.nil? then
# @map_menu.addSeparator
#end
if map.host != previous_host and not previous_host.nil? then
@map_menu.addSeparator
end
itemx = Qt::Action.new(map.name, @map_menu)
itemx.setCheckable true;
#puts "Loading #{map.inspect}"
if map.mounted? then
itemx.setChecked true
end
@ -71,7 +72,7 @@ module Qasim
action_trigger_map_item map, itemx
end
@map_menu.addAction itemx;
#previous_host = map.name
previous_host = map.host
end
end
@ -79,8 +80,8 @@ module Qasim
# Action when map item triggered
#
def action_trigger_map_item map, item
@connect_error[map.filename] = Set.new
@connect_running[map.filename] = 0
@connect_error[map.path] = Set.new
@connect_running[map.path] = 0
method = if map.mounted? then :umount
else :mount
end
@ -90,14 +91,14 @@ module Qasim
process = Qt::Process.new
process.connect(SIGNAL('finished(int, QProcess::ExitStatus)')) do |exitcode,exitstatus|
#puts "exitcode = %s, exitstatus = %s" % [exitcode, exitstatus]
@connect_running[map.filename] -= 1
@connect_running[map.path] -= 1
if exitcode != 0 then
@connect_error[map.filename].add linkname
@connect_error[map.path].add linkname
else
end
if @connect_running[map.filename] == 0 then
if @connect_running[map.path] == 0 then
# display someting
if @connect_error[map.filename].empty? then
if @connect_error[map.path].empty? then
dbus_notify "%s (%s)" % [APP_NAME, map.name],
("<b>Map %sed successfully<b>" % method.to_s),

View file

@ -1,7 +1,6 @@
require 'fileutils'
require 'qasim/map/generic'
require 'qasim/map/smb'
require 'qasim/map/ssh'
require 'qasim/map/webdav'
@ -13,9 +12,7 @@ module Qasim ; module Map
def class_for type
plugin = nil
ObjectSpace.each_object(Class) do |cls|
if cls < Qasim::Map::Generic then
puts "Searching #{type} in " + cls.handles.inspect
plugin = cls if cls.handles.include? type.to_sym
end
end

View file

@ -8,7 +8,8 @@ module Qasim ; module Map; class Generic
attr_reader :name
def initialize app_config, params
@app_config = app_config
@app_config = app_config
@links = params[:links]
params.delete :links
@ -25,106 +26,13 @@ module Qasim ; module Map; class Generic
# Format :
# Hash of (name:Symbol * [value:Object, optional:Boolean])
def self.parameters
return {
{
map_name: [nil , true],
map_enable: [true, false],
map_mountpoint: [nil, true]
}
end
#
# Test if mount list include some path & fs type
#
def mount_include? fs_type, local_path
f = File.open("/proc/mounts")
fs_mounts = (f.readlines.select do |line|
line =~ /\s+#{fs_type}\s+/
end).map do |line|
line.split(/\s+/)[1]
end
f.close
fs_mounts.include? local_path
end
#
# Test if map is connected / mounted
#
def mounted?
score = @links.size
@links.each do |name, remotepath|
local_path = File.join @app_config.mount_dir, name
if mount_include?(self.mount_id, local_path) then
score -= 1
end
end
# FIXME: handle the case of partial mounts (for remount/umount)
return true if score == 0
return false
end
#
# Connect all maps
#
def mount &block
@links.each do |name, remotepath|
mount_link(name, remotepath)
if block_given? then
yield name, cmd, cmd_args
else
system cmd, cmd_args
if $?.exitstatus != 0 then
raise ConnectError, self
end
end
end
end
#
# Disconnect all maps
#
def umount &block
@links.each do |name, remotepath|
localpath = File.join ENV['HOME'], "mnt", name
cmd = "fusermount"
cmd_args = [
"-u", #umount
"-z" ,#lazy
localpath ]
if block_given? then
yield name, cmd, cmd_args
else
system cmd, cmd_args
if $?.exitstatus != 0 then
raise ConnectError, self
end
end
end
end
#
# Connect a single map
#
# MUST BE IMPLEMENTED BY SUBCLASSES
#
def mount_link name, remotepath
raise NotImplementedError
end
#
# Return the name of fuse helper (show in mount list)
#
# MUST BE IMPLEMENTED BY SUBCLASSES
#
def mount_id
raise NotImplementedError
end
#
# Test map liveness (connected & working)
#
@ -133,4 +41,31 @@ module Qasim ; module Map; class Generic
def alive?
raise NotImplementedError
end
#
# Test map
#
# MUST BE IMPLEMENTED BY SUBCLASSES
#
def mounted?
raise NotImplementedError
end
#
# Mount
#
# MUST BE IMPLEMENTED BY SUBCLASSES
#
def mount
raise NotImplementedError
end
#
# Umount
#
# MUST BE IMPLEMENTED BY SUBCLASSES
#
def umount
raise NotImplementedError
end
end ; end ; end

View file

@ -3,7 +3,7 @@
require 'fileutils'
require 'qasim/map/generic'
module Qasim; module Map; class Samba < Qasim::Map::Generic
module Qasim; module Map; class Webdav < Qasim::Map::Generic
def initialize *opts
super
end
@ -16,38 +16,7 @@ module Qasim; module Map; class Samba < Qasim::Map::Generic
end
def self.handles
return [ :samba, :cifs, :smb ]
[ :samba, :cifs, :smb ]
end
def mount_id
return "fuse.fusesmb"
end
def mount_link name, remotepath
localpath = File.join ENV['HOME'], "mnt", name
FileUtils.mkdir_p localpath
cmd = "sshfs"
cmd_args = [
"-o","allow_root" ,
"-o","idmap=user" ,
"-o","uid=%s" % Process.uid,
"-o","gid=%s" % Process.gid,
"-o","reconnect", # auto-reconnection
"-o","workaround=all",
"-o","cache_timeout=900", # 15 min cache for files
"-o","cache_stat_timeout=1800", # 30 min cache for directories
"-o","cache_link_timeout=1800", # 30 min cache for links
"-o","attr_timeout=1800", # 30 min attr cache
"-o","entry_timeout=1800", # 30 min entry cache
"-o","ServerAliveInterval=15", # prevent I/O hang
"-o","ServerAliveCountMax=3", # prevent I/O hang
"-o","no_readahead",
#"-o","Ciphers=arcfour", # force cypher
"-o","Port=%s" % @params[:ssh_port],
"%s@%s:%s" % [@params[:ssh_user],@params[:ssh_host],remotepath],
localpath ]
STDERR.puts cmd + ' ' + cmd_args.join(' ')
end
end ; end ; end

View file

@ -29,7 +29,7 @@ module Qasim ; module Map ; class Ssh < Qasim::Map::Generic
end
def self.handles
return [ :ssh, :sshfs ]
[ :ssh, :sshfs ]
end
#
@ -39,44 +39,96 @@ module Qasim ; module Map ; class Ssh < Qasim::Map::Generic
super
end
def mount_id
return "fuse.sshfs"
def mount_include? fs_type, local_path
f = File.open("/proc/mounts")
fs_mounts = (f.readlines.select do |line|
line =~ /\s+#{fs_type}\s+/
end).map do |line|
line.split(/\s+/)[1]
end
f.close
fs_mounts.include? local_path
end
#
# Connect single map
# Test if map is connected / mounted
#
# FIXME: test connexion with Net::SSH + timeout or ask password
def mount_link name, remotepath
localpath = File.join ENV['HOME'], "mnt", name
FileUtils.mkdir_p localpath
cmd = "sshfs"
cmd_args = [
"-o","allow_root" ,
"-o","idmap=user" ,
"-o","uid=%s" % Process.uid,
"-o","gid=%s" % Process.gid,
"-o","reconnect", # auto-reconnection
"-o","workaround=all",
"-o","cache_timeout=900", # 15 min cache for files
"-o","cache_stat_timeout=1800", # 30 min cache for directories
"-o","cache_link_timeout=1800", # 30 min cache for links
"-o","attr_timeout=1800", # 30 min attr cache
"-o","entry_timeout=1800", # 30 min entry cache
"-o","ServerAliveInterval=15", # prevent I/O hang
"-o","ServerAliveCountMax=3", # prevent I/O hang
"-o","no_readahead",
#"-o","Ciphers=arcfour", # force cypher
"-o","Port=%s" % @params[:ssh_port],
"%s@%s:%s" % [@params[:ssh_user],@params[:ssh_host],remotepath],
localpath ]
STDERR.puts cmd + ' ' + cmd_args.join(' ')
end
def mounted?
score = @links.size
@links.each do |name, remotepath|
local_path = File.join @app_config.mount_dir, name
if mount_include?("fuse.sshfs", local_path) then
score -= 1
end
end
# FIXME: handle the case of partial mounts (for remount/umount)
return true if score == 0
return false
end
#
# Connect map
#
def mount &block
# FIXME: test connexion with Net::SSH + timeout or ask password
@links.each do |name, remotepath|
localpath = File.join ENV['HOME'], "mnt", name
FileUtils.mkdir_p localpath
cmd = "sshfs"
cmd_args = [
"-o","allow_root" ,
"-o","idmap=user" ,
"-o","uid=%s" % Process.uid,
"-o","gid=%s" % Process.gid,
"-o","reconnect", # auto-reconnection
"-o","workaround=all",
"-o","cache_timeout=900", # 15 min cache for files
"-o","cache_stat_timeout=1800", # 30 min cache for directories
"-o","cache_link_timeout=1800", # 30 min cache for links
"-o","attr_timeout=1800", # 30 min attr cache
"-o","entry_timeout=1800", # 30 min entry cache
"-o","ServerAliveInterval=15", # prevent I/O hang
"-o","ServerAliveCountMax=3", # prevent I/O hang
"-o","no_readahead",
#"-o","Ciphers=arcfour", # force cypher
"-o","Port=%s" % @params[:ssh_port],
"%s@%s:%s" % [@params[:ssh_user],@params[:ssh_host],remotepath],
localpath ]
STDERR.puts cmd + ' ' + cmd_args.join(' ')
if block_given? then
yield name, cmd, cmd_args
else
system cmd, cmd_args
if $?.exitstatus != 0 then
raise ConnectError, self
end
end
end
end
#
# Disconnect map
#
def umount &block
@links.each do |name, remotepath|
localpath = File.join ENV['HOME'], "mnt", name
cmd = "fusermount"
cmd_args = [
"-u", #umount
"-z" ,#lazy
localpath ]
if block_given? then
yield name, cmd, cmd_args
else
system cmd, cmd_args
if $?.exitstatus != 0 then
raise ConnectError, self
end
end
end
end
end ; end ; end

View file

@ -10,23 +10,16 @@ module Qasim; module Map; class Webdav < Qasim::Map::Generic
def self.parameters
super.merge({
webdav_host: { required: true}, # ex : http, https
webdav_user: { required: true}, # ex : foo
webdav_password: { required: true}, # ex : bar
webdav_port: { default: 80}, # ex : 80, 8080, 443
webdav_protocol: { default: :http}, # ex : http, https
webdav_path: { default: '/'} # ex : http, https
webdav_protocol: { default: :http} # ex : http, https
})
end
def self.handles
return [ :webdav, :webdavs ]
[ :webdav, :webdavs ]
end
def mount_id
return "fuse.fusedav"
end
end ; end ; end

View file

@ -23,12 +23,12 @@ Gem::Specification.new do |spec|
.concat(Dir['*/**/*_ui.rb'])
.concat(Dir['*/**/*_qrc.rb'])
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
spec.require_paths = ["lib"]
spec.add_development_dependency "bundler"
spec.add_development_dependency "rake"
spec.add_development_dependency "bundler", "~> 1.5"
spec.add_development_dependency "rake", "~> 10.4.2"
spec.add_development_dependency "minitest", "~> 5.7.0"
spec.add_development_dependency "minitest-reporters"
spec.add_development_dependency "pry", "~> 0.10.1"
@ -39,7 +39,6 @@ Gem::Specification.new do |spec|
spec.add_development_dependency "terminal-notifier-guard"
#spec.add_runtime_dependency "qtbindings", "~> 4.8.6"
spec.add_runtime_dependency "qml"
spec.add_runtime_dependency "qtbindings", "~> 4.8.6"
spec.add_runtime_dependency "thor", "~> 0.19.1"
end