func doInstall(s *state.State, curActive bool, snapName, snapPath, channel string, userID int, flags snappy.InstallFlags) (*state.TaskSet, error) { if err := checkChangeConflict(s, snapName); err != nil { return nil, err } if snapPath == "" && channel == "" { channel = "stable" } var prepare *state.Task ss := SnapSetup{ Channel: channel, UserID: userID, Flags: int(flags), } ss.Name = snapName ss.SnapPath = snapPath if snapPath != "" { prepare = s.NewTask("prepare-snap", fmt.Sprintf(i18n.G("Prepare snap %q"), snapPath)) } else { prepare = s.NewTask("download-snap", fmt.Sprintf(i18n.G("Download snap %q from channel %q"), snapName, channel)) } prepare.Set("snap-setup", ss) tasks := []*state.Task{prepare} addTask := func(t *state.Task) { t.Set("snap-setup-task", prepare.ID()) tasks = append(tasks, t) } // mount mount := s.NewTask("mount-snap", fmt.Sprintf(i18n.G("Mount snap %q"), snapName)) addTask(mount) mount.WaitFor(prepare) precopy := mount if curActive { // unlink-current-snap (will stop services for copy-data) unlink := s.NewTask("unlink-current-snap", fmt.Sprintf(i18n.G("Make current revision for snap %q unavailable"), snapName)) addTask(unlink) unlink.WaitFor(mount) precopy = unlink } // copy-data (needs stopped services by unlink) copyData := s.NewTask("copy-snap-data", fmt.Sprintf(i18n.G("Copy snap %q data"), snapName)) addTask(copyData) copyData.WaitFor(precopy) // security setupSecurity := s.NewTask("setup-profiles", fmt.Sprintf(i18n.G("Setup snap %q security profiles"), snapName)) addTask(setupSecurity) setupSecurity.WaitFor(copyData) // finalize (wrappers+current symlink) linkSnap := s.NewTask("link-snap", fmt.Sprintf(i18n.G("Make snap %q available to the system"), snapName)) addTask(linkSnap) linkSnap.WaitFor(setupSecurity) return state.NewTaskSet(tasks...), nil }