Merge lp:~mikemc/ubuntuone-client/fix-daemon-rename-event into lp:ubuntuone-client

Proposed by Mike McCracken on 2012-09-18
Status: Merged
Approved by: Roberto Alsina on 2012-09-19
Approved revision: 1316
Merged at revision: 1318
Proposed branch: lp:~mikemc/ubuntuone-client/fix-daemon-rename-event
Merge into: lp:ubuntuone-client
Diff against target: 131 lines (+41/-16)
2 files modified
tests/platform/filesystem_notifications/test_fsevents_daemon.py (+14/-7)
ubuntuone/platform/filesystem_notifications/monitor/darwin/fsevents_daemon.py (+27/-9)
To merge this branch: bzr merge lp:~mikemc/ubuntuone-client/fix-daemon-rename-event
Reviewer Review Type Date Requested Status
Roberto Alsina (community) 2012-09-18 Approve on 2012-09-19
Manuel de la Peña (community) 2012-09-18 Approve on 2012-09-19
Review via email: mp+125074@code.launchpad.net

Commit Message

- Generate MODIFY event after CREATE when we see RENAME from system into watched path. (LP: #1052713)

Description of the Change

- Generate MODIFY event after CREATE when we see RENAME from system into watched path. (LP: #1052713)

To post a comment you must log in.
Manuel de la Peña (mandel) wrote :

Good catch..

review: Approve
Roberto Alsina (ralsina) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'tests/platform/filesystem_notifications/test_fsevents_daemon.py'
2--- tests/platform/filesystem_notifications/test_fsevents_daemon.py 2012-07-23 12:26:42 +0000
3+++ tests/platform/filesystem_notifications/test_fsevents_daemon.py 2012-09-18 23:50:38 +0000
4@@ -41,6 +41,7 @@
5 from ubuntuone.platform.filesystem_notifications.pyinotify_agnostic import (
6 IN_CREATE,
7 IN_DELETE,
8+ IN_MODIFY,
9 IN_MOVED_FROM,
10 IN_MOVED_TO,
11 )
12@@ -266,7 +267,7 @@
13 self.assertEqual(event_path, pyinotify_event.pathname)
14
15 def test_convert_in_pyinotify_event_rename_create(self):
16- """Test the creation of a rename which is a create."""
17+ """Test the creation of a rename which is a create/modify pair."""
18 source_path = u'/not/watched/path'
19 destination_path = u'/watched/path'
20 head, _ = os.path.split(destination_path)
21@@ -275,12 +276,18 @@
22 event.event_type = fseventsd.FSE_RENAME
23 event.event_paths.extend([source_path, destination_path])
24 converted_events = self.factory.convert_in_pyinotify_event(event)
25- self.assertEqual(1, len(converted_events))
26- pyinotify_event = converted_events[0]
27- self.assertEqual(0, pyinotify_event.wd)
28- self.assertEqual(event.is_directory, pyinotify_event.dir)
29- self.assertEqual(IN_CREATE, pyinotify_event.mask)
30- self.assertEqual(destination_path, pyinotify_event.pathname)
31+ self.assertEqual(2, len(converted_events))
32+ pyi_create_event = converted_events[0]
33+ self.assertEqual(0, pyi_create_event.wd)
34+ self.assertEqual(event.is_directory, pyi_create_event.dir)
35+ self.assertEqual(IN_CREATE, pyi_create_event.mask)
36+ self.assertEqual(destination_path, pyi_create_event.pathname)
37+
38+ pyi_modify_event = converted_events[1]
39+ self.assertEqual(0, pyi_modify_event.wd)
40+ self.assertEqual(event.is_directory, pyi_modify_event.dir)
41+ self.assertEqual(IN_MODIFY, pyi_modify_event.mask)
42+ self.assertEqual(destination_path, pyi_modify_event.pathname)
43
44 def test_convert_in_pyinotify_event_rename_delete(self):
45 """Test the creation of a rename which is a delete."""
46
47=== modified file 'ubuntuone/platform/filesystem_notifications/monitor/darwin/fsevents_daemon.py'
48--- ubuntuone/platform/filesystem_notifications/monitor/darwin/fsevents_daemon.py 2012-08-28 14:49:39 +0000
49+++ ubuntuone/platform/filesystem_notifications/monitor/darwin/fsevents_daemon.py 2012-09-18 23:50:38 +0000
50@@ -147,8 +147,12 @@
51 self.watched_paths = []
52 self.ignored_paths = []
53
54+ self.log = logging.getLogger('ubuntuone.SyncDaemon.EventsFactory')
55+ self.log.setLevel(TRACE)
56+
57 def events_dropper(self):
58 """Deal with the fact that the daemon dropped events."""
59+ self.log.error("Event received with dropped flag set, not handled.")
60
61 def path_is_not_interesting(self, path):
62 """Return if the factory is interested in the path."""
63@@ -160,8 +164,8 @@
64
65 def is_create(self, event):
66 """Decide if a rename event should be considered a create."""
67- # is a create if the creation path (first path) is either not watched or
68- # in the ignored paths
69+ # is a create if the creation path (first path) is either not
70+ # watched or in the ignored paths
71 source_path = get_syncdaemon_valid_path(event.event_paths[0])
72 return self.path_is_not_interesting(source_path)
73
74@@ -205,7 +209,7 @@
75 'mask': mask,
76 'name': tail,
77 'cookie': cookie,
78- 'src_pathname' : source_tail,
79+ 'src_pathname': source_tail,
80 'path': '.'}
81 move_to_event = Event(event_raw_data)
82 move_to_event.pathname = destination_path
83@@ -216,8 +220,11 @@
84 # the rename is a special type of event because it has to be either
85 # converted is a pair of events or in a single one (CREATE or DELETE)
86 if event.event_type == fseventsd.FSE_RENAME:
87+
88 is_create = self.is_create(event)
89- if is_create or self.is_delete(event):
90+ is_delete = self.is_delete(event)
91+
92+ if is_create or is_delete:
93 mask = IN_CREATE if is_create else IN_DELETE
94 if event.is_directory:
95 mask |= IN_ISDIR
96@@ -236,12 +243,22 @@
97 'mask': mask,
98 'name': tail,
99 'path': '.'}
100- pyinotify_event = Event(event_raw_data)
101- pyinotify_event.pathname = path
102- return [pyinotify_event]
103+ orig_event = Event(event_raw_data)
104+ orig_event.pathname = path
105+ events = [orig_event]
106+
107+ if is_create:
108+ mod_event = Event(event_raw_data)
109+ mod_event.pathname = path
110+ mod_event.mask = IN_MODIFY
111+ if event.is_directory:
112+ mod_event.mask |= IN_ISDIR
113+ events.append(mod_event)
114+
115+ return events
116 else:
117- # we do have a rename within watched paths lets generate to
118- # fake events
119+ # we have a rename within watched paths, so let's
120+ # generate two fake events
121 cookie = str(uuid4())
122 return [self.generate_from_event(event, cookie),
123 self.generate_to_event(event, cookie)]
124@@ -282,6 +299,7 @@
125 # this should not be very common but we have to deal with it
126 return self.events_dropper()
127 events = self.convert_in_pyinotify_event(event)
128+ self.log.debug("process_event : %r => %r" % (event, events))
129 for pyinotify_event in events:
130 # assert that the path name is valid
131 if not any([pyinotify_event.pathname.startswith(path)

Subscribers

People subscribed via source and target branches