Play

Check-in [3485ad3ca9]
Login
Overview
Comment:Refactor model of PackageLoader.
Timelines: family | ancestors | modules
Files: files | file ages | folders
SHA3-256: 3485ad3ca9a18fac9c4e08ae7ff1b12351a0e0dd4d7d87c6e86377a0469ce8f3
User & Date: robin.hansen on 2021-02-25 14:55:48
Other Links: branch diff | manifest | tags
Context
2021-02-25
14:55
Refactor model of PackageLoader. Leaf check-in: 3485ad3ca9 user: robin.hansen tags: modules
2021-02-21
10:51
Implement function to check compatibility between semver versions. check-in: eb5381534d user: robin.hansen tags: modules
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Modified src/Play/PackageLoader.elm from [510bc0213d] to [62165525df].

1
2
3
4
5
6
7
8
9
10
11
12
13
..
17
18
19
20
21
22
23

24
25
26
27
28
29
30
31
32
33
34
35

36
37
38

39






40
41
42
43
44

45

46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68






























69
70

71
72
73
74


75




76
77
78
79
80
81
82
83
84
85
86
87

88

89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
module Play.PackageLoader exposing
    ( Model
    , Msg(..)
    , Problem
    , SideEffect(..)
    , doneState
    , init
    , update
    )

import Dict exposing (Dict)
import Json.Decode as Json
import List.Extra as List
................................................................................


type Problem
    = InvalidPackageMetadata String String


type Model

    = LoadingMetadata State (List PackagePath)
    | Done State


doneState : Model -> Maybe State
doneState model =
    case model of
        Done state ->
            Just state

        _ ->
            Nothing



type alias State =

    { loadedPackages : Dict String PackageMetadata






    }


emptyState : State
emptyState =

    { loadedPackages = Dict.empty }



type Msg
    = FileContents String String String
    | ResolvedDirectories String (List PackagePath)


type SideEffect
    = NoOp
    | ReadFile String String
    | ResolveDirectories String


init : String -> ( Model, SideEffect )
init projectDirPath =
    ( LoadingMetadata emptyState [ PackagePath.Directory projectDirPath ]
    , ReadFile projectDirPath "play.json"
    )


update : Msg -> Model -> ( Model, SideEffect )
update msg model =
    case model of






























        Done _ ->
            ( model, NoOp )


        LoadingMetadata state remainingPaths ->
            loadingMetadataUpdate msg state remainingPaths








loadingMetadataUpdate : Msg -> State -> List PackagePath -> ( Model, SideEffect )
loadingMetadataUpdate msg state remainingPaths =
    case msg of
        FileContents path _ content ->
            case Json.decodeString PackageMetadata.decoder content of
                Ok metadata ->
                    let
                        updatedState =
                            { state
                                | loadedPackages =
                                    Dict.insert
                                        (PackageName.toString metadata.name)

                                        metadata

                                        state.loadedPackages
                            }

                        absolutePackagePaths =
                            List.map (PackagePath.prefix path) metadata.packagePaths

                        pathsToLoad =
                            remainingPaths
                                |> List.remove (PackagePath.Directory path)
                                |> (++) absolutePackagePaths
                    in
                    case pathsToLoad of
                        [] ->
                            ( Done updatedState, NoOp )

                        (PackagePath.Directory nextPathDir) :: _ ->
                            ( LoadingMetadata updatedState pathsToLoad
                            , ReadFile nextPathDir "play.json"
                            )

                        (PackagePath.AllDirectoriesInDirectory nextPathDir) :: _ ->
                            ( LoadingMetadata updatedState pathsToLoad
                            , ResolveDirectories nextPathDir
                            )

                Err err ->
                    Debug.todo (Json.errorToString err)

        ResolvedDirectories parentDir paths ->
            let
                pathsToLoad =
                    remainingPaths
                        |> List.remove (PackagePath.AllDirectoriesInDirectory parentDir)
                        |> (++) paths
            in
            case pathsToLoad of
                [] ->
                    ( Done state, NoOp )

                (PackagePath.Directory nextPathDir) :: _ ->
                    ( LoadingMetadata state pathsToLoad
                    , ReadFile nextPathDir "play.json"
                    )

                (PackagePath.AllDirectoriesInDirectory nextPathDir) :: _ ->
                    ( LoadingMetadata state pathsToLoad
                    , ResolveDirectories <| parentDir ++ "/" ++ nextPathDir
                    )

|

|

<







 







>
|

<
<
<
<
<
<
<
<
<
<
>



>
|
>
>
>
>
>
>



|
|
>
|
>








<
|



|

|
|
|

<
|


>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
<
>

|


>
>

>
>
>
>
|








|


>
|
>
|












|


|
|
|
<

|
|
<













|


|
|
|
<

|
|
<
1
2
3
4
5

6
7
8
9
10
11
12
..
16
17
18
19
20
21
22
23
24
25










26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

54
55
56
57
58
59
60
61
62
63

64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97

98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143

144
145
146

147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165

166
167
168

module Play.PackageLoader exposing
    ( Model(..)
    , Msg(..)
    , Problem(..)
    , SideEffect(..)

    , init
    , update
    )

import Dict exposing (Dict)
import Json.Decode as Json
import List.Extra as List
................................................................................


type Problem
    = InvalidPackageMetadata String String


type Model
    = Initializing SideEffect
    | LoadingMetadata State (List PackagePath) SideEffect
    | Done State










    | Failed Problem


type alias State =
    { rootPackage : PackageInfo
    , dependentPackages : Dict String PackageInfo
    }


type alias PackageInfo =
    { path : String
    , metadata : PackageMetadata
    }


emptyState : PackageInfo -> State
emptyState rootPackage =
    { rootPackage = rootPackage
    , dependentPackages = Dict.empty
    }


type Msg
    = FileContents String String String
    | ResolvedDirectories String (List PackagePath)


type SideEffect

    = ReadFile String String
    | ResolveDirectories String


init : String -> Model
init projectDirPath =
    Initializing
        (ReadFile projectDirPath "play.json")



update : Msg -> Model -> Model
update msg model =
    case model of
        Initializing _ ->
            case msg of
                FileContents path _ content ->
                    case Json.decodeString PackageMetadata.decoder content of
                        Ok metadata ->
                            let
                                state =
                                    emptyState
                                        { path = path
                                        , metadata = metadata
                                        }

                                pathsToLoad =
                                    List.map (PackagePath.prefix path) metadata.packagePaths
                            in
                            case pathsToLoad of
                                [] ->
                                    Done state

                                (PackagePath.Directory nextPathDir) :: _ ->
                                    LoadingMetadata state pathsToLoad <|
                                        ReadFile nextPathDir "play.json"

                                (PackagePath.AllDirectoriesInDirectory nextPathDir) :: _ ->
                                    LoadingMetadata state pathsToLoad <|
                                        ResolveDirectories nextPathDir

                        Err err ->
                            Failed <| InvalidPackageMetadata path <| Json.errorToString err

                _ ->

                    Failed (InvalidPackageMetadata "todo: path" "Wrong message on initialization")

        LoadingMetadata state remainingPaths _ ->
            loadingMetadataUpdate msg state remainingPaths

        Done _ ->
            model

        Failed _ ->
            model


loadingMetadataUpdate : Msg -> State -> List PackagePath -> Model
loadingMetadataUpdate msg state remainingPaths =
    case msg of
        FileContents path _ content ->
            case Json.decodeString PackageMetadata.decoder content of
                Ok metadata ->
                    let
                        updatedState =
                            { state
                                | dependentPackages =
                                    Dict.insert
                                        (PackageName.toString metadata.name)
                                        { path = path
                                        , metadata = metadata
                                        }
                                        state.dependentPackages
                            }

                        absolutePackagePaths =
                            List.map (PackagePath.prefix path) metadata.packagePaths

                        pathsToLoad =
                            remainingPaths
                                |> List.remove (PackagePath.Directory path)
                                |> (++) absolutePackagePaths
                    in
                    case pathsToLoad of
                        [] ->
                            Done updatedState

                        (PackagePath.Directory nextPathDir) :: _ ->
                            LoadingMetadata updatedState pathsToLoad <|
                                ReadFile nextPathDir "play.json"


                        (PackagePath.AllDirectoriesInDirectory nextPathDir) :: _ ->
                            LoadingMetadata updatedState pathsToLoad <|
                                ResolveDirectories nextPathDir


                Err err ->
                    Debug.todo (Json.errorToString err)

        ResolvedDirectories parentDir paths ->
            let
                pathsToLoad =
                    remainingPaths
                        |> List.remove (PackagePath.AllDirectoriesInDirectory parentDir)
                        |> (++) paths
            in
            case pathsToLoad of
                [] ->
                    Done state

                (PackagePath.Directory nextPathDir) :: _ ->
                    LoadingMetadata state pathsToLoad <|
                        ReadFile nextPathDir "play.json"


                (PackagePath.AllDirectoriesInDirectory nextPathDir) :: _ ->
                    LoadingMetadata state pathsToLoad <|
                        ResolveDirectories (parentDir ++ "/" ++ nextPathDir)

Modified tests/Test/PackageLoader.elm from [6452199eaa] to [5f7b23a79d].

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
..
65
66
67
68
69
70
71




72
73










74
75
76
77
78
79
80

suite : Test
suite =
    describe "PackageLoader"
        [ test "Passes the load package metadata step" <|
            \_ ->
                PackageLoader.init "/project"
                    |> Tuple.second
                    |> Expect.equal (PackageLoader.ReadFile "/project" "play.json")
        , test "Retrieves necessary files" <|
            \_ ->
                PackageLoader.init "/project"
                    |> expectSideEffects testFiles
                        [ PackageLoader.ReadFile "/project" "play.json"
                        , PackageLoader.ResolveDirectories "/project/lib"
                        , PackageLoader.ReadFile "/project/lib/template_strings" "play.json"
                        ]
        ]


expectSideEffects : Dict String String -> List PackageLoader.SideEffect -> ( PackageLoader.Model, PackageLoader.SideEffect ) -> Expectation
expectSideEffects fileSystem expectedSFs ( model, sideEffect ) =
    case PackageLoader.doneState model of
        Just _ ->
            Expect.equalLists [] expectedSFs

        Nothing ->
            case sideEffect of
                PackageLoader.ReadFile path filename ->
                    case Dict.get (path ++ "/" ++ filename) fileSystem of
                        Just fileContent ->
                            expectSideEffects
                                fileSystem
                                (List.remove sideEffect expectedSFs)
................................................................................
                        fileSystem
                        (List.remove sideEffect expectedSFs)
                        (PackageLoader.update
                            (PackageLoader.ResolvedDirectories dir childPaths)
                            model
                        )





                PackageLoader.NoOp ->
                    Expect.fail "Did not expect NoOp message."












testFiles : Dict String String
testFiles =
    Dict.fromList
        [ ( "/project/play.json"
          , """







<
|











|
|
|
|


|







 







>
>
>
>
|
<
>
>
>
>
>
>
>
>
>
>







10
11
12
13
14
15
16

17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
..
64
65
66
67
68
69
70
71
72
73
74
75

76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92

suite : Test
suite =
    describe "PackageLoader"
        [ test "Passes the load package metadata step" <|
            \_ ->
                PackageLoader.init "/project"

                    |> Expect.equal (PackageLoader.Initializing <| PackageLoader.ReadFile "/project" "play.json")
        , test "Retrieves necessary files" <|
            \_ ->
                PackageLoader.init "/project"
                    |> expectSideEffects testFiles
                        [ PackageLoader.ReadFile "/project" "play.json"
                        , PackageLoader.ResolveDirectories "/project/lib"
                        , PackageLoader.ReadFile "/project/lib/template_strings" "play.json"
                        ]
        ]


expectSideEffects : Dict String String -> List PackageLoader.SideEffect -> PackageLoader.Model -> Expectation
expectSideEffects fileSystem expectedSFs model =
    case getSideEffect model of
        Nothing ->
            Expect.equalLists [] expectedSFs

        Just sideEffect ->
            case sideEffect of
                PackageLoader.ReadFile path filename ->
                    case Dict.get (path ++ "/" ++ filename) fileSystem of
                        Just fileContent ->
                            expectSideEffects
                                fileSystem
                                (List.remove sideEffect expectedSFs)
................................................................................
                        fileSystem
                        (List.remove sideEffect expectedSFs)
                        (PackageLoader.update
                            (PackageLoader.ResolvedDirectories dir childPaths)
                            model
                        )


getSideEffect : PackageLoader.Model -> Maybe PackageLoader.SideEffect
getSideEffect model =
    case model of
        PackageLoader.Done _ ->

            Nothing

        PackageLoader.Failed _ ->
            Nothing

        PackageLoader.Initializing sf ->
            Just sf

        PackageLoader.LoadingMetadata _ _ sf ->
            Just sf


testFiles : Dict String String
testFiles =
    Dict.fromList
        [ ( "/project/play.json"
          , """