3
# Copyright 2008 Evenflow, Inc.
6
# Dropbox frontend script
7
# This file is part of nautilus-dropbox @PACKAGE_VERSION@.
9
# nautilus-dropbox is free software: you can redistribute it and/or modify
10
# it under the terms of the GNU General Public License as published by
11
# the Free Software Foundation, either version 3 of the License, or
12
# (at your option) any later version.
14
# nautilus-dropbox is distributed in the hope that it will be useful,
15
# but WITHOUT ANY WARRANTY; without even the implied warranty of
16
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
# GNU General Public License for more details.
19
# You should have received a copy of the GNU General Public License
20
# along with nautilus-dropbox. If not, see <http://www.gnu.org/licenses/>.
22
from __future__ import with_statement
38
from contextlib import closing
39
from posixpath import curdir, sep, pardir, join, abspath, commonprefix
41
INFO = u"Dropbox is the easiest way to share and store your files online. Want to learn more? Head to"
42
LINK = u"http://www.dropbox.com/"
43
WARNING = u"In order to use Dropbox, you must download the proprietary daemon."
45
DOWNLOADING = u"Downloading Dropbox... %d%%"
46
UNPACKING = u"Unpacking Dropbox... %d%%"
48
PARENT_DIR = os.path.expanduser("/var/lib/dropbox")
49
DROPBOXD_PATH = "%s/.dropbox-dist/dropboxd" % PARENT_DIR
51
enc = locale.getpreferredencoding()
55
def methodcaller(name, *args, **kwargs):
57
return getattr(obj, name)(*args, **kwargs)
60
def relpath(path, start=curdir):
61
"""Return a relative version of a path"""
64
raise ValueError("no path specified")
66
if type(start) is unicode:
67
start_list = unicode_abspath(start).split(sep)
69
start_list = abspath(start).split(sep)
71
if type(path) is unicode:
72
path_list = unicode_abspath(path).split(sep)
74
path_list = abspath(path).split(sep)
76
# Work out how much of the filepath is shared by start and path.
77
i = len(commonprefix([start_list, path_list]))
79
rel_list = [pardir] * (len(start_list)-i) + path_list[i:]
82
return join(*rel_list)
87
def console_print(st=u"", f=sys.stdout, linebreak=True):
89
assert type(st) is unicode
90
f.write(st.encode(enc))
91
if linebreak: f.write(os.linesep)
93
def console_flush(f=sys.stdout):
96
def yes_no_question(question):
98
console_print(question, linebreak=False)
99
console_print(u" [y/n] ", linebreak=False)
102
if text.lower().startswith("y"):
104
elif text.lower().startswith("n"):
107
console_print(u"Sorry, I didn't understand that. Please type yes or no.")
110
if sys.platform.lower().startswith('linux'):
111
arch = subprocess.Popen(["dpkg", "--print-architecture"],
112
stdout=subprocess.PIPE).communicate()[0]
113
arch = arch.rstrip("\n")
116
elif arch == "amd64":
119
FatalVisibleError("Platform not supported")
120
return "lnx.%s" % plat
122
FatalVisibleError("Platform not supported")
124
def is_dropbox_running():
125
pidfile = os.path.expanduser("~/.dropbox/dropbox.pid")
128
with open(pidfile, "r") as f:
130
with open("/proc/%d/cmdline" % pid, "r") as f:
131
cmdline = f.read().lower()
135
return "dropbox" in cmdline
137
def unicode_abspath(path):
139
assert type(path) is unicode
140
# shouldn't pass unicode to this craphead, it appends with os.getcwd() which is always a str
141
return os.path.abspath(path.encode(sys.getfilesystemencoding())).decode(sys.getfilesystemencoding())
143
# This sets a custom User-Agent
144
class DropboxURLopener(urllib.FancyURLopener):
145
version = "DropboxLinuxDownloader/@PACKAGE_VERSION@"
146
urllib._urlopener = DropboxURLopener()
148
class DownloadState(object):
151
self.file = urllib.urlopen("http://www.dropbox.com/download?plat=%s" % plat())
153
FatalVisibleError("Trouble connecting to Dropbox servers. Maybe your internet connection is down, or you need to set your http_proxy environment variable.")
155
fcntl.fcntl(self.file, fcntl.F_SETFL, os.O_NONBLOCK)
157
self.size = int(self.file.info()['content-length'])
160
self.local_path = "%s/dropbox.tar.gz" % PARENT_DIR
161
self.local_file = open(self.local_path, 'wb')
166
chunk = os.read(self.file.fileno(), 4096)
167
self.progress += len(chunk)
168
self.local_file.write(chunk)
170
if self.progress == self.size:
173
if hasattr(e, 'errno') and e.errno == errno.EAGAIN:
174
# nothing left to read
182
self.local_file.close()
183
archive = tarfile.open(self.local_path, 'r:gz')
184
total_members = len(archive.getmembers())
185
for i, member in enumerate(archive.getmembers()):
186
archive.extract(member, PARENT_DIR)
187
yield member.name, i, total_members
189
os.remove(self.local_path)
192
if not self.local_file.closed:
193
self.local_file.close()
194
if os.path.exists(self.local_path):
195
os.remove(self.local_path)
197
def load_serialized_images():
198
global box_logo_pixbuf, window_icon
200
box_logo_pixbuf = @IMAGEDATA64@
201
window_icon = @IMAGEDATA16@
203
GUI_AVAILABLE = os.environ.get("DISPLAY", '')
214
load_serialized_images()
216
global FatalVisibleError
217
def FatalVisibleError(s):
218
error = gtk.MessageDialog(parent = None,
219
flags = gtk.DIALOG_MODAL,
220
type = gtk.MESSAGE_ERROR,
221
buttons = gtk.BUTTONS_OK,
223
error.set_title("Error")
228
def gtk_flush_events():
229
while gtk.events_pending():
232
class DownloadDialog(gtk.Dialog):
233
def handle_delete_event(self, wid, ev, data=None):
234
self.handle_cancel(wid)
236
def handle_dont_show_toggle(self, button, data=None):
237
reroll_autostart(not button.get_active())
239
def handle_cancel(self, button):
241
gobject.source_remove(self.watch)
243
self.download.cancel()
245
self.user_cancelled = True
247
def handle_ok(self, button):
250
self.download = DownloadState()
251
self.one_chunk = self.download.copy_data()
252
self.watch = gobject.io_add_watch(self.download.file,
257
self.handle_data_waiting)
259
self.dont_show_again_align.hide()
262
def update_progress(self, text, fraction):
263
self.progress.set_text(text % int(fraction*100))
264
self.progress.set_fraction(fraction)
267
def handle_data_waiting(self, fd, condition):
268
if condition == gobject.IO_HUP:
269
FatalVisibleError("Connection to server unexpectedly closed.")
270
elif condition == gobject.IO_ERR:
271
FatalVisibleError("Unexpected error occurred with download.")
273
while self.one_chunk.next():
274
self.update_progress(DOWNLOADING, float(self.download.progress)/self.download.size)
275
except StopIteration:
276
self.update_progress(DOWNLOADING, 1.0)
277
self.unpack_dropbox()
280
self.update_progress(DOWNLOADING, float(self.download.progress)/self.download.size)
283
def unpack_dropbox(self):
284
one_member = self.download.unpack()
287
name, i, total = one_member.next()
288
self.update_progress(UNPACKING, float(i)/total)
289
except StopIteration:
290
self.update_progress(UNPACKING, 1.0)
293
def mouse_down(self, widget, event):
295
self.clicked_link = True
297
def mouse_up(self, widget, event):
298
if self.clicked_link:
299
webbrowser.open(LINK)
300
self.clicked_link = False
302
def label_motion(self, widget, event):
303
offx, offy = self.label.get_layout_offsets()
304
layout = self.label.get_layout()
305
index = layout.xy_to_index(int((offx+event.x)*pango.SCALE),
306
int((offy+event.y)*pango.SCALE))[0]
307
link_index = layout.get_text().find(LINK)
308
if index >= link_index and index < link_index+len(LINK):
310
self.label_box.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.HAND2))
312
self.hovering = False
313
self.label_box.window.set_cursor(gtk.gdk.Cursor(gtk.gdk.ARROW))
317
super(DownloadDialog, self).__init__(parent = None,
318
title = "Dropbox Installation")
322
self.hovering = False
323
self.clicked_link = False
324
self.user_cancelled = False
326
self.ok = ok = gtk.Button(stock=gtk.STOCK_OK)
327
ok.connect('clicked', self.handle_ok)
328
self.action_area.add(ok)
331
cancel = gtk.Button(stock=gtk.STOCK_CANCEL)
332
cancel.connect('clicked', self.handle_cancel)
333
self.action_area.add(cancel)
336
self.connect('delete_event', self.handle_delete_event)
338
self.box_logo = gtk.image_new_from_pixbuf(box_logo_pixbuf)
341
self.set_icon(window_icon)
343
self.progress = gtk.ProgressBar()
344
self.progress.set_property('width-request', 300)
346
self.label = gtk.Label()
347
self.label.set_markup('%s <span foreground="#000099" underline="single" weight="bold">%s</span>\n\n%s' % (INFO, LINK, WARNING))
348
self.label.set_line_wrap(True)
349
self.label.set_property('width-request', 300)
352
self.label_box = gtk.EventBox()
353
self.label_box.add(self.label)
354
self.label_box.connect("button-release-event", self.mouse_up)
355
self.label_box.connect("button-press-event", self.mouse_down)
356
self.label_box.connect("motion-notify-event", self.label_motion)
358
self.label_box.show()
359
def on_realize(widget):
360
self.label_box.add_events(gtk.gdk.POINTER_MOTION_MASK)
361
self.label_box.connect("realize", on_realize)
363
self.hbox = gtk.HBox(spacing=10)
364
self.hbox.set_property('border-width',10)
365
self.hbox.pack_start(self.box_logo, False, False)
366
self.hbox.pack_start(self.label_box, False, False)
367
self.hbox.pack_start(self.progress, False, False)
370
self.vbox.add(self.hbox)
373
if can_reroll_autostart():
374
dont_show_again = gtk.CheckButton("_Don't show this again")
375
dont_show_again.connect('toggled', self.handle_dont_show_toggle)
376
dont_show_again.show()
378
self.dont_show_again_align = gtk.Alignment(xalign=1.0, yalign=0.0, xscale=0.0, yscale=0.0)
379
self.dont_show_again_align.add(dont_show_again)
380
self.dont_show_again_align.show()
383
hbox.set_property('border-width', 10)
384
hbox.pack_start(self.dont_show_again_align, True, True)
389
self.set_resizable(False)
392
traceback.print_exc()
396
dialog = DownloadDialog()
399
if dialog.user_cancelled:
400
raise Exception("user cancelled download!!!")
403
global FatalVisibleError
404
def FatalVisibleError(s):
405
console_print(u"\nError: %s" % s, f=sys.stderr)
413
erase_to_start = ESC+"[1K"
414
write = sys.stdout.write
415
flush = sys.stdout.flush
417
last_progress = [None, None]
418
def setprogress(text, frac):
419
if last_progress == [text, frac]:
421
if sys.stdout.isatty():
422
write(erase_to_start)
424
console_print(text % int(100*frac), linebreak=not sys.stdout.isatty())
425
if sys.stdout.isatty():
427
last_progress[0], last_progress[1] = text, frac
430
if sys.stdout.isatty():
433
console_print(u"%s %s\n" % (INFO, LINK))
435
download = DownloadState()
436
one_chunk = download.copy_data()
441
setprogress(DOWNLOADING, float(download.progress)/download.size)
442
except StopIteration:
443
setprogress(DOWNLOADING, 1.0)
447
one_member = download.unpack()
451
name, i, total = one_member.next()
452
setprogress(UNPACKING, float(i)/total)
453
except StopIteration:
454
setprogress(UNPACKING, 1.0)
458
class CommandTicker(threading.Thread):
460
threading.Thread.__init__(self)
461
self.stop_event = threading.Event()
464
self.stop_event.set()
467
ticks = ['[. ]', '[.. ]', '[...]', '[ ..]', '[ .]', '[ ]']
471
self.stop_event.wait(0.25)
472
if self.stop_event.isSet(): break
477
sys.stderr.write("\r%s\r" % ticks[i])
483
class DropboxCommand(object):
484
class CouldntConnectError(Exception): pass
485
class BadConnectionError(Exception): pass
486
class EOFError(Exception): pass
487
class CommandError(Exception): pass
489
def __init__(self, timeout=5):
490
self.s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
491
self.s.settimeout(timeout)
493
self.s.connect(os.path.expanduser(u'~/.dropbox/command_socket'))
494
except socket.error, e:
495
raise DropboxCommand.CouldntConnectError()
496
self.f = self.s.makefile("r+", 4096)
502
def __readline(self):
504
toret = self.f.readline().decode('utf8').rstrip(u"\n")
505
except socket.error, e:
506
raise DropboxCommand.BadConnectionError()
508
raise DropboxCommand.EOFError()
512
# atttribute doesn't exist, i know what you want
513
def send_command(self, name, args):
514
self.f.write(name.encode('utf8'))
515
self.f.write(u"\n".encode('utf8'))
516
self.f.writelines((u"\t".join([k] + (list(v)
517
if hasattr(v, '__iter__') else
518
[v])) + u"\n").encode('utf8')
519
for k,v in args.iteritems())
520
self.f.write(u"done\n".encode('utf8'))
525
ticker_thread = CommandTicker()
526
ticker_thread.start()
528
# This is the potentially long-running call.
530
ok = self.__readline() == u"ok"
531
except KeyboardInterrupt:
532
raise DropboxCommand.BadConnectionError("Keyboard interruption detected")
534
# Tell the ticker to stop.
542
raise Exception(u"close this connection!")
544
line = self.__readline()
548
argval = line.split(u"\t")
549
toret[argval[0]] = argval[1:]
556
raise Exception(u"close this connection!")
558
line = self.__readline()
562
problems.append(line)
564
raise DropboxCommand.CommandError(u"\n".join(problems))
566
# this is the hotness, auto marshalling
567
def __getattr__(self, name):
569
return super(DropboxCommand, self).__getattr__(name)
571
def __spec_command(**kw):
572
return self.send_command(unicode(name), kw)
573
self.__setattr__(name, __spec_command)
574
return __spec_command
580
global commands, aliases
581
assert meth.__doc__, "All commands need properly formatted docstrings (even %r!!)" % meth
582
if hasattr(meth, 'im_func'): # bound method, if we ever have one
584
commands[meth.func_name] = meth
585
meth_aliases = [unicode(alias) for alias in aliases.iterkeys() if aliases[alias].func_name == meth.func_name]
587
meth.__doc__ += u"\nAliases: %s" % ",".join(meth_aliases)
592
global commands, aliases
593
assert name not in commands, "This alias is the name of a command."
598
def requires_dropbox_running(meth):
599
def newmeth(*n, **kw):
600
if is_dropbox_running():
601
return meth(*n, **kw)
603
console_print(u"Dropbox isn't running!")
604
newmeth.func_name = meth.func_name
605
newmeth.__doc__ = meth.__doc__
609
db_path = os.path.expanduser(DROPBOXD_PATH).encode(sys.getfilesystemencoding())
610
if os.access(db_path, os.X_OK):
611
f = open("/dev/null", "w")
612
# we don't reap the child because we're gonna die anyway, let init do it
613
a = subprocess.Popen([db_path], preexec_fn=os.setsid, cwd=os.path.expanduser("~"),
614
stderr=sys.stderr, stdout=f, close_fds=True)
619
for i in xrange(int(wait_for / interval)):
620
if is_dropbox_running():
622
# back off from connect for a while
629
# Extracted and modified from os.cmd.Cmd
630
def columnize(list, display_list=None, display_width=None):
632
console_print(u"<empty>")
635
non_unicode = [i for i in range(len(list)) if not (isinstance(list[i], unicode))]
637
raise TypeError, ("list[i] not a string for i in %s" %
638
", ".join(map(unicode, non_unicode)))
640
if not display_width:
641
d = os.popen('stty size', 'r').read().split()
643
display_width = int(d[1])
654
console_print(display_list[0])
657
for nrows in range(1, len(list)):
658
ncols = (size+nrows-1) // nrows
661
for col in range(ncols):
663
for row in range(nrows):
668
colwidth = max(colwidth, len(x))
669
colwidths.append(colwidth)
670
totwidth += colwidth + 2
671
if totwidth > display_width:
673
if totwidth <= display_width:
680
for row in range(nrows):
683
for col in range(ncols):
692
display_texts.append(y)
693
while texts and not texts[-1]:
695
original_texts = texts[:]
696
for col in range(len(texts)):
697
texts[col] = texts[col].ljust(colwidths[col])
698
line = u"%s" % " ".join(texts)
699
for i, text in enumerate(original_texts):
700
line = line.replace(text, display_texts[i])
707
u"""download latest version of dropbox
710
Downloads the latest version of dropbox.
715
@requires_dropbox_running
717
def filestatus(args):
718
u"""get current sync status of one or more files
719
dropbox filestatus [-l] [-a] [FILE]...
721
Prints the current status of each FILE.
724
-l --list prints out information in a format similar to ls. works best when your console supports color :)
725
-a --all do not ignore entries starting with .
729
oparser = optparse.OptionParser()
730
oparser.add_option("-l", "--list", action="store_true", dest="list")
731
oparser.add_option("-a", "--all", action="store_true", dest="all")
732
(options, args) = oparser.parse_args(args)
735
with closing(DropboxCommand()) as dc:
739
# Separate directories from files.
741
dirs, nondirs = [u"."], []
743
dirs, nondirs = [], []
747
(dirs if os.path.isdir(a) else nondirs).append(a.decode(enc))
748
except UnicodeDecodeError:
751
if len(dirs) == 0 and len(nondirs) == 0:
755
dirs.sort(key=methodcaller('lower'))
756
nondirs.sort(key=methodcaller('lower'))
758
# Gets a string representation for a path.
759
def path_to_string(file_path):
760
if not os.path.exists(file_path):
761
path = u"%s (File doesn't exist!)" % os.path.basename(file_path)
764
status = dc.icon_overlay_file_status(path=file_path).get(u'status', [None])[0]
765
except DropboxCommand.CommandError, e:
766
path = u"%s (%s)" % (os.path.basename(file_path), e)
769
env_term = os.environ.get('TERM','')
770
supports_color = (sys.stderr.isatty() and (
771
env_term.startswith('vt') or
772
env_term.startswith('linux') or
773
'xterm' in env_term or
778
# TODO: Test when you don't support color.
779
if not supports_color:
780
path = os.path.basename(file_path)
783
if status == u"up to date":
784
init, cleanup = "\x1b[32;1m", "\x1b[0m"
785
elif status == u"syncing":
786
init, cleanup = "\x1b[36;1m", "\x1b[0m"
787
elif status == u"unsyncable":
788
init, cleanup = "\x1b[41;1m", "\x1b[0m"
789
elif status == u"selsync":
790
init, cleanup = "\x1b[37;1m", "\x1b[0m"
792
init, cleanup = '', ''
794
path = os.path.basename(file_path)
795
return (path, u"%s%s%s" % (init, path, cleanup))
797
# Prints a directory.
798
def print_directory(name):
801
for subname in sorted(os.listdir(name), key=methodcaller('lower')):
802
if type(subname) != unicode:
805
if not options.all and subname[0] == u'.':
809
clean, formatted = path_to_string(unicode_abspath(os.path.join(name, subname)))
810
clean_paths.append(clean)
811
formatted_paths.append(formatted)
812
except (UnicodeEncodeError, UnicodeDecodeError), e:
815
columnize(clean_paths, formatted_paths)
818
if len(dirs) == 1 and len(nondirs) == 0:
819
print_directory(dirs[0])
821
nondir_formatted_paths = []
822
nondir_clean_paths = []
825
clean, formatted = path_to_string(unicode_abspath(name))
826
nondir_clean_paths.append(clean)
827
nondir_formatted_paths.append(formatted)
828
except (UnicodeEncodeError, UnicodeDecodeError), e:
831
if nondir_clean_paths:
832
columnize(nondir_clean_paths, nondir_formatted_paths)
834
if len(nondirs) == 0:
835
console_print(dirs[0] + u":")
836
print_directory(dirs[0])
841
console_print(name + u":")
842
print_directory(name)
844
except DropboxCommand.EOFError:
845
console_print(u"Dropbox daemon stopped.")
846
except DropboxCommand.BadConnectionError, e:
847
console_print(u"Dropbox isn't responding!")
850
args = [name for name in sorted(os.listdir(u"."), key=methodcaller('lower')) if type(name) == unicode]
851
indent = max(len(st)+1 for st in args)
855
if type(file) is not unicode:
856
file = file.decode(enc)
857
fp = unicode_abspath(file)
858
except (UnicodeEncodeError, UnicodeDecodeError), e:
860
if not os.path.exists(fp):
861
console_print(u"%-*s %s" % \
862
(indent, file+':', "File doesn't exist"))
866
status = dc.icon_overlay_file_status(path=fp).get(u'status', [u'unknown'])[0]
867
console_print(u"%-*s %s" % (indent, file+':', status))
868
except DropboxCommand.CommandError, e:
869
console_print(u"%-*s %s" % (indent, file+':', e))
870
except DropboxCommand.CouldntConnectError, e:
871
console_print(u"Dropbox isn't running!")
874
@requires_dropbox_running
876
u"""list directory contents with current sync status
879
This is an alias for filestatus -l
881
return filestatus(["-l"] + args)
884
@requires_dropbox_running
886
u"""get public url of a file in your dropbox
889
Prints out a public url for FILE.
892
console_print(puburl.__doc__,linebreak=False)
896
with closing(DropboxCommand()) as dc:
898
console_print(dc.get_public_link(path=unicode_abspath(args[0].decode(sys.getfilesystemencoding()))).get(u'link', [u'No Link'])[0])
899
except DropboxCommand.CommandError, e:
900
console_print(u"Couldn't get public url: " + str(e))
901
except DropboxCommand.BadConnectionError, e:
902
console_print(u"Dropbox isn't responding!")
903
except DropboxCommand.EOFError:
904
console_print(u"Dropbox daemon stopped.")
905
except DropboxCommand.CouldntConnectError, e:
906
console_print(u"Dropbox isn't running!")
909
@requires_dropbox_running
911
u"""get current status of the dropboxd
914
Prints out the current status of the Dropbox daemon.
917
console_print(status.__doc__,linebreak=False)
921
with closing(DropboxCommand()) as dc:
923
lines = dc.get_dropbox_status()[u'status']
925
console_print(u'Idle')
930
console_print(u"Couldn't get status: daemon isn't responding")
931
except DropboxCommand.CommandError, e:
932
console_print(u"Couldn't get status: " + str(e))
933
except DropboxCommand.BadConnectionError, e:
934
console_print(u"Dropbox isn't responding!")
935
except DropboxCommand.EOFError:
936
console_print(u"Dropbox daemon stopped.")
937
except DropboxCommand.CouldntConnectError, e:
938
console_print(u"Dropbox isn't running!")
942
u"""return whether dropbox is running
945
Returns 1 if running 0 if not running.
947
return int(is_dropbox_running())
950
@requires_dropbox_running
955
Stops the dropbox daemon.
958
with closing(DropboxCommand()) as dc:
960
dc.tray_action_hard_exit()
961
except DropboxCommand.BadConnectionError, e:
962
console_print(u"Dropbox isn't responding!")
963
except DropboxCommand.EOFError:
964
console_print(u"Dropbox daemon stopped.")
965
except DropboxCommand.CouldntConnectError, e:
966
console_print(u"Dropbox isn't running!")
968
#returns true if link is necessary
969
def grab_link_url_if_necessary():
971
with closing(DropboxCommand()) as dc:
973
link_url = dc.needs_link().get(u"link_url", None)
974
if link_url is not None:
975
console_print(u"To link this computer to a dropbox account, visit the following url:\n%s" % link_url[0])
979
except DropboxCommand.CommandError, e:
981
except DropboxCommand.BadConnectionError, e:
982
console_print(u"Dropbox isn't responding!")
983
except DropboxCommand.EOFError:
984
console_print(u"Dropbox daemon stopped.")
985
except DropboxCommand.CouldntConnectError, e:
986
console_print(u"Dropbox isn't running!")
989
@requires_dropbox_running
991
u"""ignores/excludes a directory from syncing
992
dropbox exclude [list]
993
dropbox exclude add [DIRECTORY] [DIRECTORY] ...
994
dropbox exclude remove [DIRECTORY] [DIRECTORY] ...
996
"list" prints a list of directories currently excluded from syncing.
997
"add" adds one or more directories to the exclusion list, then resynchronizes Dropbox.
998
"remove" removes one or more directories from the exclusion list, then resynchronizes Dropbox.
999
With no arguments, executes "list".
1000
Any specified path must be within Dropbox.
1004
with closing(DropboxCommand()) as dc:
1006
lines = [relpath(path) for path in dc.get_ignore_set()[u'ignore_set']]
1009
console_print(u'No directories are being ignored.')
1011
console_print(u'Excluded: ')
1013
console_print(unicode(line))
1015
console_print(u"Couldn't get ignore set: daemon isn't responding")
1016
except DropboxCommand.CommandError, e:
1017
if e.args[0].startswith(u"No command exists by that name"):
1018
console_print(u"This version of the client does not support this command.")
1020
console_print(u"Couldn't get ignore set: " + str(e))
1021
except DropboxCommand.BadConnectionError, e:
1022
console_print(u"Dropbox isn't responding!")
1023
except DropboxCommand.EOFError:
1024
console_print(u"Dropbox daemon stopped.")
1025
except DropboxCommand.CouldntConnectError, e:
1026
console_print(u"Dropbox isn't running!")
1027
elif len(args) == 1 and args[0] == u"list":
1029
elif len(args) >= 2:
1030
sub_command = args[0]
1032
absolute_paths = [unicode_abspath(path.decode(sys.getfilesystemencoding())) for path in paths]
1033
if sub_command == u"add":
1035
with closing(DropboxCommand(timeout=None)) as dc:
1037
result = dc.ignore_set_add(paths=absolute_paths)
1038
if result[u"ignored"]:
1039
console_print(u"Excluded: ")
1040
lines = [relpath(path) for path in result[u"ignored"]]
1042
console_print(unicode(line))
1044
console_print(u"Couldn't add ignore path: daemon isn't responding")
1045
except DropboxCommand.CommandError, e:
1046
if e.args[0].startswith(u"No command exists by that name"):
1047
console_print(u"This version of the client does not support this command.")
1049
console_print(u"Couldn't get ignore set: " + str(e))
1050
except DropboxCommand.BadConnectionError, e:
1051
console_print(u"Dropbox isn't responding! [%s]" % e)
1052
except DropboxCommand.EOFError:
1053
console_print(u"Dropbox daemon stopped.")
1054
except DropboxCommand.CouldntConnectError, e:
1055
console_print(u"Dropbox isn't running!")
1056
elif sub_command == u"remove":
1058
with closing(DropboxCommand(timeout=None)) as dc:
1060
result = dc.ignore_set_remove(paths=absolute_paths)
1061
if result[u"removed"]:
1062
console_print(u"No longer excluded: ")
1063
lines = [relpath(path) for path in result[u"removed"]]
1065
console_print(unicode(line))
1067
console_print(u"Couldn't remove ignore path: daemon isn't responding")
1068
except DropboxCommand.CommandError, e:
1069
if e.args[0].startswith(u"No command exists by that name"):
1070
console_print(u"This version of the client does not support this command.")
1072
console_print(u"Couldn't get ignore set: " + str(e))
1073
except DropboxCommand.BadConnectionError, e:
1074
console_print(u"Dropbox isn't responding! [%s]" % e)
1075
except DropboxCommand.EOFError:
1076
console_print(u"Dropbox daemon stopped.")
1077
except DropboxCommand.CouldntConnectError, e:
1078
console_print(u"Dropbox isn't running!")
1080
console_print(exclude.__doc__, linebreak=False)
1083
console_print(exclude.__doc__, linebreak=False)
1091
Starts the dropbox daemon, dropboxd. If dropboxd is already running, this will do nothing.
1094
-i --install auto install dropboxd if not available on the system
1097
should_install = "-i" in argv or "--install" in argv
1099
# first check if dropbox is already running
1100
if is_dropbox_running():
1101
if not grab_link_url_if_necessary():
1102
console_print(u"Dropbox is already running!")
1105
console_print(u"Starting Dropbox...", linebreak=False)
1107
if not start_dropbox():
1108
if not should_install:
1110
console_print(u"The Dropbox daemon is not installed!")
1111
console_print(u"Run \"dropbox start -i\" to install the daemon")
1114
# install dropbox!!!
1122
console_print(u"Done!")
1125
if not grab_link_url_if_necessary():
1126
console_print(u"Done!")
1128
if not grab_link_url_if_necessary():
1129
console_print(u"Done!")
1132
def can_reroll_autostart():
1133
return u".config" in os.listdir(os.path.expanduser(u'~'))
1135
def reroll_autostart(should_autostart):
1136
home_dir = os.path.expanduser(u'~')
1137
contents = os.listdir(home_dir)
1140
if u".config" in contents:
1141
autostart_dir = os.path.join(home_dir, u".config", u"autostart")
1142
autostart_link = os.path.join(autostart_dir, u"%s.desktop" % "dropbox") #BUILD_KEY.lower()
1143
desktop_file = u"/usr/share/applications/%s.desktop" % "dropbox" #BUILD_KEY.lower()
1144
if should_autostart:
1145
if os.path.exists(desktop_file):
1146
if not os.path.exists(autostart_dir):
1147
os.makedirs(autostart_dir)
1148
shutil.copyfile(desktop_file, autostart_link)
1149
elif os.path.exists(autostart_link):
1150
os.remove(autostart_link)
1155
def autostart(argv):
1156
u"""automatically start dropbox at login
1157
dropbox autostart [y/n]
1160
n dropbox will not start automatically at login
1161
y dropbox will start automatically at login (default)
1163
Note: May only work on current Ubuntu distributions.
1166
console_print(''.join(autostart.__doc__.split('\n', 1)[1:]).decode('ascii'))
1170
if s.startswith('y') or s.startswith('-y'):
1171
should_autostart = True
1172
elif s.startswith('n') or s.startswith('-n'):
1173
should_autostart = False
1175
should_autostart = None
1177
if should_autostart is None:
1178
console_print(autostart.__doc__,linebreak=False)
1180
reroll_autostart(should_autostart)
1185
dropbox help [COMMAND]
1187
With no arguments, print a list of commands and a short description of each. With a command, print descriptive help on how to use the command.
1191
for command in commands:
1192
if command == argv[0]:
1193
console_print(commands[command].__doc__.split('\n', 1)[1].decode('ascii'))
1195
for alias in aliases:
1196
if alias == argv[0]:
1197
console_print(aliases[alias].__doc__.split('\n', 1)[1].decode('ascii'))
1199
console_print(u"unknown command '%s'" % argv[0], f=sys.stderr)
1202
console_print(u"Dropbox command-line interface\n")
1203
console_print(u"commands:\n")
1204
console_print(u"Note: use dropbox help <command> to view usage for a specific command.\n")
1206
for command in commands:
1207
out.append((command, commands[command].__doc__.splitlines()[0]))
1208
spacing = max(len(o[0])+3 for o in out)
1210
console_print(" %-*s%s" % (spacing, o[0], o[1]))
1216
# now we need to find out if one of the commands are in the
1217
# argv list, and if so split the list at the point to
1218
# separate the argv list at that point
1220
for i in range(len(argv)):
1221
if argv[i] in commands or argv[i] in aliases:
1230
# lol no options for now
1231
globaloptionparser = optparse.OptionParser()
1232
globaloptionparser.parse_args(argv[0:i])
1234
# now dispatch and run
1236
if argv[i] in commands:
1237
result = commands[argv[i]](argv[i+1:])
1238
elif argv[i] in aliases:
1239
result = aliases[argv[i]](argv[i+1:])
1241
# flush, in case output is rerouted to a file.
1247
if __name__ == "__main__":
1248
ret = main(sys.argv)