├── smartcopy.egg-info
├── not-zip-safe
├── dependency_links.txt
├── requires.txt
├── top_level.txt
├── SOURCES.txt
└── PKG-INFO
├── dist
├── smartcopy-0.1.tar.gz
├── smartcopy-0.2.tar.gz
├── smartcopy-0.5.tar.gz
└── smartcopy-0.6.tar.gz
├── smartutils
├── __init__.pyc
└── __init__.py
├── .idea
├── scopes
│ └── scope_settings.xml
├── encodings.xml
├── vcs.xml
├── other.xml
├── inspectionProfiles
│ └── profiles_settings.xml
├── libraries
│ └── sass_stdlib.xml
├── misc.xml
├── testrunner.xml
├── modules.xml
├── smartcopy.iml
└── workspace.xml
├── setup.py
├── README.md
└── smartcopy
├── smartcopy
└── smartcopyd
/smartcopy.egg-info/not-zip-safe:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/smartcopy.egg-info/dependency_links.txt:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/smartcopy.egg-info/requires.txt:
--------------------------------------------------------------------------------
1 | watchdog>=0.7.1
--------------------------------------------------------------------------------
/smartcopy.egg-info/top_level.txt:
--------------------------------------------------------------------------------
1 | smartutils
2 |
--------------------------------------------------------------------------------
/dist/smartcopy-0.1.tar.gz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sarchak/smartcopy/HEAD/dist/smartcopy-0.1.tar.gz
--------------------------------------------------------------------------------
/dist/smartcopy-0.2.tar.gz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sarchak/smartcopy/HEAD/dist/smartcopy-0.2.tar.gz
--------------------------------------------------------------------------------
/dist/smartcopy-0.5.tar.gz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sarchak/smartcopy/HEAD/dist/smartcopy-0.5.tar.gz
--------------------------------------------------------------------------------
/dist/smartcopy-0.6.tar.gz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sarchak/smartcopy/HEAD/dist/smartcopy-0.6.tar.gz
--------------------------------------------------------------------------------
/smartutils/__init__.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sarchak/smartcopy/HEAD/smartutils/__init__.pyc
--------------------------------------------------------------------------------
/.idea/scopes/scope_settings.xml:
--------------------------------------------------------------------------------
1 |
48 | Shrikars-MacBook-Pro:~ shrikar$ smartcopyd
49 | Shrikars-MacBook-Pro:~ shrikar$ smartcopy
50 | /Users/shrikar/.smartcopy
51 | Starting SmartCopy Engine...
52 | smartcopy> add .*.jpg
53 | Adding this pattern to ignore path : .*.jpg
54 | smartcopy> add .*.pdf
55 | Adding this pattern to ignore path : .*.pdf
56 | smartcopy> add .*.jar
57 | Adding this pattern to ignore path : .*.jar
58 | smartcopy>
59 |
60 |
61 |
62 | The above command will create a directory called SmartCopy in your home folder feel free to drag it to the finder sidebar or where ever its convenient for you to copy files.
63 |
64 | ### Important : While syncing files DO NOT COPY OR MOVE files directly to the dropbox folder instead copy/move to SmartCopy folder which will filter the files and sync's them to the dropbox folder.
65 |
66 | [More Info](http://shrikar.com/blog/2014/02/21/smartcopy-intelligent-layer-on-top-of-existing-cloud-storage/)
67 |
--------------------------------------------------------------------------------
/smartcopy/smartcopy:
--------------------------------------------------------------------------------
1 | #! /usr/bin/python
2 |
3 | __author__ = 'shrikar'
4 | from cmd import Cmd
5 | from os.path import expanduser
6 | import os
7 | from smartutils import get_config
8 | from smartutils import get_db
9 | from smartutils import reload_config
10 | import subprocess
11 | import sys
12 | class MyPrompt(Cmd):
13 |
14 | def __init__(self):
15 | Cmd.__init__(self)
16 | self.data = []
17 | fd = open(get_db(),"r")
18 | for pattern in fd.readlines():
19 | self.data.append(pattern.strip("\n"))
20 | fd.close()
21 | self.index = 1
22 |
23 | def savefile(self):
24 | home = expanduser("~")
25 | fd = open(get_db(),"w")
26 | for pattern in self.data:
27 | fd.write(pattern+"\n")
28 | fd.close()
29 |
30 | def do_change_config(self,args):
31 | """In case you want to change the path of the location which need to be watched or the destination
32 | path use this command. Please note after this you need to restart the smartcopyd ( Smart copy daemon)."""
33 | fd = open(get_config()+".bk","w")
34 | source = raw_input("Enter local directory: ")
35 | destination = raw_input("Enter Dropbox/Box/Google mounted path: ")
36 | fd.write("source="+source+"\n")
37 | fd.write("destination="+destination+"\n")
38 | fd.close()
39 | os.system("mv "+get_config()+".bk " + get_config())
40 | os.system("pkill -f smartcopyd")
41 | print("=================================================================")
42 | print("!!!! Important information !!!!")
43 | print "Please restart the smartcopyd.\nExample : \nsmartcopyd"
44 | print("=================================================================")
45 | sys.exit(0)
46 |
47 | def do_display_config(self,args):
48 | """Displays the current source and the destination path."""
49 | src,dest = reload_config()
50 | print "Local directory : " + src
51 | print "Dropbox/Box/Google mounted path : " + dest
52 |
53 | def do_add(self, args):
54 | """Add a file pattern to be ignored."""
55 | if(args==""):
56 | print "Please provide the pattern. "
57 | print "Example: add *.jar ( For ignore any file ending with jar ) "
58 | return;
59 | print "Adding this pattern to ignore path : %s" % args
60 | self.data.append(args)
61 | self.savefile()
62 |
63 | def do_list(self,args):
64 | """List existing patterns that are ignored."""
65 | self.index = 1
66 | if(len(self.data) == 0):
67 | print "No pattern listed in the database."
68 |
69 | for pattern in self.data:
70 | print str(self.index) +" ) " + pattern
71 | self.index += 1
72 |
73 | def do_del(self,args):
74 | """Delete an existing pattern that was ignored."""
75 | if(int(args) > len(self.data)):
76 | return
77 | del self.data[int(args)-1]
78 | self.do_list(0)
79 | self.savefile()
80 |
81 | def do_quit(self, args):
82 | """Quits the program."""
83 | print "Quitting."
84 | raise SystemExit
85 |
86 |
87 | if __name__ == '__main__':
88 | home = expanduser("~")
89 | smartdir = home+"/.smartcopy"
90 | if(not os.path.exists(smartdir)):
91 | os.system("mkdir -p " + smartdir)
92 | if(not os.path.exists(get_config())):
93 | fd = open(get_config(),"w")
94 | fd.write("source="+home+"/SmartCopy\n")
95 | fd.write("destination="+home+"/Dropbox\n")
96 | fd.close()
97 | if(not os.path.exists(get_db())):
98 | subprocess.call(["touch ",get_db()])
99 |
100 | prompt = MyPrompt()
101 | prompt.prompt = 'smartcopy> '
102 | prompt.cmdloop('Starting SmartCopy Engine...')
103 |
--------------------------------------------------------------------------------
/smartcopy/smartcopyd:
--------------------------------------------------------------------------------
1 | #!/usr/bin/python
2 | import time
3 | from watchdog.observers import Observer
4 | from watchdog.events import FileSystemEventHandler
5 | import re
6 | import os
7 | import sys
8 | import subprocess
9 | from Queue import Queue
10 | from os.path import expanduser
11 | from smartutils import get_config
12 | from smartutils import get_db
13 | from smartutils import reload_config
14 | from smartutils import get_patterns
15 | from smartutils import quote
16 |
17 | class MyHandler(FileSystemEventHandler):
18 | def __init__(self,src,dest,dirstocreate,filestocopy,filestodelete):
19 | self.src = src
20 | self.dest = dest
21 | self.dirstocreate = dirstocreate
22 | self.filestocopy = filestocopy
23 | self.filestodelete = filestodelete
24 | self.patterns = re.compile(get_patterns())
25 |
26 |
27 | def on_created(self, event):
28 | ## Ignore the created event for the backup file generated
29 | ## during the change config phase
30 |
31 | if(event.src_path == get_config()+".bk"):
32 | return;
33 |
34 | ## If there is not pattern match for the files to be ignored or there are no rules
35 | ## in the database add to the files to be copied case.
36 | if len(self.patterns.findall(event.src_path)) == 0 or os.path.getsize(get_db()) == 0:
37 | if(event.is_directory):
38 | self.dirstocreate.put(event.src_path)
39 | else:
40 | self.filestocopy.put(event.src_path)
41 |
42 |
43 | def on_moved(self, event):
44 | ## Delegate to the on created
45 | self.on_created(event)
46 |
47 | def on_deleted(self, event):
48 | ## Add the file to the list of files to be deleted
49 | self.filestodelete.put(event.src_path)
50 |
51 | def on_modified(self, event):
52 | ## If the file modified is the config file. Then reload the config file
53 | if(event.src_path == get_config()):
54 | self.src,self.dest = reload_config()
55 | ## If the file modified is the db file. Then reload the patterns
56 | elif(event.src_path == get_db()):
57 | self.patterns = re.compile(get_patterns())
58 | elif(event.src_path == get_config()+".bk"):
59 | None
60 | else :
61 | self.on_created(event)
62 |
63 | def runme():
64 | src,dest = reload_config()
65 | home = expanduser("~")
66 | dirstocreate = Queue()
67 | filestocopy = Queue()
68 | filestodelete = Queue()
69 | handler = MyHandler(src,dest,dirstocreate,filestocopy,filestodelete)
70 | observer = Observer()
71 | observer.schedule(handler, path=src, recursive=True)
72 | observer.schedule(handler, path=home+"/.smartcopy/", recursive=True)
73 | observer.start()
74 |
75 | try:
76 | while True:
77 | time.sleep(1)
78 |
79 | while(not filestodelete.empty()):
80 | file = filestodelete.get()
81 | rfile = dest+file.replace(src,"")
82 | if(os.path.isfile(rfile)):
83 | subprocess.call(["rm",rfile])
84 | if(os.path.isdir(rfile) and rfile.startswith(dest)):
85 | subprocess.call(["rm","-rf",rfile])
86 |
87 | while(not dirstocreate.empty()):
88 | dir = dirstocreate.get()
89 | subprocess.call(["mkdir","-p",quote(dest+dir.replace(src,""))])
90 |
91 | while(not filestocopy.empty()):
92 | file = filestocopy.get()
93 | subprocess.call(["cp",file,dest+file.replace(src,"")])
94 |
95 |
96 | except KeyboardInterrupt:
97 | observer.stop()
98 | observer.join()
99 |
100 | if __name__ == "__main__":
101 | home = expanduser("~")
102 | smartdir = home+"/.smartcopy"
103 |
104 | try:
105 | pid = os.fork()
106 | if pid > 0:
107 | sys.exit(0)
108 | else :
109 | if(not os.path.exists(home+"/SmartCopy")):
110 | subprocess.call(["mkdir","-p",quote(home+"/SmartCopy")])
111 | if(not os.path.exists(home+"/Dropbox")):
112 | subprocess.call(["mkdir","-p",quote(home+"/Dropbox")])
113 | if(not os.path.exists(smartdir)):
114 | subprocess.call(["mkdir","-p",quote(smartdir)])
115 | if(not os.path.exists(get_config())):
116 | fd = open(get_config(),"w")
117 | fd.write("source="+home+"/SmartCopy\n")
118 | fd.write("destination="+home+"/Dropbox\n")
119 | fd.close()
120 | if(not os.path.exists(get_db())):
121 | subprocess.call(["touch",get_db()])
122 |
123 | except OSError, e:
124 | print >> sys.stderr, "fork failed: %d (%s)" % (e.errno, e.strerror)
125 | sys.exit(1)
126 |
127 | os.chdir("/")
128 | os.setsid()
129 | os.umask(0)
130 | f = open(os.devnull, 'w')
131 | sys.stdout = f
132 | sys.stderr = f
133 | runme()
134 |
135 |
136 |
137 |
--------------------------------------------------------------------------------
/.idea/workspace.xml:
--------------------------------------------------------------------------------
1 |
2 |