Daily checkin of rewritten code.
[guestfs-browser.git] / filetree.ml
index 0737820..0368d53 100644 (file)
@@ -48,11 +48,11 @@ and state_t =
   | NodeNotStarted   (* user has not tried to open this *)
   | NodeLoading      (* user tried to open it, still loading *)
   | IsNode           (* we've loaded the children of this directory *)
-  | Loading          (* special row contains the "Loading ..." message *)
 
 (* The actual content of a row. *)
 and content_t =
-  | NoContent
+  | Loading                          (* special "loading ..." node *)
+  | ErrorMessage of string           (* error message node *)
   | Top of Slave.source              (* top level OS or volume node *)
   | Directory of Slave.direntry      (* a directory *)
   | File of Slave.direntry           (* a file inc. special files *)
@@ -95,7 +95,7 @@ let create ~packing () =
 
   let renderer = GTree.cell_renderer_text [], ["markup", name_col] in
   let name_view = GTree.view_column ~title:"Filename" ~renderer () in
-  name_view#set_max_width 400 (*pixels?!?*);
+  name_view#set_max_width 300 (*pixels?!?*);
   ignore (view#append_column name_view);
 
   let renderer = GTree.cell_renderer_text [], ["text", size_col] in
@@ -219,13 +219,19 @@ let rec add ({ model = model; hash = hash } as t) name data =
   List.iter (add_top_level_os t name) data.Slave.insp_oses;
 
   (* Add top level left-over filesystems. *)
-  DeviceSet.iter (add_top_level_vol t name) other_filesystems
+  DeviceSet.iter (add_top_level_vol t name) other_filesystems;
+
+  (* Expand the first top level node. *)
+  match model#get_iter_first with
+  | None -> ()
+  | Some row ->
+      t.view#expand_row (model#get_path row)
 
 and add_top_level_os ({ model = model; hash = hash } as t) name os =
   let markup =
-    sprintf "<b>%s</b>: %s (%s)"
-      (markup_of_name name) (markup_of_name os.Slave.insp_hostname)
-      (markup_of_name os.Slave.insp_product_name) in
+    sprintf "<b>%s</b>\n<small>%s</small>\n<small>%s</small>"
+      (markup_escape name) (markup_escape os.Slave.insp_hostname)
+      (markup_escape os.Slave.insp_product_name) in
 
   let row = model#append () in
   make_node t row (Top (Slave.OS os));
@@ -233,7 +239,7 @@ and add_top_level_os ({ model = model; hash = hash } as t) name os =
 
 and add_top_level_vol ({ model = model; hash = hash } as t) name dev =
   let markup =
-    sprintf "<b>%s</b>: %s" (markup_of_name name) (markup_of_name dev) in
+    sprintf "<b>%s: %s</b>" (markup_escape name) (markup_escape dev) in
 
   let row = model#append () in
   make_node t row (Top (Slave.Volume dev));
@@ -248,7 +254,7 @@ and make_node ({ model = model; hash = hash } as t) row content =
    * the user has something to expand.
    *)
   let placeholder = model#append ~parent:row () in
-  let hdata = Loading, NoContent in
+  let hdata = IsLeaf, Loading in
   store_hdata t placeholder hdata;
   model#set ~row:placeholder ~column:t.name_col loading_msg;
   ignore (t.view#connect#row_expanded ~callback:(expand_row t))
@@ -270,7 +276,8 @@ and expand_row ({ model = model; hash = hash } as t) row _ =
       (* Get a stable path for this row. *)
       let path = model#get_path row in
 
-      Slave.read_directory src "/" (when_read_directory t path)
+      Slave.read_directory ~fail:(when_read_directory_fail t path)
+        src "/" (when_read_directory t path)
 
   | NodeNotStarted, Directory direntry ->
       (* User has opened a filesystem directory not previously opened. *)
@@ -284,15 +291,16 @@ and expand_row ({ model = model; hash = hash } as t) row _ =
 
       let src, pathname = get_pathname t row in
 
-      Slave.read_directory src pathname (when_read_directory t path)
+      Slave.read_directory ~fail:(when_read_directory_fail t path)
+        src pathname (when_read_directory t path)
 
   | NodeLoading, _ | IsNode, _ -> ()
 
   (* These are not nodes so it should never be possible to open them. *)
-  | _, File _ | IsLeaf, _ | Loading, _ -> assert false
+  | _, File _ | IsLeaf, _ -> assert false
 
-  (* Should not exist in the tree. *)
-  | NodeNotStarted, NoContent -> assert false
+  (* Node should not exist in the tree. *)
+  | NodeNotStarted, (Loading | ErrorMessage _) -> assert false
 
 (* Search up to the top of the tree so we know if this directory
  * comes from an OS or a volume, and the full path to here.
@@ -308,9 +316,9 @@ and get_pathname ({ model = model } as t) row =
   let parent = model#iter_parent row in
 
   match hdata, parent with
-  | (Loading, NoContent), Some parent ->
+  | (IsLeaf, Loading), Some parent ->
       get_pathname t parent
-  | (Loading, NoContent), None ->
+  | (IsLeaf, Loading), None ->
       assert false
   | (_, Directory { Slave.dent_name = name }), Some parent
   | (_, File { Slave.dent_name = name }), Some parent ->
@@ -320,8 +328,10 @@ and get_pathname ({ model = model } as t) row =
         else parent_name ^ "/" ^ name in
       src, path
   | (_, Top src), _ -> src, "/"
-  | (_, Directory _), None | (_, File _), None -> assert false
-  | (_, NoContent), _ -> assert false
+  | (_, Directory _), None -> assert false
+  | (_, File _), None -> assert false
+  | (_, Loading), _ -> assert false
+  | (_, ErrorMessage _), _ -> assert false
 
 (* This is the callback when the slave has read the directory for us. *)
 and when_read_directory ({ model = model } as t) path entries =
@@ -361,3 +371,24 @@ and when_read_directory ({ model = model } as t) path entries =
   let state, content = get_hdata t row in
   let hdata = IsNode, content in
   store_hdata t row hdata
+
+(* This is called instead of when_read_directory when the read directory
+ * (or mount etc) failed.  Convert the "Loading" entry into the
+ * error message.
+ *)
+and when_read_directory_fail ({ model = model } as t) path exn =
+  debug "when_read_directory_fail: %s" (Printexc.to_string exn);
+
+  match exn with
+  | G.Error msg ->
+      let row = model#get_iter path in
+      let row = model#iter_children ~nth:0 (Some row) in
+
+      let hdata = IsLeaf, ErrorMessage msg in
+      store_hdata t row hdata;
+
+      model#set ~row ~column:t.name_col (markup_escape msg)
+
+  | exn ->
+      (* unexpected exception: re-raise it *)
+      raise exn