Contact
CoCalc Logo Icon
StoreFeaturesDocsShareSupport News AboutSign UpSign In
| Download
Views: 39535
1
fs = require('fs')
2
temp = require('temp')
3
child_process = require('child_process')
4
5
async = require('async')
6
winston = require('winston')
7
8
message = require('smc-util/message')
9
misc_node = require('smc-util-node/misc_node')
10
misc = require('smc-util/misc')
11
12
common = require('./common')
13
14
###############################################
15
# Read and write individual files
16
###############################################
17
18
# Read a file located in the given project. This will result in an
19
# error if the readFile function fails, e.g., if the file doesn't
20
# exist or the project is not open. We then send the resulting file
21
# over the socket as a blob message.
22
#
23
# Directories get sent as a ".tar.bz2" file.
24
# TODO: should support -- 'tar', 'tar.bz2', 'tar.gz', 'zip', '7z'. and mesg.archive option!!!
25
#
26
exports.read_file_from_project = (socket, mesg) ->
27
#dbg = (m) -> winston.debug("read_file_from_project(path='#{mesg.path}'): #{m}")
28
#dbg()
29
data = undefined
30
path = misc_node.abspath(mesg.path)
31
is_dir = undefined
32
id = undefined
33
archive = undefined
34
stats = undefined
35
async.series([
36
(cb) ->
37
#dbg("Determine whether the path '#{path}' is a directory or file.")
38
fs.stat path, (err, _stats) ->
39
if err
40
cb(err)
41
else
42
stats = _stats
43
is_dir = stats.isDirectory()
44
cb()
45
(cb) ->
46
# make sure the file isn't too large
47
cb(common.check_file_size(stats.size))
48
(cb) ->
49
if is_dir
50
if mesg.archive != 'tar.bz2'
51
cb("The only supported directory archive format is tar.bz2")
52
return
53
target = temp.path(suffix:'.' + mesg.archive)
54
#dbg("'#{path}' is a directory, so archive it to '#{target}', change path, and read that file")
55
archive = mesg.archive
56
if path[path.length-1] == '/' # common nuisance with paths to directories
57
path = path.slice(0,path.length-1)
58
split = misc.path_split(path)
59
path = target
60
# same patterns also in project.coffee (TODO)
61
args = ["--exclude=.sagemathcloud*", '--exclude=.forever', '--exclude=.node*', '--exclude=.npm', '--exclude=.sage', '-jcf', target, split.tail]
62
#dbg("tar #{args.join(' ')}")
63
child_process.execFile 'tar', args, {cwd:split.head}, (err, stdout, stderr) ->
64
if err
65
winston.debug("Issue creating tarball: #{err}, #{stdout}, #{stderr}")
66
cb(err)
67
else
68
cb()
69
else
70
#dbg("It is a file.")
71
cb()
72
73
(cb) ->
74
#dbg("Read the file into memory.")
75
fs.readFile path, (err, _data) ->
76
data = _data
77
cb(err)
78
79
(cb) ->
80
id = misc_node.uuidsha1(data)
81
#dbg("sha1 hash = '#{id}'")
82
cb()
83
(cb) ->
84
#dbg("send the file as a blob back to the hub.")
85
socket.write_mesg 'json', message.file_read_from_project(id:mesg.id, data_uuid:id, archive:archive)
86
socket.write_mesg 'blob', {uuid:id, blob:data}
87
cb()
88
], (err) ->
89
if err and err != 'file already known'
90
socket.write_mesg('json', message.error(id:mesg.id, error:err))
91
if is_dir
92
fs.exists path, (exists) ->
93
if exists
94
#dbg("It was a directory, so remove the temporary archive '#{path}'.")
95
fs.unlink(path)
96
)
97
98
exports.write_file_to_project = (socket, mesg) ->
99
#dbg = (m) -> winston.debug("write_file_to_project(path='#{mesg.path}'): #{m}")
100
#dbg()
101
102
data_uuid = mesg.data_uuid
103
path = misc_node.abspath(mesg.path)
104
105
# Listen for the blob containing the actual content that we will write.
106
write_file = (type, value) ->
107
if type == 'blob' and value.uuid == data_uuid
108
socket.removeListener('mesg', write_file)
109
async.series([
110
(cb) ->
111
misc_node.ensure_containing_directory_exists(path, cb)
112
(cb) ->
113
#dbg('writing the file')
114
fs.writeFile(path, value.blob, cb)
115
], (err) ->
116
if err
117
#dbg("error writing file -- #{err}")
118
socket.write_mesg 'json', message.error(id:mesg.id, error:err)
119
else
120
#dbg("wrote file '#{path}' fine")
121
socket.write_mesg 'json', message.file_written_to_project(id:mesg.id)
122
)
123
socket.on('mesg', write_file)
124
125
126